/
githubmirror
/
angular-cli
Обзор
Документация
Войти
/
githubmirror
/
angular-cli
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
packages/angular/build/src/builders/dev-server/vite/server.ts
274 строки
10 KB
Charles Lyding
refactor(@angular/build): use xxhash-wasm for fast non-cryptographic content hashing
07 авг 2026, 10:56
07 авг 2026, 10:56
cda8830
Код
Авторство
О чём код?
/** * @license * Copyright Google LLC All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.dev/license */ import { readFile } from 'node:fs/promises'; import { join } from 'node:path'; import type * as Vite from 'vite' with { 'resolution-mode': 'import', }; import type { ComponentStyleRecord } from '../../../tools/vite/middlewares'; import { ServerSsrMode, createAngularMemoryPlugin, createAngularServerSideSSLPlugin, createAngularSetupMiddlewaresPlugin, createAngularSsrTransformPlugin, createRemoveIdPrefixPlugin, } from '../../../tools/vite/plugins'; import { RolldownLoaderOption, getDepOptimizationConfig } from '../../../tools/vite/utils'; import { loadProxyConfiguration } from '../../../utils'; import { initializeHash } from '../../../utils/hash'; import { type ApplicationBuilderInternalOptions, JavaScriptTransformer } from '../internal'; import type { NormalizedDevServerOptions } from '../options'; import { DevServerExternalResultMetadata, OutputAssetRecord, OutputFileRecord } from './utils'; async function createServerConfig( serverOptions: NormalizedDevServerOptions, assets: Map<string, OutputAssetRecord>, ssrMode: ServerSsrMode, preTransformRequests: boolean, cacheDir: string, ): Promise<Vite.ServerOptions> { const proxy = await loadProxyConfiguration( serverOptions.workspaceRoot, serverOptions.proxyConfig, ); // Files used for SSR warmup. let ssrFiles: string[] | undefined; switch (ssrMode) { case ServerSsrMode.InternalSsrMiddleware: ssrFiles = ['./main.server.mjs']; break; case ServerSsrMode.ExternalSsrMiddleware: ssrFiles = ['./main.server.mjs', './server.mjs']; break; } const server: Vite.ServerOptions = { preTransformRequests, warmup: { ssrFiles, }, port: serverOptions.port, strictPort: true, host: serverOptions.host, open: serverOptions.open, allowedHosts: serverOptions.allowedHosts, headers: serverOptions.headers, // Disable the websocket if live reload is disabled (false/undefined are the only valid values) ws: serverOptions.liveReload === false && serverOptions.hmr === false ? false : undefined, proxy, cors: { // Allow preflight requests to be proxied. preflightContinue: true, }, // File watching is handled by the build directly. `null` disables file watching for Vite. watch: null, fs: { // Ensure cache directory, node modules, and all assets are accessible by the client. // The first two are required for Vite to function in prebundling mode (the default) and to load // the Vite client-side code for browser reloading. These would be available by default but when // the `allow` option is explicitly configured, they must be included manually. allow: [ cacheDir, join(serverOptions.workspaceRoot, 'node_modules'), ...[...assets.values()].map(({ source }) => source), ], }, }; if (serverOptions.ssl && serverOptions.sslCert && serverOptions.sslKey) { const [cert, key] = await Promise.all([ readFile(serverOptions.sslCert), readFile(serverOptions.sslKey), ]); server.https = { cert, key, }; } return server; } function createSsrConfig( externalMetadata: DevServerExternalResultMetadata, serverOptions: NormalizedDevServerOptions, prebundleTransformer: JavaScriptTransformer, prebundleLoaderExtensions: RolldownLoaderOption | undefined, thirdPartySourcemaps: boolean, define: ApplicationBuilderInternalOptions['define'], target: string[], ): Vite.SSROptions { return { // 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.explicitServer, optimizeDeps: getDepOptimizationConfig({ target, // 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.explicitServer, // Include all implict dependencies from the external packages internal option include: externalMetadata.implicitServer, prebundleTransformer, loader: prebundleLoaderExtensions, thirdPartySourcemaps, define: { ...define, 'ngServerMode': 'true', }, }), }; } export async function setupServer( serverOptions: NormalizedDevServerOptions, outputFiles: Map<string, OutputFileRecord>, assets: Map<string, OutputAssetRecord>, preserveSymlinks: boolean | undefined, externalMetadata: DevServerExternalResultMetadata, ssrMode: ServerSsrMode, prebundleTransformer: JavaScriptTransformer, target: string[], componentStyles: Map<string, ComponentStyleRecord>, templateUpdates: Map<string, string>, prebundleLoaderExtensions: RolldownLoaderOption | undefined, define: ApplicationBuilderInternalOptions['define'], extensionMiddleware?: Vite.Connect.NextHandleFunction[], indexHtmlTransformer?: (content: string) => Promise<string>, thirdPartySourcemaps = false, ): Promise<Vite.InlineConfig> { await initializeHash(); const { normalizePath } = (await import('vite' as string)) as typeof Vite; // Path will not exist on disk and only used to provide separate path for Vite requests const virtualProjectRoot = normalizePath( join(serverOptions.workspaceRoot, `.angular/vite-root`, serverOptions.buildTarget.project), ); /** * Required when using `externalDependencies` to prevent Vite load errors. * * @note Can be removed if Vite introduces native support for externals. * @note Vite misresolves browser modules in SSR when accessing URLs with multiple segments * (e.g., 'foo/bar'), as they are not correctly re-based from the base href. */ const preTransformRequests = externalMetadata.explicitBrowser.length === 0 && ssrMode === ServerSsrMode.NoSsr; const cacheDir = join(serverOptions.cacheOptions.path, serverOptions.buildTarget.project, 'vite'); const configuration: Vite.InlineConfig = { configFile: false, envDir: false, cacheDir, root: virtualProjectRoot, publicDir: false, oxc: false, mode: 'development', // We use custom as we do not rely on Vite's htmlFallbackMiddleware and indexHtmlMiddleware. appType: 'custom', css: { devSourcemap: true, }, // Ensure custom 'file' loader build option entries are handled by Vite in application code that // reference third-party libraries. Relative usage is handled directly by the build and not Vite. // Only 'file' loader entries are currently supported directly by Vite. assetsInclude: prebundleLoaderExtensions && Object.entries(prebundleLoaderExtensions) .filter(([, value]) => value === 'asset') // Create a file extension glob for each key .map(([key]) => '*' + key), // Vite will normalize the `base` option by adding a leading slash. base: serverOptions.servePath, resolve: { mainFields: ['es2020', 'browser', 'module', 'main'], preserveSymlinks, }, dev: { preTransformRequests, }, server: await createServerConfig( serverOptions, assets, ssrMode, preTransformRequests, cacheDir, ), build: { target, }, ssr: ssrMode === ServerSsrMode.NoSsr ? undefined : createSsrConfig( externalMetadata, serverOptions, prebundleTransformer, prebundleLoaderExtensions, thirdPartySourcemaps, define, target, ), plugins: [ createAngularSetupMiddlewaresPlugin({ outputFiles, assets, indexHtmlTransformer, extensionMiddleware, componentStyles, templateUpdates, ssrMode, resetComponentUpdates: () => templateUpdates.clear(), projectRoot: serverOptions.projectRoot, }), createRemoveIdPrefixPlugin(externalMetadata.explicitBrowser), await createAngularSsrTransformPlugin(serverOptions.workspaceRoot), await createAngularMemoryPlugin({ virtualProjectRoot, outputFiles, templateUpdates, external: externalMetadata.explicitBrowser, disableViteTransport: !serverOptions.liveReload, }), ], // Browser only optimizeDeps. (This does not run for SSR dependencies). optimizeDeps: getDepOptimizationConfig({ target, // 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.explicitBrowser, // Include all implict dependencies from the external packages internal option include: externalMetadata.implicitBrowser, prebundleTransformer, loader: prebundleLoaderExtensions, thirdPartySourcemaps, define, }), }; if (serverOptions.ssl) { configuration.plugins ??= []; if (!serverOptions.sslCert || !serverOptions.sslKey) { const { default: basicSslPlugin } = await import('@vitejs/plugin-basic-ssl'); configuration.plugins.push(basicSslPlugin()); } if (ssrMode !== ServerSsrMode.NoSsr) { configuration.plugins?.push(createAngularServerSideSSLPlugin()); } } return configuration; }