mirror of https://github.com/status-im/metro.git
Add support for JSON files to `js_file` rule
Reviewed By: cpojer Differential Revision: D3981152 fbshipit-source-id: 94b5018a1afa27c635ddff5e26c1ff2bed09baf9
This commit is contained in:
parent
dc0f7875c8
commit
506604c5bb
|
@ -10,24 +10,82 @@
|
||||||
|
|
||||||
// RUNS UNTRANSFORMED IN A WORKER PROCESS. ONLY USE NODE 4 COMPATIBLE FEATURES!
|
// RUNS UNTRANSFORMED IN A WORKER PROCESS. ONLY USE NODE 4 COMPATIBLE FEATURES!
|
||||||
|
|
||||||
const fs = require('fs');
|
|
||||||
const dirname = require('path').dirname;
|
|
||||||
|
|
||||||
const babel = require('babel-core');
|
const babel = require('babel-core');
|
||||||
const generate = require('babel-generator').default;
|
const babelGenerate = require('babel-generator').default;
|
||||||
|
const collectDependencies = require('../JSTransformer/worker/collect-dependencies');
|
||||||
|
const constantFolding = require('../JSTransformer/worker/constant-folding').plugin;
|
||||||
|
const docblock = require('../node-haste/DependencyGraph/docblock');
|
||||||
|
const fs = require('fs');
|
||||||
|
const inline = require('../JSTransformer/worker/inline').plugin;
|
||||||
|
const minify = require('../JSTransformer/worker/minify');
|
||||||
const mkdirp = require('mkdirp');
|
const mkdirp = require('mkdirp');
|
||||||
|
const path = require('path');
|
||||||
const series = require('async/series');
|
const series = require('async/series');
|
||||||
const sourceMap = require('source-map');
|
const sourceMap = require('source-map');
|
||||||
|
|
||||||
const collectDependencies = require('../JSTransformer/worker/collect-dependencies');
|
const basename = path.basename;
|
||||||
const constantFolding = require('../JSTransformer/worker/constant-folding').plugin;
|
const dirname = path.dirname;
|
||||||
const inline = require('../JSTransformer/worker/inline').plugin;
|
const defaultVariants = {default: {}};
|
||||||
const minify = require('../JSTransformer/worker/minify');
|
const moduleFactoryParameters = ['require', 'module', 'global', 'exports'];
|
||||||
|
|
||||||
const docblock = require('../node-haste/DependencyGraph/docblock');
|
function transformJSON(infile, options, outfile, callback) {
|
||||||
|
let json, value;
|
||||||
|
try {
|
||||||
|
json = fs.readFileSync(infile, 'utf8');
|
||||||
|
value = JSON.parse(json);
|
||||||
|
} catch (readError) {
|
||||||
|
callback(readError);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const filename = options.filename || infile;
|
||||||
|
const code =
|
||||||
|
`__d(function(${moduleFactoryParameters.join(', ')}) { module.exports = \n${
|
||||||
|
json
|
||||||
|
}\n})`;
|
||||||
|
|
||||||
|
const moduleData = {
|
||||||
|
code,
|
||||||
|
map: null, // no source map for JSON files!
|
||||||
|
dependencies: [],
|
||||||
|
};
|
||||||
|
const transformed = {};
|
||||||
|
|
||||||
|
Object
|
||||||
|
.keys(options.variants || defaultVariants)
|
||||||
|
.forEach(key => (transformed[key] = moduleData));
|
||||||
|
|
||||||
|
const result = {
|
||||||
|
file: filename,
|
||||||
|
code: json,
|
||||||
|
transformed,
|
||||||
|
hasteID: value.name,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (basename(filename) === 'package.json') {
|
||||||
|
result.package = {
|
||||||
|
name: value.name,
|
||||||
|
browser: value.browser,
|
||||||
|
'react-native': value['react-native'],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
writeResult(outfile, result);
|
||||||
|
} catch (writeError) {
|
||||||
|
callback(writeError);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(null);
|
||||||
|
}
|
||||||
|
|
||||||
function transformModule(infile, options, outfile, callback) {
|
function transformModule(infile, options, outfile, callback) {
|
||||||
|
const filename = options.filename || infile;
|
||||||
|
if (filename.endsWith('.json')) {
|
||||||
|
return transformJSON(infile, options, outfile, callback);
|
||||||
|
}
|
||||||
|
|
||||||
let code, transform;
|
let code, transform;
|
||||||
try {
|
try {
|
||||||
transform = require(options.transform);
|
transform = require(options.transform);
|
||||||
|
@ -37,9 +95,7 @@ function transformModule(infile, options, outfile, callback) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const filename = options.filename || infile;
|
const variants = options.variants || defaultVariants;
|
||||||
const variants = options.variants || {default: {}};
|
|
||||||
|
|
||||||
const tasks = {};
|
const tasks = {};
|
||||||
Object.keys(variants).forEach(name => {
|
Object.keys(variants).forEach(name => {
|
||||||
tasks[name] = cb => transform({
|
tasks[name] = cb => transform({
|
||||||
|
@ -111,26 +167,18 @@ function makeResult(ast, filename, sourceCode) {
|
||||||
const dependencies = collectDependencies(ast);
|
const dependencies = collectDependencies(ast);
|
||||||
const file = wrapModule(ast);
|
const file = wrapModule(ast);
|
||||||
|
|
||||||
const gen = generate(file, {
|
const gen = generate(file, filename, sourceCode);
|
||||||
comments: false,
|
|
||||||
compact: true,
|
|
||||||
filename,
|
|
||||||
sourceMaps: true,
|
|
||||||
sourceMapTarget: filename,
|
|
||||||
sourceFileName: filename,
|
|
||||||
}, sourceCode);
|
|
||||||
return {code: gen.code, map: gen.map, dependencies};
|
return {code: gen.code, map: gen.map, dependencies};
|
||||||
}
|
}
|
||||||
|
|
||||||
function wrapModule(file) {
|
function wrapModule(file) {
|
||||||
const p = file.program;
|
const p = file.program;
|
||||||
const t = babel.types;
|
const t = babel.types;
|
||||||
const factory = t.functionExpression(t.identifier(''), [
|
const factory = t.functionExpression(
|
||||||
t.identifier('require'),
|
t.identifier(''),
|
||||||
t.identifier('module'),
|
moduleFactoryParameters.map(makeIdentifier),
|
||||||
t.identifier('global'),
|
t.blockStatement(p.body, p.directives),
|
||||||
t.identifier('exports')
|
);
|
||||||
], t.blockStatement(p.body, p.directives));
|
|
||||||
const def = t.callExpression(t.identifier('__d'), [factory]);
|
const def = t.callExpression(t.identifier('__d'), [factory]);
|
||||||
return t.file(t.program([t.expressionStatement(def)]));
|
return t.file(t.program([t.expressionStatement(def)]));
|
||||||
}
|
}
|
||||||
|
@ -142,18 +190,42 @@ function optimize(transformed, file, originalCode, options) {
|
||||||
const dependencies = collectDependencies.forOptimization(
|
const dependencies = collectDependencies.forOptimization(
|
||||||
optimized.ast, transformed.dependencies);
|
optimized.ast, transformed.dependencies);
|
||||||
|
|
||||||
const gen = generate(optimized.ast, {
|
const inputMap = transformed.map;
|
||||||
|
const gen = generate(optimized.ast, file, originalCode);
|
||||||
|
|
||||||
|
const min = minify(
|
||||||
|
file,
|
||||||
|
gen.code,
|
||||||
|
inputMap && mergeSourceMaps(file, inputMap, gen.map),
|
||||||
|
);
|
||||||
|
return {code: min.code, map: inputMap && min.map, dependencies};
|
||||||
|
}
|
||||||
|
|
||||||
|
function optimizeCode(code, map, filename, options) {
|
||||||
|
const inlineOptions = Object.assign({isWrapped: true}, options);
|
||||||
|
return babel.transform(code, {
|
||||||
|
plugins: [[constantFolding], [inline, inlineOptions]],
|
||||||
|
babelrc: false,
|
||||||
|
code: false,
|
||||||
|
filename,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function generate(ast, filename, sourceCode) {
|
||||||
|
return babelGenerate(ast, {
|
||||||
comments: false,
|
comments: false,
|
||||||
compact: true,
|
compact: true,
|
||||||
filename: file,
|
filename,
|
||||||
|
sourceFileName: filename,
|
||||||
sourceMaps: true,
|
sourceMaps: true,
|
||||||
sourceMapTarget: file,
|
sourceMapTarget: filename,
|
||||||
sourceFileName: file,
|
}, sourceCode);
|
||||||
}, originalCode);
|
}
|
||||||
|
|
||||||
|
function mergeSourceMaps(file, originalMap, secondMap) {
|
||||||
const merged = new sourceMap.SourceMapGenerator();
|
const merged = new sourceMap.SourceMapGenerator();
|
||||||
const inputMap = new sourceMap.SourceMapConsumer(transformed.map);
|
const inputMap = new sourceMap.SourceMapConsumer(originalMap);
|
||||||
new sourceMap.SourceMapConsumer(gen.map)
|
new sourceMap.SourceMapConsumer(secondMap)
|
||||||
.eachMapping(mapping => {
|
.eachMapping(mapping => {
|
||||||
const original = inputMap.originalPositionFor({
|
const original = inputMap.originalPositionFor({
|
||||||
line: mapping.originalLine,
|
line: mapping.originalLine,
|
||||||
|
@ -170,19 +242,7 @@ function optimize(transformed, file, originalCode, options) {
|
||||||
name: original.name || mapping.name,
|
name: original.name || mapping.name,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
return merged.toJSON();
|
||||||
const min = minify(file, gen.code, merged.toJSON());
|
|
||||||
return {code: min.code, map: min.map, dependencies};
|
|
||||||
}
|
|
||||||
|
|
||||||
function optimizeCode(code, map, filename, options) {
|
|
||||||
const inlineOptions = Object.assign({isWrapped: true}, options);
|
|
||||||
return babel.transform(code, {
|
|
||||||
plugins: [[constantFolding], [inline, inlineOptions]],
|
|
||||||
babelrc: false,
|
|
||||||
code: false,
|
|
||||||
filename,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function writeResult(outfile, result) {
|
function writeResult(outfile, result) {
|
||||||
|
@ -190,5 +250,9 @@ function writeResult(outfile, result) {
|
||||||
fs.writeFileSync(outfile, JSON.stringify(result), 'utf8');
|
fs.writeFileSync(outfile, JSON.stringify(result), 'utf8');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function makeIdentifier(name) {
|
||||||
|
return babel.types.identifier(name);
|
||||||
|
}
|
||||||
|
|
||||||
exports.transformModule = transformModule;
|
exports.transformModule = transformModule;
|
||||||
exports.optimizeModule = optimizeModule;
|
exports.optimizeModule = optimizeModule;
|
||||||
|
|
Loading…
Reference in New Issue