perf: Speed up getTargets (#15228)

This commit is contained in:
liuxingbaoyu
2022-12-05 11:57:20 +01:00
committed by GitHub
parent b2faa8df66
commit 80e95fd19e
9 changed files with 134 additions and 45 deletions
@@ -0,0 +1,40 @@
import Benchmark from "benchmark";
import baseline from "@babel-baseline/helper-compilation-targets";
import current from "@babel/helper-compilation-targets";
import { report } from "../util.mjs";
const suite = new Benchmark.Suite("", { initCount: 0 });
function benchCases(implementation, name) {
suite.add(name + "#getTargets last1", () => {
implementation({
browsers: [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version",
"last 1 iOS version",
"last 1 edge version",
],
});
});
suite.add(name + "#getTargets last100", () => {
implementation({
browsers: [
"last 100 chrome version",
"last 100 firefox version",
"last 100 safari version",
"last 100 iOS version",
"last 100 edge version",
],
});
});
suite.add(name + "#getTargets chrome 49 ie 11", () => {
implementation({
browsers: ["chrome 49", "ie 11"],
});
});
}
benchCases(baseline.default, "baseline");
benchCases(current.default, "current");
suite.on("cycle", report).run();
+2
View File
@@ -5,12 +5,14 @@
"devDependencies": {
"@babel-baseline/core": "npm:@babel/[email protected]",
"@babel-baseline/generator": "npm:@babel/[email protected]",
"@babel-baseline/helper-compilation-targets": "npm:@babel/[email protected]",
"@babel-baseline/helper-validator-identifier": "npm:@babel/[email protected]",
"@babel-baseline/parser": "npm:@babel/[email protected]",
"@babel-baseline/traverse": "npm:@babel/[email protected]",
"@babel-baseline/types": "npm:@babel/[email protected]",
"@babel/core": "workspace:^",
"@babel/generator": "workspace:^",
"@babel/helper-compilation-targets": "workspace:^",
"@babel/helper-validator-identifier": "workspace:^",
"@babel/parser": "workspace:^",
"@babel/preset-env": "workspace:^",
@@ -25,6 +25,7 @@
"@babel/compat-data": "workspace:^",
"@babel/helper-validator-option": "workspace:^",
"browserslist": "^4.21.3",
"lru-cache": "condition:BABEL_8_BREAKING ? ^7.14.1 : ^5.1.1",
"semver": "condition:BABEL_8_BREAKING ? ^7.3.4 : ^6.3.0"
},
"peerDependencies": {
@@ -33,6 +34,7 @@
"devDependencies": {
"@babel/core": "workspace:^",
"@babel/helper-plugin-test-runner": "workspace:^",
"@types/lru-cache": "^5.1.1",
"@types/semver": "^5.5.0"
},
"engines": {
@@ -12,7 +12,7 @@ export function getInclusionReasons(
targetVersions: Targets,
list: { [key: string]: Targets },
) {
const minVersions = list[item] || ({} as Targets);
const minVersions = list[item] || {};
return (Object.keys(targetVersions) as Target[]).reduce((result, env) => {
const minVersion = getLowestImplementedVersion(minVersions, env);
@@ -1,6 +1,7 @@
import browserslist from "browserslist";
import { findSuggestion } from "@babel/helper-validator-option";
import browserModulesData from "@babel/compat-data/native-modules";
import LruCache from "lru-cache";
import {
semverify,
@@ -45,7 +46,7 @@ function validateTargetNames(targets: Targets): TargetsTuple {
}
}
return targets as any;
return targets;
}
export function isBrowsersQueryValid(browsers: unknown): boolean {
@@ -70,7 +71,7 @@ function getLowestVersions(browsers: Array<string>): Targets {
BrowserslistBrowserName,
string,
];
const target: Target = browserNameMap[browserName];
const target = browserNameMap[browserName];
if (!target) {
return all;
@@ -108,7 +109,7 @@ function getLowestVersions(browsers: Array<string>): Targets {
function outputDecimalWarning(
decimalTargets: Array<{ target: string; value: number }>,
): void {
) {
if (!decimalTargets.length) {
return;
}
@@ -123,7 +124,7 @@ getting parsed as 6.1, which can lead to unexpected behavior.
`);
}
function semverifyTarget(target: keyof Targets, value: string) {
function semverifyTarget(target: Target, value: string) {
try {
return semverify(value);
} catch (error) {
@@ -141,7 +142,7 @@ function nodeTargetParser(value: true | string) {
value === true || value === "current"
? process.versions.node
: semverifyTarget("node", value);
return ["node" as const, parsed] as const;
return ["node", parsed] as const;
}
function defaultTargetParser(
@@ -158,7 +159,7 @@ function generateTargets(inputTargets: InputTargets): Targets {
const input = { ...inputTargets };
delete input.esmodules;
delete input.browsers;
return input as any as Targets;
return input;
}
function resolveTargets(queries: Browsers, env?: string): Targets {
@@ -169,6 +170,18 @@ function resolveTargets(queries: Browsers, env?: string): Targets {
return getLowestVersions(resolved);
}
const targetsCache = new LruCache({ max: 64 });
function resolveTargetsCached(queries: Browsers, env?: string): Targets {
const cacheKey = typeof queries === "string" ? queries : queries.join() + env;
let cached = targetsCache.get(cacheKey) as Targets | undefined;
if (!cached) {
cached = resolveTargets(queries, env);
targetsCache.set(cacheKey, cached);
}
return { ...cached };
}
type GetTargetsOption = {
// This is not the path of the config file, but the path where start searching it from
configPath?: string;
@@ -181,7 +194,7 @@ type GetTargetsOption = {
};
export default function getTargets(
inputTargets: InputTargets = {} as InputTargets,
inputTargets: InputTargets = {},
options: GetTargetsOption = {},
): Targets {
let { browsers, esmodules } = inputTargets;
@@ -190,7 +203,7 @@ export default function getTargets(
validateBrowsers(browsers);
const input = generateTargets(inputTargets);
let targets: TargetsTuple = validateTargetNames(input);
let targets = validateTargetNames(input);
const shouldParseBrowsers = !!browsers;
const hasTargets = shouldParseBrowsers || Object.keys(targets).length > 0;
@@ -233,7 +246,10 @@ export default function getTargets(
// or an empty array (without any user config, use default config),
// we don't need to call `resolveTargets` to execute the related methods of `browserslist` library.
if (browsers?.length) {
const queryBrowsers = resolveTargets(browsers, options.browserslistEnv);
const queryBrowsers = resolveTargetsCached(
browsers,
options.browserslistEnv,
);
if (esmodules === "intersect") {
for (const browser of Object.keys(queryBrowsers) as Target[]) {
@@ -258,7 +274,7 @@ export default function getTargets(
}
// Parse remaining targets
const result: Targets = {} as Targets;
const result: Targets = {};
const decimalWarnings = [];
for (const target of Object.keys(targets).sort() as Target[]) {
const value = targets[target];
@@ -7,9 +7,9 @@ export function prettifyVersion(version: string) {
return version;
}
const parts = [semver.major(version)];
const minor = semver.minor(version);
const patch = semver.patch(version);
const { major, minor, patch } = semver.parse(version);
const parts = [major];
if (minor || patch) {
parts.push(minor);
+2 -4
View File
@@ -17,10 +17,8 @@ export type Targets = {
[target in Target]?: string;
};
export type TargetsTuple = {
[target in Exclude<Target, "node">]: string;
} & {
node: string | true;
export type TargetsTuple = Omit<Targets, "node"> & {
node?: string | true;
};
export type Browsers = string | ReadonlyArray<string>;
@@ -29,11 +29,14 @@ export function semverify(version: number | string): string {
`'${version}' is not a valid version`,
);
const split = version.toString().split(".");
while (split.length < 3) {
split.push("0");
version = version.toString();
let pos = 0;
let num = 0;
while ((pos = version.indexOf(".", pos + 1)) > 0) {
num++;
}
return split.join(".");
return version + ".0".repeat(2 - num);
}
export function isUnreleasedVersion(
+51 -23
View File
@@ -55,6 +55,20 @@ __metadata:
languageName: node
linkType: hard
"@babel-baseline/helper-compilation-targets@npm:@babel/[email protected], @babel/helper-compilation-targets@npm:^7.17.7, @babel/helper-compilation-targets@npm:^7.18.2, @babel/helper-compilation-targets@npm:^7.18.9, @babel/helper-compilation-targets@npm:^7.20.0":
version: 7.20.0
resolution: "@babel/helper-compilation-targets@npm:7.20.0"
dependencies:
"@babel/compat-data": ^7.20.0
"@babel/helper-validator-option": ^7.18.6
browserslist: ^4.21.3
semver: ^6.3.0
peerDependencies:
"@babel/core": ^7.0.0
checksum: bc183f2109648849c8fde0b3c5cf08adf2f7ad6dc617b546fd20f34c8ef574ee5ee293c8d1bd0ed0221212e8f5907cdc2c42097870f1dcc769a654107d82c95b
languageName: node
linkType: hard
"@babel-baseline/helper-validator-identifier@npm:@babel/[email protected]":
version: 7.16.7
resolution: "@babel/helper-validator-identifier@npm:7.16.7"
@@ -154,12 +168,14 @@ __metadata:
dependencies:
"@babel-baseline/core": "npm:@babel/[email protected]"
"@babel-baseline/generator": "npm:@babel/[email protected]"
"@babel-baseline/helper-compilation-targets": "npm:@babel/[email protected]"
"@babel-baseline/helper-validator-identifier": "npm:@babel/[email protected]"
"@babel-baseline/parser": "npm:@babel/[email protected]"
"@babel-baseline/traverse": "npm:@babel/[email protected]"
"@babel-baseline/types": "npm:@babel/[email protected]"
"@babel/core": "workspace:^"
"@babel/generator": "workspace:^"
"@babel/helper-compilation-targets": "workspace:^"
"@babel/helper-validator-identifier": "workspace:^"
"@babel/parser": "workspace:^"
"@babel/preset-env": "workspace:^"
@@ -528,20 +544,6 @@ __metadata:
languageName: unknown
linkType: soft
"@babel/helper-compilation-targets@npm:^7.17.7, @babel/helper-compilation-targets@npm:^7.18.2, @babel/helper-compilation-targets@npm:^7.18.9, @babel/helper-compilation-targets@npm:^7.20.0":
version: 7.20.0
resolution: "@babel/helper-compilation-targets@npm:7.20.0"
dependencies:
"@babel/compat-data": ^7.20.0
"@babel/helper-validator-option": ^7.18.6
browserslist: ^4.21.3
semver: ^6.3.0
peerDependencies:
"@babel/core": ^7.0.0
checksum: bc183f2109648849c8fde0b3c5cf08adf2f7ad6dc617b546fd20f34c8ef574ee5ee293c8d1bd0ed0221212e8f5907cdc2c42097870f1dcc769a654107d82c95b
languageName: node
linkType: hard
"@babel/helper-compilation-targets@workspace:^, @babel/helper-compilation-targets@workspace:packages/babel-helper-compilation-targets":
version: 0.0.0-use.local
resolution: "@babel/helper-compilation-targets@workspace:packages/babel-helper-compilation-targets"
@@ -550,8 +552,10 @@ __metadata:
"@babel/core": "workspace:^"
"@babel/helper-plugin-test-runner": "workspace:^"
"@babel/helper-validator-option": "workspace:^"
"@types/lru-cache": ^5.1.1
"@types/semver": ^5.5.0
browserslist: ^4.21.3
lru-cache: "condition:BABEL_8_BREAKING ? ^7.14.1 : ^5.1.1"
semver: "condition:BABEL_8_BREAKING ? ^7.3.4 : ^6.3.0"
peerDependencies:
"@babel/core": ^7.0.0
@@ -4553,6 +4557,13 @@ __metadata:
languageName: node
linkType: hard
"@types/lru-cache@npm:^5.1.1":
version: 5.1.1
resolution: "@types/lru-cache@npm:5.1.1"
checksum: e1d6c0085f61b16ec5b3073ec76ad1be4844ea036561c3f145fc19f71f084b58a6eb600b14128aa95809d057d28f1d147c910186ae51219f58366ffd2ff2e118
languageName: node
linkType: hard
"@types/minimatch@npm:*, @types/minimatch@npm:^3.0.3":
version: 3.0.5
resolution: "@types/minimatch@npm:3.0.5"
@@ -11157,6 +11168,32 @@ fsevents@^1.2.7:
languageName: node
linkType: hard
"lru-cache-BABEL_8_BREAKING-false@npm:lru-cache@^5.1.1, lru-cache@npm:^5.1.1":
version: 5.1.1
resolution: "lru-cache@npm:5.1.1"
dependencies:
yallist: ^3.0.2
checksum: c154ae1cbb0c2206d1501a0e94df349653c92c8cbb25236d7e85190bcaf4567a03ac6eb43166fabfa36fd35623694da7233e88d9601fbf411a9a481d85dbd2cb
languageName: node
linkType: hard
"lru-cache-BABEL_8_BREAKING-true@npm:lru-cache@^7.14.1":
version: 7.14.1
resolution: "lru-cache@npm:7.14.1"
checksum: d72c6713c6a6d86836a7a6523b3f1ac6764768cca47ec99341c3e76db06aacd4764620e5e2cda719a36848785a52a70e531822dc2b33fb071fa709683746c104
languageName: node
linkType: hard
"lru-cache@condition:BABEL_8_BREAKING ? ^7.14.1 : ^5.1.1":
version: 0.0.0-condition-86c673
resolution: "lru-cache@condition:BABEL_8_BREAKING?^7.14.1:^5.1.1#86c673"
dependencies:
lru-cache-BABEL_8_BREAKING-false: "npm:lru-cache@^5.1.1"
lru-cache-BABEL_8_BREAKING-true: "npm:lru-cache@^7.14.1"
checksum: 9a90e9b7fff14a71bd363ac5e40cea193f2da3380ca92d012589d3da49cc6af9c9a8399fc59b57b206e62753347ff4d77769a1e3bc0dd5550f3a8225a1a78a9a
languageName: node
linkType: hard
"lru-cache@npm:^4.0.1":
version: 4.1.5
resolution: "lru-cache@npm:4.1.5"
@@ -11167,15 +11204,6 @@ fsevents@^1.2.7:
languageName: node
linkType: hard
"lru-cache@npm:^5.1.1":
version: 5.1.1
resolution: "lru-cache@npm:5.1.1"
dependencies:
yallist: ^3.0.2
checksum: c154ae1cbb0c2206d1501a0e94df349653c92c8cbb25236d7e85190bcaf4567a03ac6eb43166fabfa36fd35623694da7233e88d9601fbf411a9a481d85dbd2cb
languageName: node
linkType: hard
"lru-cache@npm:^6.0.0":
version: 6.0.0
resolution: "lru-cache@npm:6.0.0"