Skip to content

Commit

Permalink
perf: Speed up getTargets (#15228)
Browse files Browse the repository at this point in the history
  • Loading branch information
liuxingbaoyu committed Dec 5, 2022
1 parent 543c15a commit 00783f5
Show file tree
Hide file tree
Showing 9 changed files with 134 additions and 45 deletions.
40 changes: 40 additions & 0 deletions benchmark/babel-helper-compilation-targets/getTargets.mjs
@@ -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 changes: 2 additions & 0 deletions benchmark/package.json
Expand Up @@ -5,12 +5,14 @@
"devDependencies": {
"@babel-baseline/core": "npm:@babel/core@7.18.5",
"@babel-baseline/generator": "npm:@babel/generator@7.18.2",
"@babel-baseline/helper-compilation-targets": "npm:@babel/helper-compilation-targets@7.20.0",
"@babel-baseline/helper-validator-identifier": "npm:@babel/helper-validator-identifier@7.16.7",
"@babel-baseline/parser": "npm:@babel/parser@7.18.5",
"@babel-baseline/traverse": "npm:@babel/traverse@7.18.5",
"@babel-baseline/types": "npm:@babel/types@7.18.4",
"@babel/core": "workspace:^",
"@babel/generator": "workspace:^",
"@babel/helper-compilation-targets": "workspace:^",
"@babel/helper-validator-identifier": "workspace:^",
"@babel/parser": "workspace:^",
"@babel/preset-env": "workspace:^",
Expand Down
2 changes: 2 additions & 0 deletions packages/babel-helper-compilation-targets/package.json
Expand Up @@ -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": {
Expand All @@ -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": {
Expand Down
2 changes: 1 addition & 1 deletion packages/babel-helper-compilation-targets/src/debug.ts
Expand Up @@ -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);
Expand Down
36 changes: 26 additions & 10 deletions packages/babel-helper-compilation-targets/src/index.ts
@@ -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,
Expand Down Expand Up @@ -45,7 +46,7 @@ function validateTargetNames(targets: Targets): TargetsTuple {
}
}

return targets as any;
return targets;
}

export function isBrowsersQueryValid(browsers: unknown): boolean {
Expand All @@ -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;
Expand Down Expand Up @@ -108,7 +109,7 @@ function getLowestVersions(browsers: Array<string>): Targets {

function outputDecimalWarning(
decimalTargets: Array<{ target: string; value: number }>,
): void {
) {
if (!decimalTargets.length) {
return;
}
Expand All @@ -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) {
Expand All @@ -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(
Expand All @@ -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 {
Expand All @@ -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;
Expand All @@ -181,7 +194,7 @@ type GetTargetsOption = {
};

export default function getTargets(
inputTargets: InputTargets = {} as InputTargets,
inputTargets: InputTargets = {},
options: GetTargetsOption = {},
): Targets {
let { browsers, esmodules } = inputTargets;
Expand All @@ -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;
Expand Down Expand Up @@ -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[]) {
Expand All @@ -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];
Expand Down
6 changes: 3 additions & 3 deletions packages/babel-helper-compilation-targets/src/pretty.ts
Expand Up @@ -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);
Expand Down
6 changes: 2 additions & 4 deletions packages/babel-helper-compilation-targets/src/types.d.ts
Expand Up @@ -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>;
Expand Down
11 changes: 7 additions & 4 deletions packages/babel-helper-compilation-targets/src/utils.ts
Expand Up @@ -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(
Expand Down
74 changes: 51 additions & 23 deletions yarn.lock
Expand Up @@ -55,6 +55,20 @@ __metadata:
languageName: node
linkType: hard

"@babel-baseline/helper-compilation-targets@npm:@babel/helper-compilation-targets@7.20.0, @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/helper-validator-identifier@7.16.7":
version: 7.16.7
resolution: "@babel/helper-validator-identifier@npm:7.16.7"
Expand Down Expand Up @@ -154,12 +168,14 @@ __metadata:
dependencies:
"@babel-baseline/core": "npm:@babel/core@7.18.5"
"@babel-baseline/generator": "npm:@babel/generator@7.18.2"
"@babel-baseline/helper-compilation-targets": "npm:@babel/helper-compilation-targets@7.20.0"
"@babel-baseline/helper-validator-identifier": "npm:@babel/helper-validator-identifier@7.16.7"
"@babel-baseline/parser": "npm:@babel/parser@7.18.5"
"@babel-baseline/traverse": "npm:@babel/traverse@7.18.5"
"@babel-baseline/types": "npm:@babel/types@7.18.4"
"@babel/core": "workspace:^"
"@babel/generator": "workspace:^"
"@babel/helper-compilation-targets": "workspace:^"
"@babel/helper-validator-identifier": "workspace:^"
"@babel/parser": "workspace:^"
"@babel/preset-env": "workspace:^"
Expand Down Expand Up @@ -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"
Expand All @@ -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
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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"
Expand All @@ -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"
Expand Down

0 comments on commit 00783f5

Please sign in to comment.