UNPKG

7.17 kBJavaScriptView Raw
1/**
2 * Copyright (c) 2015-present, Facebook, Inc.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7'use strict';
8
9const path = require('path');
10
11const validateBoolOption = (name, value, defaultValue) => {
12 if (typeof value === 'undefined') {
13 value = defaultValue;
14 }
15
16 if (typeof value !== 'boolean') {
17 throw new Error(`Preset react-app: '${name}' option must be a boolean.`);
18 }
19
20 return value;
21};
22
23module.exports = function(api, opts, env) {
24 if (!opts) {
25 opts = {};
26 }
27
28 var isEnvDevelopment = env === 'development';
29 var isEnvProduction = env === 'production';
30 var isEnvTest = env === 'test';
31
32 var useESModules = validateBoolOption(
33 'useESModules',
34 opts.useESModules,
35 isEnvDevelopment || isEnvProduction
36 );
37 var isFlowEnabled = validateBoolOption('flow', opts.flow, true);
38 var isTypeScriptEnabled = validateBoolOption(
39 'typescript',
40 opts.typescript,
41 true
42 );
43 var areHelpersEnabled = validateBoolOption('helpers', opts.helpers, true);
44 var useAbsoluteRuntime = validateBoolOption(
45 'absoluteRuntime',
46 opts.absoluteRuntime,
47 true
48 );
49
50 var absoluteRuntimePath = undefined;
51 if (useAbsoluteRuntime) {
52 absoluteRuntimePath = path.dirname(
53 require.resolve('@babel/runtime/package.json')
54 );
55 }
56
57 if (!isEnvDevelopment && !isEnvProduction && !isEnvTest) {
58 throw new Error(
59 'Using `babel-preset-react-app` requires that you specify `NODE_ENV` or ' +
60 '`BABEL_ENV` environment variables. Valid values are "development", ' +
61 '"test", and "production". Instead, received: ' +
62 JSON.stringify(env) +
63 '.'
64 );
65 }
66
67 return {
68 presets: [
69 isEnvTest && [
70 // ES features necessary for user's Node version
71 require('@babel/preset-env').default,
72 {
73 targets: {
74 node: 'current',
75 },
76 },
77 ],
78 (isEnvProduction || isEnvDevelopment) && [
79 // Latest stable ECMAScript features
80 require('@babel/preset-env').default,
81 {
82 // Allow importing core-js in entrypoint and use browserlist to select polyfills
83 useBuiltIns: 'entry',
84 // Set the corejs version we are using to avoid warnings in console
85 // This will need to change once we upgrade to corejs@3
86 corejs: 3,
87 // Do not transform modules to CJS
88 modules: false,
89 // Exclude transforms that make all code slower
90 exclude: ['transform-typeof-symbol'],
91 },
92 ],
93 [
94 require('@babel/preset-react').default,
95 {
96 // Adds component stack to warning messages
97 // Adds __self attribute to JSX which React will use for some warnings
98 development: isEnvDevelopment || isEnvTest,
99 // Will use the native built-in instead of trying to polyfill
100 // behavior for any plugins that require one.
101 useBuiltIns: true,
102 },
103 ],
104 isTypeScriptEnabled && [require('@babel/preset-typescript').default],
105 ].filter(Boolean),
106 plugins: [
107 // Strip flow types before any other transform, emulating the behavior
108 // order as-if the browser supported all of the succeeding features
109 // https://github.com/facebook/create-react-app/pull/5182
110 // We will conditionally enable this plugin below in overrides as it clashes with
111 // @babel/plugin-proposal-decorators when using TypeScript.
112 // https://github.com/facebook/create-react-app/issues/5741
113 isFlowEnabled && [
114 require('@babel/plugin-transform-flow-strip-types').default,
115 false,
116 ],
117 // Experimental macros support. Will be documented after it's had some time
118 // in the wild.
119 require('babel-plugin-macros'),
120 // Necessary to include regardless of the environment because
121 // in practice some other transforms (such as object-rest-spread)
122 // don't work without it: https://github.com/babel/babel/issues/7215
123 [
124 require('@babel/plugin-transform-destructuring').default,
125 {
126 // Use loose mode for performance:
127 // https://github.com/facebook/create-react-app/issues/5602
128 loose: false,
129 selectiveLoose: [
130 'useState',
131 'useEffect',
132 'useContext',
133 'useReducer',
134 'useCallback',
135 'useMemo',
136 'useRef',
137 'useImperativeHandle',
138 'useLayoutEffect',
139 'useDebugValue',
140 ],
141 },
142 ],
143 // Turn on legacy decorators for TypeScript files
144 isTypeScriptEnabled && [
145 require('@babel/plugin-proposal-decorators').default,
146 false,
147 ],
148 // class { handleClick = () => { } }
149 // Enable loose mode to use assignment instead of defineProperty
150 // See discussion in https://github.com/facebook/create-react-app/issues/4263
151 [
152 require('@babel/plugin-proposal-class-properties').default,
153 {
154 loose: true,
155 },
156 ],
157 // The following two plugins use Object.assign directly, instead of Babel's
158 // extends helper. Note that this assumes `Object.assign` is available.
159 // { ...todo, completed: true }
160 [
161 require('@babel/plugin-proposal-object-rest-spread').default,
162 {
163 useBuiltIns: true,
164 },
165 ],
166 // Polyfills the runtime needed for async/await, generators, and friends
167 // https://babeljs.io/docs/en/babel-plugin-transform-runtime
168 [
169 require('@babel/plugin-transform-runtime').default,
170 {
171 corejs: false,
172 helpers: areHelpersEnabled,
173 regenerator: true,
174 // https://babeljs.io/docs/en/babel-plugin-transform-runtime#useesmodules
175 // We should turn this on once the lowest version of Node LTS
176 // supports ES Modules.
177 useESModules,
178 // Undocumented option that lets us encapsulate our runtime, ensuring
179 // the correct version is used
180 // https://github.com/babel/babel/blob/090c364a90fe73d36a30707fc612ce037bdbbb24/packages/babel-plugin-transform-runtime/src/index.js#L35-L42
181 absoluteRuntime: absoluteRuntimePath,
182 },
183 ],
184 isEnvProduction && [
185 // Remove PropTypes from production build
186 require('babel-plugin-transform-react-remove-prop-types').default,
187 {
188 removeImport: true,
189 },
190 ],
191 // Adds syntax support for import()
192 require('@babel/plugin-syntax-dynamic-import').default,
193 isEnvTest &&
194 // Transform dynamic import to require
195 require('babel-plugin-dynamic-import-node'),
196 ].filter(Boolean),
197 overrides: [
198 isFlowEnabled && {
199 exclude: /\.tsx?$/,
200 plugins: [require('@babel/plugin-transform-flow-strip-types').default],
201 },
202 isTypeScriptEnabled && {
203 test: /\.tsx?$/,
204 plugins: [
205 [
206 require('@babel/plugin-proposal-decorators').default,
207 { legacy: true },
208 ],
209 ],
210 },
211 ].filter(Boolean),
212 };
213};