mirror of https://github.com/status-im/metro.git
Use "babel-preset-react-native"
Summary: Rather than specifying Babel plugins in the `.babelrc` packaged with react-native, leverage a Babel preset to define the plugins (https://github.com/exponentjs/babel-preset-react-native). This allows for a much better user experience for those who want (or need) to override options in their project's `.babelrc`. Prior to this PR, if a user wanted to use a custom babel-plugin (or a custom set of babel plugins), they'd have either 1) manually override the `.babelrc` in the react-packager directory (or fork RN), or 2) specify a custom transformer to use when running the packager that loaded their own `.babelrc`. Note - the custom transformer was necessary because without it, RN's `.babelrc` options would supersede the options defined in the project's `.babelrc`...potentially causing issues with plugin ordering. This PR makes the transformer check for the existence of a project-level `.babelrc`, and if it it's there, it _doesn't_ use the react-native `.babelrc`. This prevents any oddities with Babel plug Closes https://github.com/facebook/react-native/pull/5214 Reviewed By: davidaurelio Differential Revision: D2881814 Pulled By: martinbigio fb-gh-sync-id: 4168144b7a365fae62bbeed094d8a03a48b4798c
This commit is contained in:
parent
6d8ccc318b
commit
38cea2edeb
|
@ -16,7 +16,7 @@ var path = require('path');
|
||||||
var _only = [];
|
var _only = [];
|
||||||
|
|
||||||
function readBabelRC() {
|
function readBabelRC() {
|
||||||
var rcpath = path.join(__dirname, 'react-packager', '.babelrc');
|
var rcpath = path.join(__dirname, 'react-packager', 'rn-babelrc.json');
|
||||||
var source = fs.readFileSync(rcpath).toString();
|
var source = fs.readFileSync(rcpath).toString();
|
||||||
return JSON.parse(source);
|
return JSON.parse(source);
|
||||||
}
|
}
|
||||||
|
@ -25,5 +25,5 @@ module.exports = function(onlyList) {
|
||||||
_only = _only.concat(onlyList);
|
_only = _only.concat(onlyList);
|
||||||
var config = readBabelRC();
|
var config = readBabelRC();
|
||||||
config.only = _only;
|
config.only = _only;
|
||||||
require('babel-core/register')(config);
|
require('babel-register')(config);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
{
|
|
||||||
"retainLines": true,
|
|
||||||
"compact": true,
|
|
||||||
"comments": false,
|
|
||||||
"plugins": [
|
|
||||||
"syntax-async-functions",
|
|
||||||
"syntax-class-properties",
|
|
||||||
"syntax-trailing-function-commas",
|
|
||||||
"transform-class-properties",
|
|
||||||
"transform-es2015-arrow-functions",
|
|
||||||
"transform-es2015-block-scoping",
|
|
||||||
"transform-es2015-classes",
|
|
||||||
"transform-es2015-computed-properties",
|
|
||||||
"transform-es2015-constants",
|
|
||||||
"transform-es2015-destructuring",
|
|
||||||
["transform-es2015-modules-commonjs", {"strict": false, "allowTopLevelThis": true}],
|
|
||||||
"transform-es2015-parameters",
|
|
||||||
"transform-es2015-shorthand-properties",
|
|
||||||
"transform-es2015-spread",
|
|
||||||
"transform-es2015-template-literals",
|
|
||||||
"transform-flow-strip-types",
|
|
||||||
"transform-object-assign",
|
|
||||||
"transform-object-rest-spread",
|
|
||||||
"transform-react-display-name",
|
|
||||||
"transform-react-jsx",
|
|
||||||
"transform-regenerator",
|
|
||||||
"transform-es2015-for-of"
|
|
||||||
],
|
|
||||||
"sourceMaps": false
|
|
||||||
}
|
|
|
@ -15,7 +15,6 @@ useGracefulFs();
|
||||||
var debug = require('debug');
|
var debug = require('debug');
|
||||||
var omit = require('underscore').omit;
|
var omit = require('underscore').omit;
|
||||||
var Activity = require('./src/Activity');
|
var Activity = require('./src/Activity');
|
||||||
var Transforms = require('./src/transforms');
|
|
||||||
|
|
||||||
exports.createServer = createServer;
|
exports.createServer = createServer;
|
||||||
exports.middleware = function(options) {
|
exports.middleware = function(options) {
|
||||||
|
@ -24,7 +23,6 @@ exports.middleware = function(options) {
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.Activity = Activity;
|
exports.Activity = Activity;
|
||||||
exports.getTransforms = Transforms.getAll;
|
|
||||||
|
|
||||||
// Renamed "package" to "bundle". But maintain backwards
|
// Renamed "package" to "bundle". But maintain backwards
|
||||||
// compat.
|
// compat.
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"presets": [ "react-native" ],
|
||||||
|
"plugins": []
|
||||||
|
}
|
|
@ -66,6 +66,7 @@ class Transformer {
|
||||||
|
|
||||||
this._cache = opts.cache;
|
this._cache = opts.cache;
|
||||||
this._transformModulePath = opts.transformModulePath;
|
this._transformModulePath = opts.transformModulePath;
|
||||||
|
this._projectRoots = opts.projectRoots;
|
||||||
|
|
||||||
if (opts.transformModulePath != null) {
|
if (opts.transformModulePath != null) {
|
||||||
let transformer;
|
let transformer;
|
||||||
|
@ -129,6 +130,7 @@ class Transformer {
|
||||||
filename: filePath,
|
filename: filePath,
|
||||||
options: {
|
options: {
|
||||||
...options,
|
...options,
|
||||||
|
projectRoots: this._projectRoots,
|
||||||
externalTransformModulePath: this._transformModulePath,
|
externalTransformModulePath: this._transformModulePath,
|
||||||
},
|
},
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (c) 2015-present, 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.
|
|
||||||
*/
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Manually resolve all default Babel plugins.
|
|
||||||
* `babel.transform` will attempt to resolve all base plugins relative to
|
|
||||||
* the file it's compiling. This makes sure that we're using the plugins
|
|
||||||
* installed in the react-native package.
|
|
||||||
*/
|
|
||||||
function resolvePlugins(plugins) {
|
|
||||||
return plugins.map(function(plugin) {
|
|
||||||
// Normalise plugin to an array.
|
|
||||||
if (!Array.isArray(plugin)) {
|
|
||||||
plugin = [plugin];
|
|
||||||
}
|
|
||||||
// Only resolve the plugin if it's a string reference.
|
|
||||||
if (typeof plugin[0] === 'string') {
|
|
||||||
plugin[0] = require('babel-plugin-' + plugin[0]);
|
|
||||||
plugin[0] = plugin[0].__esModule ? plugin[0].default : plugin[0];
|
|
||||||
}
|
|
||||||
return plugin;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = resolvePlugins;
|
|
|
@ -9,30 +9,25 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var babel = require('babel-core');
|
var babel = require('babel-core');
|
||||||
var resolvePlugins = require('./resolvePlugins');
|
var makeInternalConfig = require('babel-preset-react-native/configs/internal');
|
||||||
var Transforms = require('../transforms');
|
|
||||||
|
|
||||||
// Runs internal transforms on the given sourceCode. Note that internal
|
// Runs internal transforms on the given sourceCode. Note that internal
|
||||||
// transforms should be run after the external ones to ensure that they run on
|
// transforms should be run after the external ones to ensure that they run on
|
||||||
// Javascript code
|
// Javascript code
|
||||||
function internalTransforms(sourceCode, filename, options) {
|
function internalTransforms(sourceCode, filename, options) {
|
||||||
var plugins = resolvePlugins(Transforms.getAll(options));
|
var internalBabelConfig = makeInternalConfig(options);
|
||||||
if (plugins.length === 0) {
|
|
||||||
|
if (!internalBabelConfig) {
|
||||||
return {
|
return {
|
||||||
code: sourceCode,
|
code: sourceCode,
|
||||||
filename: filename,
|
filename: filename,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = babel.transform(sourceCode, {
|
var result = babel.transform(sourceCode, Object.assign({
|
||||||
retainLines: true,
|
|
||||||
compact: true,
|
|
||||||
comments: false,
|
|
||||||
filename: filename,
|
filename: filename,
|
||||||
sourceFileName: filename,
|
sourceFileName: filename,
|
||||||
sourceMaps: false,
|
}, internalBabelConfig));
|
||||||
plugins: plugins,
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
code: result.code,
|
code: result.code,
|
||||||
|
|
|
@ -93,7 +93,6 @@ class Resolver {
|
||||||
// should work after this release and we can
|
// should work after this release and we can
|
||||||
// remove it from here.
|
// remove it from here.
|
||||||
'parse',
|
'parse',
|
||||||
'react-transform-hmr',
|
|
||||||
],
|
],
|
||||||
platforms: ['ios', 'android'],
|
platforms: ['ios', 'android'],
|
||||||
preferNativePlatform: true,
|
preferNativePlatform: true,
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (c) 2015-present, 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.
|
|
||||||
*/
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
exports.getAll = function(options) {
|
|
||||||
return [];
|
|
||||||
};
|
|
||||||
|
|
100
transformer.js
100
transformer.js
|
@ -11,47 +11,95 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const babel = require('babel-core');
|
const babel = require('babel-core');
|
||||||
|
const externalHelpersPlugin = require('babel-plugin-external-helpers');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const inlineRequires = require('fbjs-scripts/babel-6/inline-requires');
|
const makeHMRConfig = require('babel-preset-react-native/configs/hmr');
|
||||||
|
const resolvePlugins = require('babel-preset-react-native/lib/resolvePlugins');
|
||||||
|
const inlineRequiresPlugin = require('fbjs-scripts/babel-6/inline-requires');
|
||||||
const json5 = require('json5');
|
const json5 = require('json5');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const ReactPackager = require('./react-packager');
|
|
||||||
const resolvePlugins = require('./react-packager/src/JSTransformer/resolvePlugins');
|
|
||||||
|
|
||||||
const babelRC =
|
/**
|
||||||
json5.parse(
|
* Return a memoized function that checks for the existence of a
|
||||||
fs.readFileSync(
|
* project level .babelrc file, and if it doesn't exist, reads the
|
||||||
path.resolve(__dirname, 'react-packager', '.babelrc')));
|
* default RN babelrc file and uses that.
|
||||||
|
*/
|
||||||
|
const getBabelRC = (function() {
|
||||||
|
let babelRC = null;
|
||||||
|
|
||||||
function transform(src, filename, options) {
|
return function _getBabelRC(projectRoots) {
|
||||||
options = options || {};
|
if (babelRC !== null) {
|
||||||
|
return babelRC;
|
||||||
|
}
|
||||||
|
|
||||||
|
babelRC = { plugins: [] }; // empty babelrc
|
||||||
|
|
||||||
|
// Let's look for the .babelrc in the first project root.
|
||||||
|
// In the future let's look into adding a command line option to specify
|
||||||
|
// this location.
|
||||||
|
//
|
||||||
|
// NOTE: we're not reading the project's .babelrc here. We leave it up to
|
||||||
|
// Babel to do that automatically and apply the transforms accordingly
|
||||||
|
// (which works because we pass in `filename` and `sourceFilename` to
|
||||||
|
// Babel when we transform).
|
||||||
|
let projectBabelRCPath;
|
||||||
|
if (projectRoots && projectRoots.length > 0) {
|
||||||
|
projectBabelRCPath = path.resolve(projectRoots[0], '.babelrc');
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a .babelrc file doesn't exist in the project,
|
||||||
|
// use the Babel config provided with react-native.
|
||||||
|
if (!projectBabelRCPath || !fs.existsSync(projectBabelRCPath)) {
|
||||||
|
babelRC = json5.parse(
|
||||||
|
fs.readFileSync(
|
||||||
|
path.resolve(__dirname, 'react-packager', 'rn-babelrc.json'))
|
||||||
|
);
|
||||||
|
|
||||||
|
// Require the babel-preset's listed in the default babel config
|
||||||
|
babelRC.presets = babelRC.presets.map((preset) => require('babel-preset-' + preset));
|
||||||
|
babelRC.plugins = resolvePlugins(babelRC.plugins);
|
||||||
|
}
|
||||||
|
|
||||||
|
return babelRC;
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a filename and options, build a Babel
|
||||||
|
* config object with the appropriate plugins.
|
||||||
|
*/
|
||||||
|
function buildBabelConfig(filename, options) {
|
||||||
|
const babelRC = getBabelRC(options.projectRoots);
|
||||||
|
|
||||||
const extraPlugins = ['external-helpers-2'];
|
|
||||||
const extraConfig = {
|
const extraConfig = {
|
||||||
filename,
|
filename,
|
||||||
sourceFileName: filename,
|
sourceFileName: filename,
|
||||||
};
|
};
|
||||||
|
|
||||||
const config = Object.assign({}, babelRC, extraConfig);
|
let config = Object.assign({}, babelRC, extraConfig);
|
||||||
if (options.hot) {
|
|
||||||
extraPlugins.push([
|
// Add extra plugins
|
||||||
'react-transform',
|
const extraPlugins = [externalHelpersPlugin];
|
||||||
{
|
|
||||||
transforms: [{
|
|
||||||
transform: 'react-transform-hmr/lib/index.js',
|
|
||||||
imports: ['React'],
|
|
||||||
locals: ['module'],
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.inlineRequires) {
|
if (options.inlineRequires) {
|
||||||
extraPlugins.push(inlineRequires);
|
extraPlugins.push(inlineRequiresPlugin);
|
||||||
}
|
}
|
||||||
config.plugins = resolvePlugins(extraPlugins.concat(config.plugins));
|
|
||||||
|
|
||||||
const result = babel.transform(src, Object.assign({}, babelRC, config));
|
config.plugins = extraPlugins.concat(config.plugins);
|
||||||
|
|
||||||
|
if (options.hot) {
|
||||||
|
const hmrConfig = makeHMRConfig(options);
|
||||||
|
config = Object.assign({}, config, hmrConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Object.assign({}, babelRC, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
function transform(src, filename, options) {
|
||||||
|
options = options || {};
|
||||||
|
|
||||||
|
const babelConfig = buildBabelConfig(filename, options);
|
||||||
|
const result = babel.transform(src, babelConfig);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
code: result.code,
|
code: result.code,
|
||||||
|
|
Loading…
Reference in New Issue