Skip to content

fix(@angular/build): prevent transformation of Node.js internal dependencies by Vite #28393

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 1 commit into from
Sep 11, 2024
Merged
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
33 changes: 21 additions & 12 deletions packages/angular/build/src/builders/dev-server/vite-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ interface OutputFileRecord {
type: BuildOutputFileType;
}

interface DevServerExternalResultMetadata extends Omit<ExternalResultMetadata, 'explicit'> {
explicitBrowser: string[];
explicitServer: string[];
}

export type BuilderAction = (
options: ApplicationBuilderInternalOptions,
context: BuilderContext,
Expand Down Expand Up @@ -140,10 +145,11 @@ export async function* serveWithVite(
let hadError = false;
const generatedFiles = new Map<string, OutputFileRecord>();
const assetFiles = new Map<string, string>();
const externalMetadata: ExternalResultMetadata = {
const externalMetadata: DevServerExternalResultMetadata = {
implicitBrowser: [],
implicitServer: [],
explicit: [],
explicitBrowser: [],
explicitServer: [],
};

// Add cleanup logic via a builder teardown.
Expand Down Expand Up @@ -236,17 +242,20 @@ export async function* serveWithVite(
}

// Empty Arrays to avoid growing unlimited with every re-build.
externalMetadata.explicit.length = 0;
externalMetadata.explicitBrowser.length = 0;
externalMetadata.explicitServer.length = 0;
externalMetadata.implicitServer.length = 0;
externalMetadata.implicitBrowser.length = 0;

externalMetadata.explicit.push(...explicit);
externalMetadata.explicitBrowser.push(...explicit);
externalMetadata.explicitServer.push(...explicit, ...nodeJsBuiltinModules);
externalMetadata.implicitServer.push(...implicitServerFiltered);
externalMetadata.implicitBrowser.push(...implicitBrowserFiltered);

// The below needs to be sorted as Vite uses these options are part of the hashing invalidation algorithm.
// See: https://github.com/vitejs/vite/blob/0873bae0cfe0f0718ad2f5743dd34a17e4ab563d/packages/vite/src/node/optimizer/index.ts#L1203-L1239
externalMetadata.explicit.sort();
externalMetadata.explicitBrowser.sort();
externalMetadata.explicitServer.sort();
externalMetadata.implicitServer.sort();
externalMetadata.implicitBrowser.sort();
}
Expand Down Expand Up @@ -494,7 +503,7 @@ export async function setupServer(
outputFiles: Map<string, OutputFileRecord>,
assets: Map<string, string>,
preserveSymlinks: boolean | undefined,
externalMetadata: ExternalResultMetadata,
externalMetadata: DevServerExternalResultMetadata,
ssr: boolean,
prebundleTransformer: JavaScriptTransformer,
target: string[],
Expand Down Expand Up @@ -573,18 +582,18 @@ export async function setupServer(
},
// This is needed when `externalDependencies` is used to prevent Vite load errors.
// NOTE: If Vite adds direct support for externals, this can be removed.
preTransformRequests: externalMetadata.explicit.length === 0,
preTransformRequests: externalMetadata.explicitBrowser.length === 0,
},
ssr: {
// Note: `true` and `/.*/` have different sematics. When true, the `external` option is ignored.
noExternal: /.*/,
// Exclude any Node.js built in module and provided dependencies (currently build defined externals)
external: externalMetadata.explicit,
external: externalMetadata.explicitServer,
optimizeDeps: getDepOptimizationConfig({
// Only enable with caching since it causes prebundle dependencies to be cached
disabled: serverOptions.prebundle === false,
// Exclude any explicitly defined dependencies (currently build defined externals and node.js built-ins)
exclude: externalMetadata.explicit,
exclude: externalMetadata.explicitServer,
// Include all implict dependencies from the external packages internal option
include: externalMetadata.implicitServer,
ssr: true,
Expand All @@ -603,19 +612,19 @@ export async function setupServer(
outputFiles,
assets,
ssr,
external: externalMetadata.explicit,
external: externalMetadata.explicitBrowser,
indexHtmlTransformer,
extensionMiddleware,
normalizePath,
}),
createRemoveIdPrefixPlugin(externalMetadata.explicit),
createRemoveIdPrefixPlugin(externalMetadata.explicitBrowser),
],
// Browser only optimizeDeps. (This does not run for SSR dependencies).
optimizeDeps: getDepOptimizationConfig({
// Only enable with caching since it causes prebundle dependencies to be cached
disabled: serverOptions.prebundle === false,
// Exclude any explicitly defined dependencies (currently build defined externals)
exclude: externalMetadata.explicit,
exclude: externalMetadata.explicitBrowser,
// Include all implict dependencies from the external packages internal option
include: externalMetadata.implicitBrowser,
ssr: false,
Expand Down