Skip to content

Commit b6c781a

Browse files
fix: support extends with env for browserslist (#19964)
1 parent 3c08fd1 commit b6c781a

File tree

23 files changed

+416
-154
lines changed

23 files changed

+416
-154
lines changed

lib/config/browserslistTargetHandler.js

Lines changed: 28 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -15,59 +15,46 @@ const browserslist = require("browserslist");
1515
// [[C:]/path/to/config][:env]
1616
const inputRx = /^(?:((?:[A-Z]:)?[/\\].*?))?(?::(.+?))?$/i;
1717

18-
/**
19-
* @typedef {object} BrowserslistHandlerConfig
20-
* @property {string=} configPath
21-
* @property {string=} env
22-
* @property {string=} query
23-
*/
24-
2518
/**
2619
* @param {string | null | undefined} input input string
2720
* @param {string} context the context directory
28-
* @returns {BrowserslistHandlerConfig} config
21+
* @returns {string[] | undefined} selected browsers
2922
*/
30-
const parse = (input, context) => {
31-
if (!input) {
32-
return {};
33-
}
34-
35-
if (path.isAbsolute(input)) {
23+
const load = (input, context) => {
24+
// browserslist:path-to-config
25+
// browserslist:path-to-config:env
26+
if (input && path.isAbsolute(input)) {
3627
const [, configPath, env] = inputRx.exec(input) || [];
37-
return { configPath, env };
38-
}
3928

40-
const config = browserslist.findConfig(context);
29+
const config = browserslist.loadConfig({
30+
config: configPath,
31+
env
32+
});
4133

42-
if (config && Object.keys(config).includes(input)) {
43-
return { env: input };
34+
return browserslist(config, { env });
4435
}
4536

46-
return { query: input };
47-
};
37+
const env = input || undefined;
4838

49-
/**
50-
* @param {string | null | undefined} input input string
51-
* @param {string} context the context directory
52-
* @returns {string[] | undefined} selected browsers
53-
*/
54-
const load = (input, context) => {
55-
const { configPath, env, query } = parse(input, context);
39+
const config = browserslist.loadConfig({
40+
path: context,
41+
env
42+
});
5643

57-
// if a query is specified, then use it, else
58-
// if a path to a config is specified then load it, else
59-
// find a nearest config
60-
const config =
61-
query ||
62-
(configPath
63-
? browserslist.loadConfig({
64-
config: configPath,
65-
env
66-
})
67-
: browserslist.loadConfig({ path: context, env }));
44+
// browserslist
45+
// browserslist:env
46+
if (config) {
47+
try {
48+
return browserslist(config, { env, throwOnMissing: true });
49+
} catch (_err) {
50+
// Nothing, no `env` was found in browserslist, maybe input is `queries`
51+
}
52+
}
6853

69-
if (!config) return;
70-
return browserslist(config);
54+
// browserslist:query
55+
if (env) {
56+
return browserslist(env);
57+
}
7158
};
7259

7360
/**

lib/config/defaults.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1326,8 +1326,13 @@ const applyOutputDefaults = (
13261326
if (tp.importScripts) return "array-push";
13271327
throw new Error(
13281328
"For the selected environment is no default script chunk format available:\n" +
1329-
"JSONP Array push can be chosen when 'document' or 'importScripts' is available.\n" +
1330-
`CommonJs exports can be chosen when 'require' or node builtins are available.\n${
1329+
`${
1330+
tp.module
1331+
? "Module ('module') can be chosen when ES modules are available (please set 'experiments.outputModule' and 'output.module' to `true`)"
1332+
: ""
1333+
}\n` +
1334+
"JSONP Array push ('array-push') can be chosen when 'document' or 'importScripts' is available.\n" +
1335+
`CommonJs exports ('commonjs') can be chosen when 'require' or node builtins are available.\n${
13311336
helpMessage
13321337
}`
13331338
);

lib/config/target.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const getBrowserslistTargetHandler = memoize(() =>
1616
* @returns {string} default target
1717
*/
1818
const getDefaultTarget = (context) => {
19-
const browsers = getBrowserslistTargetHandler().load(null, context);
19+
const browsers = getBrowserslistTargetHandler().load(undefined, context);
2020
return browsers ? "browserslist" : "web";
2121
};
2222

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@
8989
"@webassemblyjs/wasm-parser": "^1.14.1",
9090
"acorn": "^8.15.0",
9191
"acorn-import-phases": "^1.0.3",
92-
"browserslist": "^4.24.5",
92+
"browserslist": "^4.26.3",
9393
"chrome-trace-event": "^1.0.2",
9494
"enhanced-resolve": "^5.17.3",
9595
"es-module-lexer": "^1.2.1",
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
extends browserslist-config-mycompany
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
it("should compile and run the test", function() {});
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
"use strict";
2+
3+
const fs = require("fs");
4+
const path = require("path");
5+
6+
const rootPath = path.resolve(__dirname, "../../../../");
7+
const rootNodeModules = path.resolve(rootPath, "./node_modules");
8+
const browserslistPackage = path.resolve(
9+
rootNodeModules,
10+
"browserslist-config-mycompany"
11+
);
12+
const content = `
13+
module.exports = {
14+
development: [
15+
'last 1 version'
16+
],
17+
production: [
18+
'ie 9',
19+
]
20+
}
21+
`;
22+
const browserslistFile = path.resolve(browserslistPackage, "./index.js");
23+
24+
try {
25+
fs.mkdirSync(browserslistPackage);
26+
} catch (_err) {
27+
// Nothing
28+
}
29+
30+
fs.writeFileSync(browserslistFile, content);
31+
32+
module.exports = {
33+
afterExecute() {
34+
fs.unlinkSync(browserslistFile);
35+
fs.rmdirSync(browserslistPackage);
36+
}
37+
};
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
"use strict";
2+
3+
const path = require("path");
4+
5+
/** @type {import("../../../../").Configuration} */
6+
module.exports = {
7+
target: `browserslist:${path.join(__dirname, ".browserslistrc")}:production`,
8+
plugins: [
9+
(compiler) => {
10+
compiler.hooks.compilation.tap("Test", (compilation) => {
11+
expect(compilation.outputOptions.environment).toMatchInlineSnapshot(`
12+
Object {
13+
"arrowFunction": false,
14+
"asyncFunction": false,
15+
"bigIntLiteral": false,
16+
"const": false,
17+
"destructuring": false,
18+
"document": true,
19+
"dynamicImport": false,
20+
"dynamicImportInWorker": false,
21+
"forOf": false,
22+
"globalThis": false,
23+
"module": false,
24+
"nodePrefixForCoreModules": false,
25+
"optionalChaining": false,
26+
"templateLiteral": false,
27+
}
28+
`);
29+
expect(compilation.options.externalsPresets).toMatchInlineSnapshot(`
30+
Object {
31+
"electron": false,
32+
"electronMain": false,
33+
"electronPreload": false,
34+
"electronRenderer": false,
35+
"node": false,
36+
"nwjs": false,
37+
"web": true,
38+
}
39+
`);
40+
});
41+
}
42+
]
43+
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
extends browserslist-config-mycompany1
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
it("should compile and run the test", function() {});

0 commit comments

Comments
 (0)