nwb
Version:
A toolkit for React, Preact & Inferno apps, React libraries and other npm modules for the web, with no configuration (until you need it)
177 lines (144 loc) • 5.88 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = createBabelConfig;
var _path = _interopRequireDefault(require("path"));
var _errors = require("./errors");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function createBabelConfig(buildConfig = {}, userConfig = {}, userConfigPath = '', userConfigBrowsers = {}) {
let {
absoluteRuntime,
commonJSInterop,
env: buildEnv = {},
modules = false,
plugins: buildPlugins = [],
presets: buildPresets,
proposals: buildProposals = {},
removePropTypes: buildRemovePropTypes = false,
runtime: buildRuntime,
webpack = true
} = buildConfig;
let {
cherryPick,
config: userConfigFunction,
env: userEnv = {},
loose,
plugins: userPlugins = [],
presets: userPresets,
proposals: userProposals = {},
react = {},
reactConstantElements,
removePropTypes: userRemovePropTypes,
runtime: userRuntime
} = userConfig;
let presets = [];
let plugins = [// XXX Webpack can't currently handle untranspiled ?. and ?? syntax
// See https://github.com/webpack/webpack/issues/10227#issuecomment-588409413
require.resolve('@babel/plugin-proposal-optional-chaining'), require.resolve('@babel/plugin-proposal-nullish-coalescing-operator')]; // Default to loose mode unless explicitly configured
if (typeof loose === 'undefined') {
loose = true;
} // Build config controls whether or not we set browser targets. Users can
// override this using `browsers` or `babel.env.targets` config.
let userTargets = {};
if (buildEnv.targets) {
let targets = userConfigBrowsers && (process.env.NODE_ENV === 'production' ? userConfigBrowsers.production : userConfigBrowsers.development);
if (targets) {
userTargets.targets = targets;
}
}
presets.push([require.resolve('@babel/preset-env'), {
loose,
...buildEnv,
modules,
// Targets config from top-level browsers config if present
...userTargets,
// The user gets a last go at all the env options
...userEnv
}]); // Additional build presets
if (Array.isArray(buildPresets)) {
buildPresets.forEach(preset => {
// Presets which are configurable via user config are specified by name so
// customisation can be handled in this module.
if (preset === 'react') {
presets.push([require.resolve('@babel/preset-react'), {
development: process.env.NODE_ENV !== 'production',
...react
}]);
} else if (preset === 'react-prod') {
// Hoist static element subtrees up so React can skip them when reconciling
if (reactConstantElements !== false) {
plugins.push(require.resolve('@babel/plugin-transform-react-constant-elements'));
} // Remove or wrap propTypes and optionally remove prop-types imports
if (userRemovePropTypes !== false) {
plugins.push([require.resolve('babel-plugin-transform-react-remove-prop-types'), typeof userRemovePropTypes === 'object' ? userRemovePropTypes : {}]);
}
} else {
presets.push(preset);
}
});
} // Proposal plugins
if (userProposals !== false) {
presets.push([require.resolve('babel-preset-proposals'), {
// Pass on nwb's loose = true default
loose,
decorators: true,
classProperties: true,
exportDefaultFrom: true,
exportNamespaceFrom: true,
...buildProposals,
...userProposals,
// Required for non-local usage of nwb
absolutePaths: true
}]);
}
if (userPresets) {
presets = presets.concat(userPresets);
}
let config = {
presets
};
plugins = plugins.concat(buildPlugins, userPlugins); // App builds use the 'react-prod' preset to remove/wrap propTypes, component
// builds use this config instead.
if (buildRemovePropTypes) {
// User config can disable removal of propTypes
if (userRemovePropTypes !== false) {
plugins.push([require.resolve('babel-plugin-transform-react-remove-prop-types'), { ...(typeof buildRemovePropTypes === 'object' ? buildRemovePropTypes : {}),
...(typeof userRemovePropTypes === 'object' ? userRemovePropTypes : {})
}]);
}
} // The Runtime transform imports helpers and the regenerator runtime when required
// See https://babeljs.io/docs/en/babel-plugin-transform-runtime.html
if (userRuntime !== false) {
plugins.push([require.resolve('@babel/plugin-transform-runtime'), {
absoluteRuntime: absoluteRuntime !== false ? _path.default.resolve(__dirname, '..') : false,
useESModules: modules === false,
...(typeof buildRuntime === 'object' ? buildRuntime : {}),
...(typeof userRuntime === 'object' ? userRuntime : {})
}]);
} // Allow Babel to parse (but not transform) import() when used with Webpack
if (webpack) {
plugins.push(require.resolve('@babel/plugin-syntax-dynamic-import'));
} // Provide CommonJS interop so users don't have to tag a .default onto their
// imports if they're using vanilla Node.js require().
if (commonJSInterop) {
plugins.push(require.resolve('babel-plugin-add-module-exports'));
} // The lodash plugin supports generic cherry-picking for named modules
if (cherryPick) {
plugins.push([require.resolve('babel-plugin-lodash'), {
id: cherryPick
}]);
}
if (plugins.length > 0) {
config.plugins = plugins;
} // Finally, give the user a chance to do whatever they want with the generated
// config.
if (typeof userConfigFunction === 'function') {
config = userConfigFunction(config);
if (!config) {
throw new _errors.UserError(`babel.config() in ${userConfigPath} didn't return anything - it must return the Babel config object.`);
}
}
return config;
}
module.exports = exports.default;