UNPKG

3.97 kBJavaScriptView Raw
1/* eslint-disable no-console */
2
3const { loadConfig } = require('browserslist');
4const pick = require('lodash/pick');
5const path = require('path');
6const envPreset = require('@babel/preset-env');
7const reactPreset = require('@babel/preset-react');
8
9const intlPreset = require('./intl-preset');
10const plugins = require('./plugins');
11
12const PRESET_ENV_OPTIONS = [
13 'targets',
14 'spec',
15 'loose',
16 'modules',
17 'debug',
18 'include',
19 'exclude',
20 'useBuiltIns',
21 // For this, we use envCorejs below.
22 // 'corejs',
23 'forceAllTransforms',
24 'configPath',
25 'ignoreBrowserslistConfig',
26 'shippedProposals',
27];
28
29const DEFAULT_BROWSERS = [
30 'ie >= 11',
31 'last 2 Edge versions',
32 'last 4 Chrome versions',
33 'last 4 Firefox versions',
34 'last 2 Safari versions',
35];
36
37function addDefaultOptions(explicitOptions) {
38 const options = {
39 target: 'web', // 'web-app' | 'node'
40 development: false,
41
42 targets: undefined,
43 spec: false,
44 loose: true,
45 modules: 'commonjs',
46 debug: false,
47 include: [],
48 exclude: null, // Defaulted below.
49 useBuiltIns: false,
50 envCorejs: null,
51 forceAllTransforms: false,
52 configPath: '.',
53 ignoreBrowserslistConfig: false,
54 shippedProposals: true,
55
56 runtime: false,
57 corejs: false,
58 intl: false,
59
60 ...explicitOptions,
61 };
62
63 if (options.useBuiltIns) {
64 options.envCorejs = options.envCorejs || options.corejs || 3;
65 }
66
67 if (options.corejs && options.envCorejs !== options.corejs) {
68 console.warn(
69 '@4c/babel-preset: You have a mismatch between requested core-js versions.\n' +
70 `preset-env requests v${options.envCorejs} while runtime is v${options.corejs}. ` +
71 'Make sure `options.corejs` is empty or matches `options.envCorejs`.',
72 );
73 }
74
75 if (!options.exclude) {
76 options.exclude =
77 options.envCorejs === 2
78 ? [
79 // Seems to be added by default with minimum benefit.
80 'web.dom.iterable',
81 ]
82 : [];
83 }
84
85 return options;
86}
87
88function getTargets({
89 development,
90 target,
91 targets,
92 configPath,
93 ignoreBrowserslistConfig,
94}) {
95 if (development) {
96 return target === 'node' ? { node: 'current' } : { esmodules: true };
97 }
98
99 // TODO: Distinguish between app and libraries for node as well.
100 if (target === 'node') return { node: '12.0' };
101
102 if (
103 ignoreBrowserslistConfig ||
104 !loadConfig({ path: path.resolve(configPath) })
105 ) {
106 return targets || DEFAULT_BROWSERS;
107 }
108
109 // We don't run browserslist ourself b/c that would require doing a bunch of
110 // additional transforms to get the output in a format preset-env would
111 // accept.
112 return targets || undefined;
113}
114
115function preset(api, explicitOptions = {}) {
116 const options = addDefaultOptions(explicitOptions);
117 const { target, development } = options;
118
119 options.targets = getTargets(options);
120
121 // In a web app, assume we are using Webpack to handle modules, and use the
122 // runtime for Babel helpers.
123 if (target === 'web-app') {
124 options.runtime =
125 explicitOptions.runtime == null ? true : explicitOptions.runtime;
126 options.modules =
127 explicitOptions.modules == null ? false : explicitOptions.modules;
128 }
129
130 // unless the user explicitly set modules, change the default to
131 // cjs in a TEST environment (jest)
132 if (api.env() === 'test' && explicitOptions.modules == null) {
133 options.modules = 'commonjs';
134 }
135
136 const presets = [
137 [
138 envPreset,
139 {
140 ...pick(options, PRESET_ENV_OPTIONS),
141 corejs: options.envCorejs,
142 },
143 ],
144 [reactPreset, { development }],
145 ];
146
147 if (options.intl) {
148 const intlOpts =
149 typeof options.intl === 'object'
150 ? options.intl
151 : {
152 prefix: explicitOptions.prefix,
153 messagesDir: 'build/messages',
154 };
155
156 if (!development) {
157 presets.push([intlPreset, intlOpts]);
158 }
159 }
160
161 return {
162 presets,
163 plugins: plugins(options),
164 };
165}
166
167module.exports = preset;