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 = [];
|
||||
|
||||
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();
|
||||
return JSON.parse(source);
|
||||
}
|
||||
|
@ -25,5 +25,5 @@ module.exports = function(onlyList) {
|
|||
_only = _only.concat(onlyList);
|
||||
var config = readBabelRC();
|
||||
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 omit = require('underscore').omit;
|
||||
var Activity = require('./src/Activity');
|
||||
var Transforms = require('./src/transforms');
|
||||
|
||||
exports.createServer = createServer;
|
||||
exports.middleware = function(options) {
|
||||
|
@ -24,7 +23,6 @@ exports.middleware = function(options) {
|
|||
};
|
||||
|
||||
exports.Activity = Activity;
|
||||
exports.getTransforms = Transforms.getAll;
|
||||
|
||||
// Renamed "package" to "bundle". But maintain backwards
|
||||
// compat.
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"presets": [ "react-native" ],
|
||||
"plugins": []
|
||||
}
|
|
@ -66,6 +66,7 @@ class Transformer {
|
|||
|
||||
this._cache = opts.cache;
|
||||
this._transformModulePath = opts.transformModulePath;
|
||||
this._projectRoots = opts.projectRoots;
|
||||
|
||||
if (opts.transformModulePath != null) {
|
||||
let transformer;
|
||||
|
@ -129,6 +130,7 @@ class Transformer {
|
|||
filename: filePath,
|
||||
options: {
|
||||
...options,
|
||||
projectRoots: this._projectRoots,
|
||||
externalTransformModulePath: this._transformModulePath,
|
||||
},
|
||||
}).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';
|
||||
|
||||
var babel = require('babel-core');
|
||||
var resolvePlugins = require('./resolvePlugins');
|
||||
var Transforms = require('../transforms');
|
||||
var makeInternalConfig = require('babel-preset-react-native/configs/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
|
||||
// Javascript code
|
||||
function internalTransforms(sourceCode, filename, options) {
|
||||
var plugins = resolvePlugins(Transforms.getAll(options));
|
||||
if (plugins.length === 0) {
|
||||
var internalBabelConfig = makeInternalConfig(options);
|
||||
|
||||
if (!internalBabelConfig) {
|
||||
return {
|
||||
code: sourceCode,
|
||||
filename: filename,
|
||||
};
|
||||
}
|
||||
|
||||
var result = babel.transform(sourceCode, {
|
||||
retainLines: true,
|
||||
compact: true,
|
||||
comments: false,
|
||||
var result = babel.transform(sourceCode, Object.assign({
|
||||
filename: filename,
|
||||
sourceFileName: filename,
|
||||
sourceMaps: false,
|
||||
plugins: plugins,
|
||||
});
|
||||
}, internalBabelConfig));
|
||||
|
||||
return {
|
||||
code: result.code,
|
||||
|
|
|
@ -93,7 +93,6 @@ class Resolver {
|
|||
// should work after this release and we can
|
||||
// remove it from here.
|
||||
'parse',
|
||||
'react-transform-hmr',
|
||||
],
|
||||
platforms: ['ios', 'android'],
|
||||
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';
|
||||
|
||||
const babel = require('babel-core');
|
||||
const externalHelpersPlugin = require('babel-plugin-external-helpers');
|
||||
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 path = require('path');
|
||||
const ReactPackager = require('./react-packager');
|
||||
const resolvePlugins = require('./react-packager/src/JSTransformer/resolvePlugins');
|
||||
|
||||
const babelRC =
|
||||
json5.parse(
|
||||
fs.readFileSync(
|
||||
path.resolve(__dirname, 'react-packager', '.babelrc')));
|
||||
/**
|
||||
* Return a memoized function that checks for the existence of a
|
||||
* project level .babelrc file, and if it doesn't exist, reads the
|
||||
* default RN babelrc file and uses that.
|
||||
*/
|
||||
const getBabelRC = (function() {
|
||||
let babelRC = null;
|
||||
|
||||
function transform(src, filename, options) {
|
||||
options = options || {};
|
||||
return function _getBabelRC(projectRoots) {
|
||||
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 = {
|
||||
filename,
|
||||
sourceFileName: filename,
|
||||
};
|
||||
|
||||
const config = Object.assign({}, babelRC, extraConfig);
|
||||
if (options.hot) {
|
||||
extraPlugins.push([
|
||||
'react-transform',
|
||||
{
|
||||
transforms: [{
|
||||
transform: 'react-transform-hmr/lib/index.js',
|
||||
imports: ['React'],
|
||||
locals: ['module'],
|
||||
}]
|
||||
},
|
||||
]);
|
||||
}
|
||||
let config = Object.assign({}, babelRC, extraConfig);
|
||||
|
||||
// Add extra plugins
|
||||
const extraPlugins = [externalHelpersPlugin];
|
||||
|
||||
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 {
|
||||
code: result.code,
|
||||
|
|
Loading…
Reference in New Issue