Skip to content

Commit cca07c9

Browse files
authored
[workspace-resolve] Allow configuration of which resolvers to apply to (#5074)
* [workspace-resolve] Allow configuration Monomorphic request object. * Update default --------- Co-authored-by: David Michon <[email protected]>
1 parent a15fef5 commit cca07c9

File tree

6 files changed

+93
-47
lines changed

6 files changed

+93
-47
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"changes": [
3+
{
4+
"packageName": "@rushstack/webpack-workspace-resolve-plugin",
5+
"comment": "(BREAKING CHANGE) Switch constructor to an options object. Add option to specify which webpack resolvers to apply the plugin to. Improve performance by using an object literal instead of the spread operator when updating the resolve request. Upgrade compilation target to not polyfill optional chaining.",
6+
"type": "minor"
7+
}
8+
],
9+
"packageName": "@rushstack/webpack-workspace-resolve-plugin"
10+
}

common/reviews/api/webpack-workspace-resolve-plugin.api.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export interface IWorkspaceLayoutCacheOptions {
4141
// @beta
4242
export interface IWorkspaceResolvePluginOptions {
4343
cache: WorkspaceLayoutCache;
44+
resolverNames?: Iterable<string>;
4445
}
4546

4647
// @beta
@@ -58,7 +59,7 @@ export class WorkspaceLayoutCache {
5859

5960
// @beta
6061
export class WorkspaceResolvePlugin implements WebpackPluginInstance {
61-
constructor(cache: WorkspaceLayoutCache);
62+
constructor(options: IWorkspaceResolvePluginOptions);
6263
// (undocumented)
6364
apply(compiler: Compiler): void;
6465
}

webpack/webpack-workspace-resolve-plugin/src/KnownDescriptionFilePlugin.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,12 +96,27 @@ export class KnownDescriptionFilePlugin {
9696
// Store the resolver context since a WeakMap lookup is cheaper than walking the tree again
9797
contextForPackage.set(descriptionFileData, match);
9898

99+
// Using the object literal is an order of magnitude faster, at least on node 18.19.1
99100
const obj: ResolveRequest = {
100-
...request,
101-
descriptionFileRoot,
101+
path: request.path,
102+
context: request.context,
102103
descriptionFilePath,
104+
descriptionFileRoot,
103105
descriptionFileData,
104-
relativePath
106+
relativePath,
107+
ignoreSymlinks: request.ignoreSymlinks,
108+
fullySpecified: request.fullySpecified,
109+
__innerRequest: request.__innerRequest,
110+
__innerRequest_request: request.__innerRequest_request,
111+
__innerRequest_relativePath: request.__innerRequest_relativePath,
112+
113+
request: request.request,
114+
query: request.query,
115+
fragment: request.fragment,
116+
module: request.module,
117+
directory: request.directory,
118+
file: request.file,
119+
internal: request.internal
105120
};
106121

107122
// Delegate to the resolver step at `target`.

webpack/webpack-workspace-resolve-plugin/src/KnownPackageDependenciesPlugin.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,16 +80,25 @@ export class KnownPackageDependenciesPlugin {
8080
(remainingPath.length > 1 && cache.normalizeToSlash?.(remainingPath)) || remainingPath;
8181
const { descriptionFileRoot } = dependency.value;
8282
const obj: ResolveRequest = {
83-
...request,
8483
path: descriptionFileRoot,
84+
context: request.context,
85+
descriptionFilePath: `${descriptionFileRoot}${cache.resolverPathSeparator}package.json`,
8586
descriptionFileRoot,
8687
descriptionFileData: undefined,
87-
descriptionFilePath: `${descriptionFileRoot}${cache.resolverPathSeparator}package.json`,
88+
relativePath,
89+
ignoreSymlinks: request.ignoreSymlinks,
90+
fullySpecified,
91+
__innerRequest: request.__innerRequest,
92+
__innerRequest_request: request.__innerRequest_request,
93+
__innerRequest_relativePath: request.__innerRequest_relativePath,
8894

89-
relativePath: relativePath,
9095
request: relativePath,
91-
fullySpecified,
92-
module: false
96+
query: request.query,
97+
fragment: request.fragment,
98+
module: false,
99+
directory: request.directory,
100+
file: request.file,
101+
internal: request.internal
93102
};
94103
// eslint-disable-next-line @rushstack/no-new-null
95104
resolver.doResolve(target, obj, null, resolveContext, callback);
Lines changed: 48 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
22
// See LICENSE in the project root for license information.
33

4-
import type { WebpackPluginInstance, Compiler } from 'webpack';
4+
import type { WebpackPluginInstance, Compiler, ResolveOptions } from 'webpack';
55

66
import type { WorkspaceLayoutCache } from './WorkspaceLayoutCache';
77
import { KnownDescriptionFilePlugin } from './KnownDescriptionFilePlugin';
@@ -17,6 +17,12 @@ export interface IWorkspaceResolvePluginOptions {
1717
* The cache of workspace layout information.
1818
*/
1919
cache: WorkspaceLayoutCache;
20+
21+
/**
22+
* Which webpack resolvers to apply the plugin to.
23+
* @defaultValue ['normal', 'context', 'loader']
24+
*/
25+
resolverNames?: Iterable<string>;
2026
}
2127

2228
/**
@@ -26,48 +32,53 @@ export interface IWorkspaceResolvePluginOptions {
2632
*/
2733
export class WorkspaceResolvePlugin implements WebpackPluginInstance {
2834
private readonly _cache: WorkspaceLayoutCache;
35+
private readonly _resolverNames: Set<string>;
2936

30-
public constructor(cache: WorkspaceLayoutCache) {
31-
this._cache = cache;
37+
public constructor(options: IWorkspaceResolvePluginOptions) {
38+
this._cache = options.cache;
39+
this._resolverNames = new Set(options.resolverNames ?? ['normal', 'context', 'loader']);
3240
}
3341

3442
public apply(compiler: Compiler): void {
35-
compiler.resolverFactory.hooks.resolveOptions
36-
.for('normal')
37-
.tap(WorkspaceResolvePlugin.name, (resolveOptions) => {
38-
// Omit default `node_modules`
39-
if (resolveOptions.modules) {
40-
resolveOptions.modules = resolveOptions.modules.filter((modulePath: string) => {
41-
return modulePath !== 'node_modules';
42-
});
43-
} else {
44-
resolveOptions.modules = [];
45-
}
43+
const cache: WorkspaceLayoutCache = this._cache;
4644

47-
const cache: WorkspaceLayoutCache = this._cache;
45+
function handler(resolveOptions: ResolveOptions): ResolveOptions {
46+
// Omit default `node_modules`
47+
if (resolveOptions.modules) {
48+
resolveOptions.modules = resolveOptions.modules.filter((modulePath: string) => {
49+
return modulePath !== 'node_modules';
50+
});
51+
} else {
52+
resolveOptions.modules = [];
53+
}
4854

49-
resolveOptions.plugins ??= [];
50-
resolveOptions.plugins.push(
51-
// Optimize identifying the package.json file for the issuer
52-
new KnownDescriptionFilePlugin(cache, 'before-parsed-resolve', 'described-resolve'),
53-
// Optimize locating the installed dependencies of the current package
54-
new KnownPackageDependenciesPlugin(cache, 'before-raw-module', 'resolve-as-module'),
55-
// Optimize loading the package.json file for the destination package (bare specifier)
56-
new KnownDescriptionFilePlugin(cache, 'before-resolve-as-module', 'resolve-in-package'),
57-
// Optimize loading the package.json file for the destination package (relative path)
58-
new KnownDescriptionFilePlugin(cache, 'before-relative', 'described-relative'),
59-
// Optimize locating and loading nested package.json for a directory
60-
new KnownDescriptionFilePlugin(
61-
cache,
62-
'before-undescribed-existing-directory',
63-
'existing-directory',
64-
true
65-
),
66-
// Optimize locating and loading nested package.json for a file
67-
new KnownDescriptionFilePlugin(cache, 'before-undescribed-raw-file', 'raw-file')
68-
);
55+
resolveOptions.plugins ??= [];
56+
resolveOptions.plugins.push(
57+
// Optimize identifying the package.json file for the issuer
58+
new KnownDescriptionFilePlugin(cache, 'before-parsed-resolve', 'described-resolve'),
59+
// Optimize locating the installed dependencies of the current package
60+
new KnownPackageDependenciesPlugin(cache, 'before-raw-module', 'resolve-as-module'),
61+
// Optimize loading the package.json file for the destination package (bare specifier)
62+
new KnownDescriptionFilePlugin(cache, 'before-resolve-as-module', 'resolve-in-package'),
63+
// Optimize loading the package.json file for the destination package (relative path)
64+
new KnownDescriptionFilePlugin(cache, 'before-relative', 'described-relative'),
65+
// Optimize locating and loading nested package.json for a directory
66+
new KnownDescriptionFilePlugin(
67+
cache,
68+
'before-undescribed-existing-directory',
69+
'existing-directory',
70+
true
71+
),
72+
// Optimize locating and loading nested package.json for a file
73+
new KnownDescriptionFilePlugin(cache, 'before-undescribed-raw-file', 'raw-file')
74+
);
6975

70-
return resolveOptions;
71-
});
76+
return resolveOptions;
77+
}
78+
for (const resolverName of this._resolverNames) {
79+
compiler.resolverFactory.hooks.resolveOptions
80+
.for(resolverName)
81+
.tap(WorkspaceResolvePlugin.name, handler);
82+
}
7283
}
7384
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"extends": "./node_modules/local-node-rig/profiles/default/tsconfig-base.json",
33
"compilerOptions": {
4-
"target": "ES2019",
4+
"target": "ES2020",
55
"types": ["heft-jest", "node"]
66
}
77
}

0 commit comments

Comments
 (0)