Skip to content

Commit 4533276

Browse files
Add enableWorkspacePatternAnalysis configuration option
1 parent a592371 commit 4533276

File tree

5 files changed

+114
-4
lines changed

5 files changed

+114
-4
lines changed

.yarn/versions/607ebb1b.yml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
releases:
2+
"@yarnpkg/core": patch
3+
4+
declined:
5+
- "@yarnpkg/plugin-catalog"
6+
- "@yarnpkg/plugin-compat"
7+
- "@yarnpkg/plugin-constraints"
8+
- "@yarnpkg/plugin-dlx"
9+
- "@yarnpkg/plugin-essentials"
10+
- "@yarnpkg/plugin-exec"
11+
- "@yarnpkg/plugin-file"
12+
- "@yarnpkg/plugin-git"
13+
- "@yarnpkg/plugin-github"
14+
- "@yarnpkg/plugin-http"
15+
- "@yarnpkg/plugin-init"
16+
- "@yarnpkg/plugin-interactive-tools"
17+
- "@yarnpkg/plugin-jsr"
18+
- "@yarnpkg/plugin-link"
19+
- "@yarnpkg/plugin-nm"
20+
- "@yarnpkg/plugin-npm"
21+
- "@yarnpkg/plugin-npm-cli"
22+
- "@yarnpkg/plugin-pack"
23+
- "@yarnpkg/plugin-patch"
24+
- "@yarnpkg/plugin-pnp"
25+
- "@yarnpkg/plugin-pnpm"
26+
- "@yarnpkg/plugin-stage"
27+
- "@yarnpkg/plugin-typescript"
28+
- "@yarnpkg/plugin-version"
29+
- "@yarnpkg/plugin-workspace-tools"
30+
- "@yarnpkg/builder"
31+
- "@yarnpkg/cli"
32+
- "@yarnpkg/doctor"
33+
- "@yarnpkg/extensions"
34+
- "@yarnpkg/nm"
35+
- "@yarnpkg/pnpify"
36+
- "@yarnpkg/sdks"

packages/acceptance-tests/pkg-tests-specs/sources/commands/patchCommit.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ describe(`Commands`, () => {
114114
});
115115

116116
expect(manifest.resolutions).toEqual({
117-
[`no-deps@npm:1.0.0`]: expect.stringMatching(/^patch:no-deps/),
117+
[`no-deps@npm:1.0.0`]: expect.stringMatching(/^patch:no-deps/),
118118
});
119119
}),
120120
);

packages/acceptance-tests/pkg-tests-specs/sources/workspace.test.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,27 @@ describe(`Workspaces tests`, () => {
3535
}),
3636
);
3737

38+
test(
39+
`it should support basic glob patterns with enableWorkspacePatternAnalysis`,
40+
makeTemporaryMonorepoEnv({
41+
workspaces: [
42+
`packages/*`,
43+
],
44+
}, {
45+
[`packages/foo`]: {},
46+
[`packages/bar`]: {},
47+
[`packages/baz`]: {},
48+
}, async ({path, run, source}) => {
49+
await run(`config`, `set`, `enableWorkspacePatternAnalysis`, `true`);
50+
await expect(getWorkspaces(run)).resolves.toStrictEqual([
51+
`.`,
52+
`packages/bar`,
53+
`packages/baz`,
54+
`packages/foo`,
55+
]);
56+
}),
57+
);
58+
3859
test(
3960
`it should support negated glob patterns`,
4061
makeTemporaryMonorepoEnv({
@@ -55,6 +76,27 @@ describe(`Workspaces tests`, () => {
5576
}),
5677
);
5778

79+
test(
80+
`it should support negated glob patterns with enableWorkspacePatternAnalysis`,
81+
makeTemporaryMonorepoEnv({
82+
workspaces: [
83+
`packages/*`,
84+
`!packages/foo`,
85+
],
86+
}, {
87+
[`packages/foo`]: {},
88+
[`packages/bar`]: {},
89+
[`packages/baz`]: {},
90+
}, async ({path, run, source}) => {
91+
await run(`config`, `set`, `enableWorkspacePatternAnalysis`, `true`);
92+
await expect(getWorkspaces(run)).resolves.toStrictEqual([
93+
`.`,
94+
`packages/bar`,
95+
`packages/baz`,
96+
]);
97+
}),
98+
);
99+
58100
test(
59101
`it should not implicitly make workspaces require-able`,
60102
makeTemporaryEnv(

packages/yarnpkg-core/sources/Configuration.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,11 @@ export const coreDefinitions: {[coreSettingName: string]: SettingsDefinition} =
348348
type: SettingsType.STRING,
349349
default: `npm:`,
350350
},
351+
enableWorkspacePatternAnalysis: {
352+
description: `If true, optimizes workspace pattern matching by separating static and dynamic globs for better performance when using mostly static patterns.`,
353+
type: SettingsType.BOOLEAN,
354+
default: false,
355+
},
351356
enableTransparentWorkspaces: {
352357
description: `If false, Yarn won't automatically resolve workspace dependencies unless they use the \`workspace:\` protocol`,
353358
type: SettingsType.BOOLEAN,

packages/yarnpkg-core/sources/Workspace.ts

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,17 +48,44 @@ export class Workspace {
4848
// @ts-expect-error: It's ok to initialize it now, even if it's readonly (setup is called right after construction)
4949
this.anchoredLocator = structUtils.makeLocator(ident, `${WorkspaceResolver.protocol}${this.relativeCwd}`);
5050

51-
const patterns = this.manifest.workspaceDefinitions.map(({pattern}) => pattern);
51+
const workspaceDefinitionPatterns = this.manifest.workspaceDefinitions.map(({pattern}) => pattern);
5252

53-
if (patterns.length === 0)
53+
if (workspaceDefinitionPatterns.length === 0)
5454
return;
5555

56-
const relativeCwds = await fastGlob(patterns, {
56+
const getOptimizedRelativeCwds = async () => {
57+
const staticPatterns: Array<string> = [];
58+
const dynamicPatterns: Array<string> = [];
59+
60+
for (const pattern of workspaceDefinitionPatterns) {
61+
if (fastGlob.isDynamicPattern(pattern)) {
62+
dynamicPatterns.push(pattern);
63+
} else {
64+
staticPatterns.push(pattern);
65+
}
66+
}
67+
68+
const globResults = dynamicPatterns.length > 0
69+
? await resolveGlobPatterns(dynamicPatterns)
70+
: [];
71+
72+
return [...staticPatterns, ...globResults];
73+
};
74+
75+
const getStandardRelativeCwds = async () => {
76+
return resolveGlobPatterns(workspaceDefinitionPatterns);
77+
};
78+
79+
const resolveGlobPatterns = async (globPatterns: Array<string>) => fastGlob(globPatterns, {
5780
cwd: npath.fromPortablePath(this.cwd),
5881
onlyDirectories: true,
5982
ignore: [`**/node_modules`, `**/.git`, `**/.yarn`],
6083
});
6184

85+
const relativeCwds = this.project.configuration.get(`enableWorkspacePatternAnalysis`) ?
86+
await getOptimizedRelativeCwds() :
87+
await getStandardRelativeCwds();
88+
6289
// fast-glob returns results in arbitrary order
6390
relativeCwds.sort();
6491

0 commit comments

Comments
 (0)