Skip to content

Include basePath in resolver cache file, instead of being external #4906

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions common/changes/@microsoft/rush/base-path_2024-08-27-21-36.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@microsoft/rush",
"comment": "In rush-resolver-cache-plugin, include the base path in the resolver cache file.",
"type": "none"
}
],
"packageName": "@microsoft/rush"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@rushstack/webpack-workspace-resolve-plugin",
"comment": "Expect the base path to be part of the resolver cache file.",
"type": "minor"
}
],
"packageName": "@rushstack/webpack-workspace-resolve-plugin"
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export interface IResolveContext {

// @beta
export interface IResolverCacheFile {
basePath: string;
contexts: ISerializedResolveContext[];
}

Expand All @@ -35,7 +36,6 @@ export interface ISerializedResolveContext {
export interface IWorkspaceLayoutCacheOptions {
cacheData: IResolverCacheFile;
resolverPathSeparator?: '/' | '\\';
workspaceRoot: string;
}

// @beta
Expand Down
2 changes: 1 addition & 1 deletion rush-plugins/rush-resolver-cache-plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ A Rush plugin that runs after successful dependency installation and generates a

When this plugin is installed, it will produce a file called `resolver-cache.json` in the temp directory of the default subspace, e.g. `<repo>/common/temp/default/resolver-cache.json`

To use this file, load it, call JSON.parse, and pass the result as the `cacheData` property to the `WorkspaceLayoutCache` constructor from `@rushstack/webpack-workspace-resolve-plugin`. The `workspaceRoot` property should be set to the path `<repo>`.
To use this file, load it, call JSON.parse, and pass the result as the `cacheData` property to the `WorkspaceLayoutCache` constructor from `@rushstack/webpack-workspace-resolve-plugin`.
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ export async function computeResolverCacheFromLockfileAsync(
);

const cacheFile: IResolverCacheFile = {
basePath: commonPrefixToTrim,
contexts: serializedContexts
};

Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,17 @@ interface ITestCase {
const TEST_CASES: readonly ITestCase[] = [
{
workspaceRoot: '/$root/common/temp/build-tests',
commonPrefixToTrim: '/$root',
commonPrefixToTrim: '/$root/',
lockfileName: 'build-tests-subspace.yaml'
},
{
workspaceRoot: '/$root/common/temp/default',
commonPrefixToTrim: '/$root',
commonPrefixToTrim: '/$root/',
lockfileName: 'default-subspace.yaml'
},
{
workspaceRoot: '/$root/common/temp/bundled-dependencies',
commonPrefixToTrim: '/$root',
commonPrefixToTrim: '/$root/',
lockfileName: 'bundled-dependencies.yaml',
afterExternalPackagesAsync: async (contexts: Map<string, IResolverContext>) => {
for (const context of contexts.values()) {
Expand Down Expand Up @@ -105,7 +105,7 @@ describe(computeResolverCacheFromLockfileAsync.name, () => {
for (const importerPath of lockfile.importers.keys()) {
const remainder: string = importerPath.slice(importerPath.lastIndexOf('../') + 3);
projectByImporterPath.setItem(importerPath, {
projectFolder: `${commonPrefixToTrim}/${remainder}`,
projectFolder: `${commonPrefixToTrim}${remainder}`,
packageJson: {
name: `@local/${remainder.replace(/\//g, '+')}`
}
Expand Down
8 changes: 8 additions & 0 deletions webpack/webpack-workspace-resolve-plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ When using this plugin, the following options should be configured for your reso
- `symlinks: false` - Since the cache knows the symlinks for package dependencies, you can avoid the cost of testing for other symlinks unless you are using additional symlinks.
- `modules: []` - The cache should contain all information necessary to locate available dependencies for any arbitrary folder. If you need to allow resolution in other roots, you can add those, but omit `'node_modules'`.

## Impact

This plugin should eliminate file system calls associated with the following operations of NodeJS module resolution in webpack:
- Find the nearest `package.json` to the calling module
- Locate a named package from a calling module
- Identify a `package.json` in a resolved directory
- Find the nearest `package.json` to a resolved file path

## Limitations

This plugin depends on the presence of a cache file in the workspace to function. Data in this cache file is assumed not to change while the webpack process is running.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ export interface ISerializedResolveContext {
* @beta
*/
export interface IResolverCacheFile {
/**
* The base path. All paths in context entries are prefixed by this path.
*/
basePath: string;
/**
* The ordered list of all contexts in the cache
*/
Expand Down Expand Up @@ -64,10 +68,6 @@ export interface IResolveContext {
* @beta
*/
export interface IWorkspaceLayoutCacheOptions {
/**
* The root folder of the workspace. All paths in the cache file are assumed to be relative to this folder.
*/
workspaceRoot: string;
/**
* The parsed cache data. File reading is left as an exercise for the caller.
*/
Expand Down Expand Up @@ -114,12 +114,13 @@ export class WorkspaceLayoutCache {
public readonly normalizeToPlatform: IPathNormalizationFunction;

public constructor(options: IWorkspaceLayoutCacheOptions) {
const { workspaceRoot, cacheData, resolverPathSeparator = directorySeparator } = options;
const { cacheData, resolverPathSeparator = directorySeparator } = options;

if (resolverPathSeparator !== '/' && resolverPathSeparator !== '\\') {
throw new Error(`Unsupported directory separator: ${resolverPathSeparator}`);
}

const { basePath } = cacheData;
const resolveContexts: ResolveContext[] = [];
const contextLookup: LookupByPath<IResolveContext> = new LookupByPath(undefined, resolverPathSeparator);

Expand Down Expand Up @@ -149,7 +150,7 @@ export class WorkspaceLayoutCache {

public get descriptionFileRoot(): string {
if (!this._descriptionFileRoot) {
this._descriptionFileRoot = `${workspaceRoot}${resolverPathSeparator}${
this._descriptionFileRoot = `${basePath}${
normalizeToPlatform?.(this._serialized.root) ?? this._serialized.root
}`;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ export function createResolveForTests(
const fileSystem: Volume = new Volume();

const cache: WorkspaceLayoutCache = new WorkspaceLayoutCache({
workspaceRoot: `${separator}workspace`,
cacheData: {
basePath: `${separator}workspace${separator}`,
contexts: [
{
root: 'a',
Expand Down
Loading