metro/scripts/build.js

151 lines
4.5 KiB
JavaScript
Raw Normal View History

2017-01-26 12:56:40 +00:00
/**
* Copyright (c) 2014, Facebook, Inc. All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
/**
* script to build (transpile) files.
* By default it transpiles all files for all packages and writes them
* into `build/` directory.
* Non-js or files matching IGNORE_PATTERN will be copied without transpiling.
*
* Example:
* node ./scripts/build.js
* node ./scripts/build.js /user/c/metro-bundler/packages/metro-abc/src/abc.js
*/
const fs = require('fs');
2017-05-22 10:51:24 +00:00
const path = require('path');
2017-01-26 12:56:40 +00:00
const glob = require('glob');
2017-05-22 10:51:24 +00:00
const mkdirp = require('mkdirp');
const babel = require('babel-core');
const chalk = require('chalk');
2017-01-26 12:56:40 +00:00
const micromatch = require('micromatch');
2017-05-22 10:51:24 +00:00
const getPackages = require('./_getPackages');
2017-01-26 12:56:40 +00:00
const SRC_DIR = 'src';
2017-05-22 10:51:24 +00:00
const BUILD_DIR = 'build';
const BUILD_ES5_DIR = 'build-es5';
2017-01-26 12:56:40 +00:00
const JS_FILES_PATTERN = '**/*.js';
const IGNORE_PATTERN = '**/__tests__/**';
const PACKAGES_DIR = path.resolve(__dirname, '../packages');
2017-05-22 10:51:24 +00:00
const babelNodeOptions = JSON.parse(
fs.readFileSync(path.resolve(__dirname, '..', '.babelrc'), 'utf8')
);
babelNodeOptions.babelrc = false;
const babelEs5Options = Object.assign(
{},
babelNodeOptions,
{presets: 'env'},
{plugins: [...babelNodeOptions.plugins, 'transform-runtime']}
);
2017-01-26 12:56:40 +00:00
const fixedWidth = str => {
const WIDTH = 80;
const strs = str.match(new RegExp(`(.{1,${WIDTH}})`, 'g'));
let lastString = strs[strs.length - 1];
if (lastString.length < WIDTH) {
lastString += Array(WIDTH - lastString.length).join(chalk.dim('.'));
}
return strs.slice(0, -1).concat(lastString).join('\n');
};
2017-05-22 10:51:24 +00:00
function getPackageName(file) {
return path.relative(PACKAGES_DIR, file).split(path.sep)[0];
}
function getBuildPath(file, buildFolder) {
const pkgName = getPackageName(file);
const pkgSrcPath = path.resolve(PACKAGES_DIR, pkgName, SRC_DIR);
const pkgBuildPath = path.resolve(PACKAGES_DIR, pkgName, buildFolder);
const relativeToSrcPath = path.relative(pkgSrcPath, file);
return path.resolve(pkgBuildPath, relativeToSrcPath);
}
2017-01-26 12:56:40 +00:00
function buildPackage(p) {
const srcDir = path.resolve(p, SRC_DIR);
const pattern = path.resolve(srcDir, '**/*');
const files = glob.sync(pattern, {nodir: true});
2017-05-22 10:51:24 +00:00
process.stdout.write(fixedWidth(`${path.basename(p)}\n`));
2017-01-26 12:56:40 +00:00
files.forEach(file => buildFile(file, true));
process.stdout.write(`[ ${chalk.green('OK')} ]\n`);
}
function buildFile(file, silent) {
2017-05-22 10:51:24 +00:00
buildFileFor(file, silent, 'node');
const pkgJsonPath = path.resolve(
PACKAGES_DIR,
getPackageName(file),
'package.json'
);
const {browser} = require(pkgJsonPath);
if (browser) {
if (browser.indexOf(BUILD_ES5_DIR) !== 0) {
throw new Error(
`browser field for ${pkgJsonPath} should start with "${BUILD_ES5_DIR}"`
);
}
buildFileFor(file, silent, 'es5');
}
}
function buildFileFor(file, silent, env) {
const buildDir = env === 'es5' ? BUILD_ES5_DIR : BUILD_DIR;
const destPath = getBuildPath(file, buildDir);
const babelOptions = env === 'es5' ? babelEs5Options : babelNodeOptions;
2017-01-26 12:56:40 +00:00
2017-05-22 10:51:24 +00:00
mkdirp.sync(path.dirname(destPath));
2017-01-26 12:56:40 +00:00
if (micromatch.isMatch(file, IGNORE_PATTERN)) {
2017-05-22 10:51:24 +00:00
silent ||
process.stdout.write(
chalk.dim(' \u2022 ') +
path.relative(PACKAGES_DIR, file) +
' (ignore)\n'
);
2017-01-26 12:56:40 +00:00
} else if (!micromatch.isMatch(file, JS_FILES_PATTERN)) {
fs.createReadStream(file).pipe(fs.createWriteStream(destPath));
2017-05-22 10:51:24 +00:00
silent ||
process.stdout.write(
chalk.red(' \u2022 ') +
path.relative(PACKAGES_DIR, file) +
chalk.red(' \u21D2 ') +
path.relative(PACKAGES_DIR, destPath) +
' (copy)' +
'\n'
);
2017-01-26 12:56:40 +00:00
} else {
const transformed = babel.transformFileSync(file, babelOptions).code;
fs.writeFileSync(destPath, transformed);
2017-06-01 17:07:31 +00:00
if (/\@flow/.test(fs.readFileSync(file))) {
fs.createReadStream(file).pipe(fs.createWriteStream(destPath + '.flow'));
}
2017-05-22 10:51:24 +00:00
silent ||
process.stdout.write(
chalk.green(' \u2022 ') +
path.relative(PACKAGES_DIR, file) +
chalk.green(' \u21D2 ') +
path.relative(PACKAGES_DIR, destPath) +
'\n'
);
2017-01-26 12:56:40 +00:00
}
}
const files = process.argv.slice(2);
if (files.length) {
files.forEach(buildFile);
} else {
process.stdout.write(chalk.bold.inverse('Building packages\n'));
getPackages().forEach(buildPackage);
process.stdout.write('\n');
}