@nake/babel-preset
Version:
Babel preset for transforming your future JS/JSX and TypeScript code
136 lines (120 loc) • 5.5 kB
JavaScript
// Utils
const { assign: _assign } = Object;
const { declare } = require('@babel/helper-plugin-utils');
// Presets
const presetEnv = require('@babel/preset-env');
const presetReact = require('@babel/preset-react');
const presetTypeScript = require('@babel/preset-typescript');
// Plugins
const pluginStrictMode = require('@babel/plugin-transform-strict-mode');
// React optimized plugins
const reactRemovePropTypes = require('babel-plugin-transform-react-remove-prop-types');
const reactInlineElements = require('@babel/plugin-transform-react-inline-elements');
const reactConstantElements = require('@babel/plugin-transform-react-constant-elements');
// TC39 Proposals
const proposalDecorators = require('@babel/plugin-proposal-decorators');
const proposalClassProperties = require('@babel/plugin-proposal-class-properties');
const proposalDoExpressions = require('@babel/plugin-proposal-do-expressions');
const proposalExportDefaultFrom = require('@babel/plugin-proposal-export-default-from');
const proposalExportNamespaceFrom = require('@babel/plugin-proposal-export-namespace-from');
const proposalFunctionBind = require('@babel/plugin-proposal-function-bind');
const proposalLogicalAssignmentOperators = require('@babel/plugin-proposal-logical-assignment-operators');
const proposalNullishCoalescingOperator = require('@babel/plugin-proposal-nullish-coalescing-operator');
const proposalNumericSeparator = require('@babel/plugin-proposal-numeric-separator');
const proposalOptionalChaining = require('@babel/plugin-proposal-optional-chaining');
const proposalPipelineOperator = require('@babel/plugin-proposal-pipeline-operator');
const proposalThrowExpressions = require('@babel/plugin-proposal-throw-expressions');
const proposalDynamicImport = require('@babel/plugin-syntax-dynamic-import');
const proposalFunctionSent = require('@babel/plugin-syntax-function-sent');
const proposalImportMeta = require('@babel/plugin-syntax-import-meta');
module.exports = declare((api, options) => {
// Declare required version
api.assertVersion('^7.2.0');
// Cache in development mode
const isDev = api.env('development');
api.cache.using(() => isDev);
// Default options
const {
react: useReact = true,
typescript: useTypeScript = false,
strict: forceStrictMode = true,
sourceMaps = true,
proposals = {
decorators: true,
'class-properties': true,
'do-expressions': true,
'export-default-from': true,
'export-namespace-from': true,
'function-bind': true,
'logical-assignment-operators': true,
'nullish-coalescing-operator': true,
'numeric-separator': true,
'optional-chaining': true,
'pipeline-operator': true,
'throw-expressions': true,
'dynamic-import': true,
'function-sent': true,
'import-meta': true,
},
...userEnvOptions
} = options;
// Make env preset with reasonable default options
const defaultEnvOptions = {
debug: false,
loose: true,
modules: false,
useBuiltIns: 'usage',
targets: {
node: 'current',
esmodules: false,
browsers: ['last 1 versions', 'not ie_mob <= 11', 'not op_mini all', 'not dead'],
},
};
const presets = [[presetEnv, _assign(defaultEnvOptions, userEnvOptions)]];
// Make react preset with reasonable default options
const defaultReactOptions = { development: isDev };
if (useReact) presets.push([presetReact, _assign(defaultReactOptions, useReact)]);
// Make typescript preset with reasonable default options
const defaultTypeScriptOptions = { isTSX: true, allExtensions: true };
if (useTypeScript) {
presets.push([presetTypeScript, _assign(defaultTypeScriptOptions, useTypeScript)]);
}
// Enabled babel plugins
const enabledPlugins = [forceStrictMode ? [pluginStrictMode, {}] : null];
// Enabled TC39 proposals with options
const enabledProposals = [
['decorators', [proposalDecorators, { decoratorsBeforeExport: false }]],
['class-properties', [proposalClassProperties, { loose: true }]],
['do-expressions', [proposalDoExpressions, {}]],
['export-default-from', [proposalExportDefaultFrom, {}]],
['export-namespace-from', [proposalExportNamespaceFrom, {}]],
['function-bind', [proposalFunctionBind, {}]],
['logical-assignment-operators', [proposalLogicalAssignmentOperators, {}]],
['nullish-coalescing-operator', [proposalNullishCoalescingOperator, { loose: true }]],
['numeric-separator', [proposalNumericSeparator, {}]],
['optional-chaining', [proposalOptionalChaining, { loose: true }]],
['pipeline-operator', [proposalPipelineOperator, { proposal: 'minimal' }]],
['throw-expressions', [proposalThrowExpressions, {}]],
['dynamic-import', [proposalDynamicImport, {}]],
['function-sent', [proposalFunctionSent, {}]],
['import-meta', [proposalImportMeta, {}]],
]
.filter(p => proposals[p[0]])
.map(p => [p[1][0], _assign(p[1][1], proposals[p[0]])]);
// Make plugins based on options
let plugins = [...enabledPlugins, ...enabledProposals];
// Add plugins in production mode
if (!isDev) {
plugins = [
...plugins,
useReact ? [reactInlineElements, {}] : null,
useReact ? [reactConstantElements, { allowMutablePropsOnTags: [] }] : null,
useReact ? [reactRemovePropTypes, { ignoreFilenames: ['node_modules'] }] : null,
].filter(p => p);
}
return {
presets,
plugins,
sourceMaps: sourceMaps && isDev ? 'inline' : true,
};
});