UNPKG

2.89 kBJavaScriptView Raw
1// @flow strict-local
2
3import type {Config} from '@parcel/types';
4import type {Targets as BabelTargets} from '@babel/preset-env';
5
6import browserslist from 'browserslist';
7import semver from 'semver';
8
9const BROWSER_CONTEXT = new Set(['browser', 'web-worker', 'service-worker']);
10
11// https://github.com/browserslist/browserslist/blob/04d7b3cc6ebeb62baf6d62aeb90f1bfd0c11117c/test/config.test.js#L23
12type BrowserslistConfig = {|[string]: string | Array<string>|};
13
14/**
15 * Loads target node and browser versions from the following locations:
16 * - package.json engines field
17 * - package.json browserslist field
18 * - browserslist or .browserslistrc files
19 *
20 * "Targets" is the name @babel/preset-env uses for what Parcel calls engines.
21 * This should not be confused with Parcel's own targets.
22 * Unlike Parcel's engines, @babel/preset-env expects to work with minimum
23 * versions, not semver ranges, of its targets.
24 */
25export default async function getBabelTargets(
26 config: Config,
27): Promise<?BabelTargets> {
28 let targets = {};
29 let compileTarget = BROWSER_CONTEXT.has(config.env.context)
30 ? 'browsers'
31 : config.env.context;
32 let pkg = await config.getPackage();
33 let packageEngines = pkg?.engines;
34
35 if (compileTarget === 'node') {
36 let nodeVersion = packageEngines?.node;
37 // Use package.engines.node by default if we are compiling for node.
38 if (typeof nodeVersion === 'string') {
39 try {
40 //$FlowFixMe catch error when minVersion() returned null
41 targets.node = semver.minVersion(nodeVersion).version;
42 } catch (e) {
43 throw new Error("Expected 'node' engine to be a valid Semver Range");
44 }
45 }
46 } else {
47 let browsers;
48 if (
49 packageEngines &&
50 (typeof packageEngines.browsers === 'string' ||
51 Array.isArray(packageEngines.browsers))
52 ) {
53 browsers = packageEngines.browsers;
54 } else if (pkg && pkg.browserslist) {
55 browsers = pkg.browserslist;
56 } else {
57 let browserslist = await loadBrowserslist(config);
58 if (browserslist) {
59 browsers = browserslist;
60 }
61 }
62
63 // Parse browser targets
64 if (
65 typeof browsers === 'object' &&
66 browsers != null &&
67 !Array.isArray(browsers)
68 ) {
69 let env = process.env.NODE_ENV ?? 'development';
70 browsers = browsers[env] || browsers.defaults;
71 }
72
73 if (browsers != null) {
74 targets.browsers = browserslist(browsers).sort();
75 }
76 }
77
78 // Dont compile if we couldn't find any targets
79 if (Object.keys(targets).length === 0) {
80 return null;
81 }
82
83 return targets;
84}
85
86async function loadBrowserslist(config): Promise<?BrowserslistConfig> {
87 let browserslistConfig = await config.getConfig(
88 ['browserslist', '.browserslistrc'],
89 {
90 parse: false,
91 },
92 );
93
94 if (browserslistConfig) {
95 return browserslist.parseConfig(browserslistConfig.contents);
96 }
97}