@angular/build 19.0.3 → 19.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -3
- package/src/builders/dev-server/vite-server.d.ts +2 -2
- package/src/builders/dev-server/vite-server.js +7 -40
- package/src/tools/angular/angular-host.d.ts +1 -1
- package/src/tools/angular/angular-host.js +4 -4
- package/src/tools/angular/compilation/aot-compilation.js +21 -7
- package/src/tools/angular/compilation/jit-compilation.js +1 -1
- package/src/tools/esbuild/application-code-bundle.js +24 -20
- package/src/tools/vite/plugins/angular-memory-plugin.d.ts +1 -0
- package/src/tools/vite/plugins/angular-memory-plugin.js +14 -2
- package/src/tools/vite/utils.d.ts +14 -0
- package/src/tools/vite/utils.js +37 -0
- package/src/utils/index-file/auto-csp.js +5 -5
- package/src/utils/normalize-cache.js +1 -1
- package/src/utils/server-rendering/esm-in-memory-loader/loader-hooks.js +9 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@angular/build",
|
|
3
|
-
"version": "19.0.
|
|
3
|
+
"version": "19.0.5",
|
|
4
4
|
"description": "Official build system for Angular",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Angular CLI",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"builders": "builders.json",
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@ampproject/remapping": "2.3.0",
|
|
26
|
-
"@angular-devkit/architect": "0.1900.
|
|
26
|
+
"@angular-devkit/architect": "0.1900.5",
|
|
27
27
|
"@babel/core": "7.26.0",
|
|
28
28
|
"@babel/helper-annotate-as-pure": "7.25.9",
|
|
29
29
|
"@babel/helper-split-export-declaration": "7.24.7",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"@angular/localize": "^19.0.0",
|
|
58
58
|
"@angular/platform-server": "^19.0.0",
|
|
59
59
|
"@angular/service-worker": "^19.0.0",
|
|
60
|
-
"@angular/ssr": "^19.0.
|
|
60
|
+
"@angular/ssr": "^19.0.5",
|
|
61
61
|
"less": "^4.2.0",
|
|
62
62
|
"postcss": "^8.4.0",
|
|
63
63
|
"tailwindcss": "^2.0.0 || ^3.0.0",
|
|
@@ -7,9 +7,10 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import type { BuilderContext } from '@angular-devkit/architect';
|
|
9
9
|
import type { Plugin } from 'esbuild';
|
|
10
|
-
import type { Connect,
|
|
10
|
+
import type { Connect, InlineConfig } from 'vite';
|
|
11
11
|
import type { ComponentStyleRecord } from '../../tools/vite/middlewares';
|
|
12
12
|
import { ServerSsrMode } from '../../tools/vite/plugins';
|
|
13
|
+
import { EsbuildLoaderOption } from '../../tools/vite/utils';
|
|
13
14
|
import { Result } from '../application/results';
|
|
14
15
|
import { type ApplicationBuilderInternalOptions, BuildOutputFileType, type ExternalResultMetadata, JavaScriptTransformer } from './internal';
|
|
15
16
|
import type { NormalizedDevServerOptions } from './options';
|
|
@@ -34,5 +35,4 @@ export declare function serveWithVite(serverOptions: NormalizedDevServerOptions,
|
|
|
34
35
|
buildPlugins?: Plugin[];
|
|
35
36
|
}): AsyncIterableIterator<DevServerBuilderOutput>;
|
|
36
37
|
export declare function setupServer(serverOptions: NormalizedDevServerOptions, outputFiles: Map<string, OutputFileRecord>, assets: Map<string, string>, preserveSymlinks: boolean | undefined, externalMetadata: DevServerExternalResultMetadata, ssrMode: ServerSsrMode, prebundleTransformer: JavaScriptTransformer, target: string[], zoneless: boolean, componentStyles: Map<string, ComponentStyleRecord>, templateUpdates: Map<string, string>, prebundleLoaderExtensions: EsbuildLoaderOption | undefined, extensionMiddleware?: Connect.NextHandleFunction[], indexHtmlTransformer?: (content: string) => Promise<string>, thirdPartySourcemaps?: boolean): Promise<InlineConfig>;
|
|
37
|
-
type EsbuildLoaderOption = Exclude<DepOptimizationConfig['esbuildOptions'], undefined>['loader'];
|
|
38
38
|
export {};
|
|
@@ -40,7 +40,8 @@ const promises_1 = require("node:fs/promises");
|
|
|
40
40
|
const node_module_1 = require("node:module");
|
|
41
41
|
const node_path_1 = require("node:path");
|
|
42
42
|
const plugins_1 = require("../../tools/vite/plugins");
|
|
43
|
-
const utils_1 = require("../../utils");
|
|
43
|
+
const utils_1 = require("../../tools/vite/utils");
|
|
44
|
+
const utils_2 = require("../../utils");
|
|
44
45
|
const environment_options_1 = require("../../utils/environment-options");
|
|
45
46
|
const load_esm_1 = require("../../utils/load-esm");
|
|
46
47
|
const results_1 = require("../application/results");
|
|
@@ -87,7 +88,7 @@ async function* serveWithVite(serverOptions, builderName, builderAction, context
|
|
|
87
88
|
// When localization is enabled with a single locale, force a flat path to maintain behavior with the existing Webpack-based dev server.
|
|
88
89
|
browserOptions.forceI18nFlatOutput = true;
|
|
89
90
|
}
|
|
90
|
-
const { vendor: thirdPartySourcemaps, scripts: scriptsSourcemaps } = (0,
|
|
91
|
+
const { vendor: thirdPartySourcemaps, scripts: scriptsSourcemaps } = (0, utils_2.normalizeSourceMaps)(browserOptions.sourceMap ?? false);
|
|
91
92
|
if (scriptsSourcemaps && browserOptions.server) {
|
|
92
93
|
// https://nodejs.org/api/process.html#processsetsourcemapsenabledval
|
|
93
94
|
process.setSourceMapsEnabled(true);
|
|
@@ -459,7 +460,7 @@ function analyzeResultFiles(normalizePath, htmlIndexPath, resultFiles, generated
|
|
|
459
460
|
}
|
|
460
461
|
}
|
|
461
462
|
async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks, externalMetadata, ssrMode, prebundleTransformer, target, zoneless, componentStyles, templateUpdates, prebundleLoaderExtensions, extensionMiddleware, indexHtmlTransformer, thirdPartySourcemaps = false) {
|
|
462
|
-
const proxy = await (0,
|
|
463
|
+
const proxy = await (0, utils_2.loadProxyConfiguration)(serverOptions.workspaceRoot, serverOptions.proxyConfig);
|
|
463
464
|
// dynamically import Vite for ESM compatibility
|
|
464
465
|
const { normalizePath } = await (0, load_esm_1.loadEsmModule)('vite');
|
|
465
466
|
// Path will not exist on disk and only used to provide separate path for Vite requests
|
|
@@ -530,7 +531,7 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
|
|
|
530
531
|
noExternal: /.*/,
|
|
531
532
|
// Exclude any Node.js built in module and provided dependencies (currently build defined externals)
|
|
532
533
|
external: externalMetadata.explicitServer,
|
|
533
|
-
optimizeDeps: getDepOptimizationConfig({
|
|
534
|
+
optimizeDeps: (0, utils_1.getDepOptimizationConfig)({
|
|
534
535
|
// Only enable with caching since it causes prebundle dependencies to be cached
|
|
535
536
|
disabled: serverOptions.prebundle === false,
|
|
536
537
|
// Exclude any explicitly defined dependencies (currently build defined externals and node.js built-ins)
|
|
@@ -561,12 +562,13 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
|
|
|
561
562
|
await (0, plugins_1.createAngularMemoryPlugin)({
|
|
562
563
|
virtualProjectRoot,
|
|
563
564
|
outputFiles,
|
|
565
|
+
templateUpdates,
|
|
564
566
|
external: externalMetadata.explicitBrowser,
|
|
565
567
|
skipViteClient: serverOptions.liveReload === false && serverOptions.hmr === false,
|
|
566
568
|
}),
|
|
567
569
|
],
|
|
568
570
|
// Browser only optimizeDeps. (This does not run for SSR dependencies).
|
|
569
|
-
optimizeDeps: getDepOptimizationConfig({
|
|
571
|
+
optimizeDeps: (0, utils_1.getDepOptimizationConfig)({
|
|
570
572
|
// Only enable with caching since it causes prebundle dependencies to be cached
|
|
571
573
|
disabled: serverOptions.prebundle === false,
|
|
572
574
|
// Exclude any explicitly defined dependencies (currently build defined externals)
|
|
@@ -599,41 +601,6 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
|
|
|
599
601
|
}
|
|
600
602
|
return configuration;
|
|
601
603
|
}
|
|
602
|
-
function getDepOptimizationConfig({ disabled, exclude, include, target, zoneless, prebundleTransformer, ssr, loader, thirdPartySourcemaps, }) {
|
|
603
|
-
const plugins = [
|
|
604
|
-
{
|
|
605
|
-
name: `angular-vite-optimize-deps${ssr ? '-ssr' : ''}${thirdPartySourcemaps ? '-vendor-sourcemap' : ''}`,
|
|
606
|
-
setup(build) {
|
|
607
|
-
build.onLoad({ filter: /\.[cm]?js$/ }, async (args) => {
|
|
608
|
-
return {
|
|
609
|
-
contents: await prebundleTransformer.transformFile(args.path),
|
|
610
|
-
loader: 'js',
|
|
611
|
-
};
|
|
612
|
-
});
|
|
613
|
-
},
|
|
614
|
-
},
|
|
615
|
-
];
|
|
616
|
-
return {
|
|
617
|
-
// Exclude any explicitly defined dependencies (currently build defined externals)
|
|
618
|
-
exclude,
|
|
619
|
-
// NB: to disable the deps optimizer, set optimizeDeps.noDiscovery to true and optimizeDeps.include as undefined.
|
|
620
|
-
// Include all implict dependencies from the external packages internal option
|
|
621
|
-
include: disabled ? undefined : include,
|
|
622
|
-
noDiscovery: disabled,
|
|
623
|
-
// Add an esbuild plugin to run the Angular linker on dependencies
|
|
624
|
-
esbuildOptions: {
|
|
625
|
-
// Set esbuild supported targets.
|
|
626
|
-
target,
|
|
627
|
-
supported: (0, internal_1.getFeatureSupport)(target, zoneless),
|
|
628
|
-
plugins,
|
|
629
|
-
loader,
|
|
630
|
-
define: {
|
|
631
|
-
'ngServerMode': `${ssr}`,
|
|
632
|
-
},
|
|
633
|
-
resolveExtensions: ['.mjs', '.js', '.cjs'],
|
|
634
|
-
},
|
|
635
|
-
};
|
|
636
|
-
}
|
|
637
604
|
/**
|
|
638
605
|
* Checks if the given value is an absolute URL.
|
|
639
606
|
*
|
|
@@ -24,4 +24,4 @@ export interface AngularHostOptions {
|
|
|
24
24
|
* @param program The TypeScript Program instance to patch.
|
|
25
25
|
*/
|
|
26
26
|
export declare function ensureSourceFileVersions(program: ts.Program): void;
|
|
27
|
-
export declare function createAngularCompilerHost(typescript: typeof ts, compilerOptions: AngularCompilerOptions, hostOptions: AngularHostOptions): AngularCompilerHost;
|
|
27
|
+
export declare function createAngularCompilerHost(typescript: typeof ts, compilerOptions: AngularCompilerOptions, hostOptions: AngularHostOptions, packageJsonCache: ts.PackageJsonInfoCache | undefined): AngularCompilerHost;
|
|
@@ -91,7 +91,7 @@ function augmentHostWithReplacements(typescript, host, replacements, moduleResol
|
|
|
91
91
|
};
|
|
92
92
|
augmentResolveModuleNames(typescript, host, tryReplace, moduleResolutionCache);
|
|
93
93
|
}
|
|
94
|
-
function createAngularCompilerHost(typescript, compilerOptions, hostOptions) {
|
|
94
|
+
function createAngularCompilerHost(typescript, compilerOptions, hostOptions, packageJsonCache) {
|
|
95
95
|
// Create TypeScript compiler host
|
|
96
96
|
const host = typescript.createIncrementalCompilerHost(compilerOptions);
|
|
97
97
|
// Set the parsing mode to the same as TS 5.3+ default for tsc. This provides a parse
|
|
@@ -135,11 +135,11 @@ function createAngularCompilerHost(typescript, compilerOptions, hostOptions) {
|
|
|
135
135
|
host.getModifiedResourceFiles = function () {
|
|
136
136
|
return hostOptions.modifiedFiles;
|
|
137
137
|
};
|
|
138
|
+
// Provide a resolution cache to ensure package.json lookups are cached
|
|
139
|
+
const resolutionCache = typescript.createModuleResolutionCache(host.getCurrentDirectory(), host.getCanonicalFileName.bind(host), compilerOptions, packageJsonCache);
|
|
140
|
+
host.getModuleResolutionCache = () => resolutionCache;
|
|
138
141
|
// Augment TypeScript Host for file replacements option
|
|
139
142
|
if (hostOptions.fileReplacements) {
|
|
140
|
-
// Provide a resolution cache since overriding resolution prevents automatic creation
|
|
141
|
-
const resolutionCache = typescript.createModuleResolutionCache(host.getCurrentDirectory(), host.getCanonicalFileName.bind(host), compilerOptions);
|
|
142
|
-
host.getModuleResolutionCache = () => resolutionCache;
|
|
143
143
|
augmentHostWithReplacements(typescript, host, hostOptions.fileReplacements, resolutionCache);
|
|
144
144
|
}
|
|
145
145
|
// Augment TypeScript Host with source file caching if provided
|
|
@@ -51,19 +51,32 @@ class AotCompilation extends angular_compilation_1.AngularCompilation {
|
|
|
51
51
|
if (compilerOptions.externalRuntimeStyles) {
|
|
52
52
|
hostOptions.externalStylesheets ??= new Map();
|
|
53
53
|
}
|
|
54
|
-
//
|
|
54
|
+
// Reuse the package.json cache from the previous compilation
|
|
55
|
+
const packageJsonCache = this.#state?.compilerHost
|
|
56
|
+
.getModuleResolutionCache?.()
|
|
57
|
+
?.getPackageJsonInfoCache();
|
|
58
|
+
const useHmr = compilerOptions['_enableHmr'];
|
|
55
59
|
let staleSourceFiles;
|
|
56
|
-
|
|
60
|
+
let clearPackageJsonCache = false;
|
|
61
|
+
if (hostOptions.modifiedFiles && this.#state) {
|
|
57
62
|
for (const modifiedFile of hostOptions.modifiedFiles) {
|
|
58
|
-
|
|
59
|
-
if (
|
|
60
|
-
|
|
61
|
-
|
|
63
|
+
// Clear package.json cache if a node modules file was modified
|
|
64
|
+
if (!clearPackageJsonCache && modifiedFile.includes('node_modules')) {
|
|
65
|
+
clearPackageJsonCache = true;
|
|
66
|
+
packageJsonCache?.clear();
|
|
67
|
+
}
|
|
68
|
+
// Collect stale source files for HMR analysis of inline component resources
|
|
69
|
+
if (useHmr) {
|
|
70
|
+
const sourceFile = this.#state.typeScriptProgram.getSourceFile(modifiedFile);
|
|
71
|
+
if (sourceFile) {
|
|
72
|
+
staleSourceFiles ??= new Map();
|
|
73
|
+
staleSourceFiles.set(modifiedFile, sourceFile);
|
|
74
|
+
}
|
|
62
75
|
}
|
|
63
76
|
}
|
|
64
77
|
}
|
|
65
78
|
// Create Angular compiler host
|
|
66
|
-
const host = (0, angular_host_1.createAngularCompilerHost)(typescript_1.default, compilerOptions, hostOptions);
|
|
79
|
+
const host = (0, angular_host_1.createAngularCompilerHost)(typescript_1.default, compilerOptions, hostOptions, packageJsonCache);
|
|
67
80
|
// Create the Angular specific program that contains the Angular compiler
|
|
68
81
|
const angularProgram = (0, profiling_1.profileSync)('NG_CREATE_PROGRAM', () => new NgtscProgram(rootNames, compilerOptions, host, this.#state?.angularProgram));
|
|
69
82
|
const angularCompiler = angularProgram.compiler;
|
|
@@ -89,6 +102,7 @@ class AotCompilation extends angular_compilation_1.AngularCompilation {
|
|
|
89
102
|
if (relativePath.startsWith('..')) {
|
|
90
103
|
relativePath = componentFilename;
|
|
91
104
|
}
|
|
105
|
+
relativePath = relativePath.replaceAll('\\', '/');
|
|
92
106
|
const updateId = encodeURIComponent(`${host.getCanonicalFileName(relativePath)}@${node.name?.text}`);
|
|
93
107
|
const updateText = angularCompiler.emitHmrUpdateModule(node);
|
|
94
108
|
if (updateText === null) {
|
|
@@ -42,7 +42,7 @@ class JitCompilation extends angular_compilation_1.AngularCompilation {
|
|
|
42
42
|
const { options: originalCompilerOptions, rootNames, errors: configurationDiagnostics, } = await this.loadConfiguration(tsconfig);
|
|
43
43
|
const compilerOptions = compilerOptionsTransformer?.(originalCompilerOptions) ?? originalCompilerOptions;
|
|
44
44
|
// Create Angular compiler host
|
|
45
|
-
const host = (0, angular_host_1.createAngularCompilerHost)(typescript_1.default, compilerOptions, hostOptions);
|
|
45
|
+
const host = (0, angular_host_1.createAngularCompilerHost)(typescript_1.default, compilerOptions, hostOptions, undefined);
|
|
46
46
|
// Create the TypeScript Program
|
|
47
47
|
const typeScriptProgram = (0, profiling_1.profileSync)('TS_CREATE_PROGRAM', () => typescript_1.default.createEmitAndSemanticDiagnosticsBuilderProgram(rootNames, compilerOptions, host, this.#state?.typeScriptProgram ?? typescript_1.default.readBuilderProgram(compilerOptions, host), configurationDiagnostics));
|
|
48
48
|
const affectedFiles = (0, profiling_1.profileSync)('TS_FIND_AFFECTED', () => findAffectedFiles(typeScriptProgram));
|
|
@@ -136,6 +136,15 @@ function createServerPolyfillBundleOptions(options, target, loadResultCache) {
|
|
|
136
136
|
if (!polyfillBundleOptions) {
|
|
137
137
|
return;
|
|
138
138
|
}
|
|
139
|
+
const jsBanner = [];
|
|
140
|
+
if (polyfillBundleOptions.external?.length) {
|
|
141
|
+
jsBanner.push(`globalThis['ngServerMode'] = true;`);
|
|
142
|
+
}
|
|
143
|
+
if (isNodePlatform) {
|
|
144
|
+
// Note: Needed as esbuild does not provide require shims / proxy from ESModules.
|
|
145
|
+
// See: https://github.com/evanw/esbuild/issues/1921.
|
|
146
|
+
jsBanner.push(`import { createRequire } from 'node:module';`, `globalThis['require'] ??= createRequire(import.meta.url);`);
|
|
147
|
+
}
|
|
139
148
|
const buildOptions = {
|
|
140
149
|
...polyfillBundleOptions,
|
|
141
150
|
platform: isNodePlatform ? 'node' : 'neutral',
|
|
@@ -146,16 +155,9 @@ function createServerPolyfillBundleOptions(options, target, loadResultCache) {
|
|
|
146
155
|
// More details: https://github.com/angular/angular-cli/issues/25405.
|
|
147
156
|
mainFields: ['es2020', 'es2015', 'module', 'main'],
|
|
148
157
|
entryNames: '[name]',
|
|
149
|
-
banner:
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
// Note: Needed as esbuild does not provide require shims / proxy from ESModules.
|
|
153
|
-
// See: https://github.com/evanw/esbuild/issues/1921.
|
|
154
|
-
`import { createRequire } from 'node:module';`,
|
|
155
|
-
`globalThis['require'] ??= createRequire(import.meta.url);`,
|
|
156
|
-
].join('\n'),
|
|
157
|
-
}
|
|
158
|
-
: undefined,
|
|
158
|
+
banner: {
|
|
159
|
+
js: jsBanner.join('\n'),
|
|
160
|
+
},
|
|
159
161
|
target,
|
|
160
162
|
entryPoints: {
|
|
161
163
|
'polyfills.server': namespace,
|
|
@@ -274,19 +276,21 @@ function createSsrEntryCodeBundleOptions(options, target, sourceFileCache, style
|
|
|
274
276
|
const ssrEntryNamespace = 'angular:ssr-entry';
|
|
275
277
|
const ssrInjectManifestNamespace = 'angular:ssr-entry-inject-manifest';
|
|
276
278
|
const isNodePlatform = options.ssrOptions?.platform !== schema_1.ExperimentalPlatform.Neutral;
|
|
279
|
+
const jsBanner = [];
|
|
280
|
+
if (options.externalDependencies?.length) {
|
|
281
|
+
jsBanner.push(`globalThis['ngServerMode'] = true;`);
|
|
282
|
+
}
|
|
283
|
+
if (isNodePlatform) {
|
|
284
|
+
// Note: Needed as esbuild does not provide require shims / proxy from ESModules.
|
|
285
|
+
// See: https://github.com/evanw/esbuild/issues/1921.
|
|
286
|
+
jsBanner.push(`import { createRequire } from 'node:module';`, `globalThis['require'] ??= createRequire(import.meta.url);`);
|
|
287
|
+
}
|
|
277
288
|
const buildOptions = {
|
|
278
289
|
...getEsBuildServerCommonOptions(options),
|
|
279
290
|
target,
|
|
280
|
-
banner:
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
// Note: Needed as esbuild does not provide require shims / proxy from ESModules.
|
|
284
|
-
// See: https://github.com/evanw/esbuild/issues/1921.
|
|
285
|
-
`import { createRequire } from 'node:module';`,
|
|
286
|
-
`globalThis['require'] ??= createRequire(import.meta.url);`,
|
|
287
|
-
].join('\n'),
|
|
288
|
-
}
|
|
289
|
-
: undefined,
|
|
291
|
+
banner: {
|
|
292
|
+
js: jsBanner.join('\n'),
|
|
293
|
+
},
|
|
290
294
|
entryPoints: {
|
|
291
295
|
'server': ssrEntryNamespace,
|
|
292
296
|
},
|
|
@@ -10,6 +10,7 @@ import { AngularMemoryOutputFiles } from '../utils';
|
|
|
10
10
|
interface AngularMemoryPluginOptions {
|
|
11
11
|
virtualProjectRoot: string;
|
|
12
12
|
outputFiles: AngularMemoryOutputFiles;
|
|
13
|
+
templateUpdates?: ReadonlyMap<string, string>;
|
|
13
14
|
external?: string[];
|
|
14
15
|
skipViteClient?: boolean;
|
|
15
16
|
}
|
|
@@ -15,6 +15,7 @@ const node_assert_1 = __importDefault(require("node:assert"));
|
|
|
15
15
|
const promises_1 = require("node:fs/promises");
|
|
16
16
|
const node_path_1 = require("node:path");
|
|
17
17
|
const load_esm_1 = require("../../../utils/load-esm");
|
|
18
|
+
const ANGULAR_PREFIX = '/@ng/';
|
|
18
19
|
async function createAngularMemoryPlugin(options) {
|
|
19
20
|
const { virtualProjectRoot, outputFiles, external } = options;
|
|
20
21
|
const { normalizePath } = await (0, load_esm_1.loadEsmModule)('vite');
|
|
@@ -22,7 +23,11 @@ async function createAngularMemoryPlugin(options) {
|
|
|
22
23
|
name: 'vite:angular-memory',
|
|
23
24
|
// Ensures plugin hooks run before built-in Vite hooks
|
|
24
25
|
enforce: 'pre',
|
|
25
|
-
async resolveId(source, importer) {
|
|
26
|
+
async resolveId(source, importer, { ssr }) {
|
|
27
|
+
// For SSR with component HMR, pass through as a virtual module
|
|
28
|
+
if (ssr && source.startsWith(ANGULAR_PREFIX)) {
|
|
29
|
+
return '\0' + source;
|
|
30
|
+
}
|
|
26
31
|
// Prevent vite from resolving an explicit external dependency (`externalDependencies` option)
|
|
27
32
|
if (external?.includes(source)) {
|
|
28
33
|
// This is still not ideal since Vite will still transform the import specifier to
|
|
@@ -41,7 +46,14 @@ async function createAngularMemoryPlugin(options) {
|
|
|
41
46
|
return (0, node_path_1.join)(virtualProjectRoot, source);
|
|
42
47
|
}
|
|
43
48
|
},
|
|
44
|
-
load(id) {
|
|
49
|
+
load(id, loadOptions) {
|
|
50
|
+
// For SSR component updates, return the component update module or empty if none
|
|
51
|
+
if (loadOptions?.ssr && id.startsWith(`\0${ANGULAR_PREFIX}`)) {
|
|
52
|
+
// Extract component identifier (first character is rollup virtual module null)
|
|
53
|
+
const requestUrl = new URL(id.slice(1), 'http://localhost');
|
|
54
|
+
const componentId = requestUrl.searchParams.get('c');
|
|
55
|
+
return (componentId && options.templateUpdates?.get(componentId)) ?? '';
|
|
56
|
+
}
|
|
45
57
|
const [file] = id.split('?', 1);
|
|
46
58
|
const relativeFile = '/' + normalizePath((0, node_path_1.relative)(virtualProjectRoot, file));
|
|
47
59
|
const codeContents = outputFiles.get(relativeFile)?.contents;
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
* Use of this source code is governed by an MIT-style license that can be
|
|
6
6
|
* found in the LICENSE file at https://angular.dev/license
|
|
7
7
|
*/
|
|
8
|
+
import type { DepOptimizationConfig } from 'vite';
|
|
9
|
+
import { JavaScriptTransformer } from '../esbuild/javascript-transformer';
|
|
8
10
|
export type AngularMemoryOutputFiles = Map<string, {
|
|
9
11
|
contents: Uint8Array;
|
|
10
12
|
hash: string;
|
|
@@ -12,3 +14,15 @@ export type AngularMemoryOutputFiles = Map<string, {
|
|
|
12
14
|
}>;
|
|
13
15
|
export declare function pathnameWithoutBasePath(url: string, basePath: string): string;
|
|
14
16
|
export declare function lookupMimeTypeFromRequest(url: string): string | undefined;
|
|
17
|
+
export type EsbuildLoaderOption = Exclude<DepOptimizationConfig['esbuildOptions'], undefined>['loader'];
|
|
18
|
+
export declare function getDepOptimizationConfig({ disabled, exclude, include, target, zoneless, prebundleTransformer, ssr, loader, thirdPartySourcemaps, }: {
|
|
19
|
+
disabled: boolean;
|
|
20
|
+
exclude: string[];
|
|
21
|
+
include: string[];
|
|
22
|
+
target: string[];
|
|
23
|
+
prebundleTransformer: JavaScriptTransformer;
|
|
24
|
+
ssr: boolean;
|
|
25
|
+
zoneless: boolean;
|
|
26
|
+
loader?: EsbuildLoaderOption;
|
|
27
|
+
thirdPartySourcemaps: boolean;
|
|
28
|
+
}): DepOptimizationConfig;
|
package/src/tools/vite/utils.js
CHANGED
|
@@ -9,8 +9,10 @@
|
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
10
|
exports.pathnameWithoutBasePath = pathnameWithoutBasePath;
|
|
11
11
|
exports.lookupMimeTypeFromRequest = lookupMimeTypeFromRequest;
|
|
12
|
+
exports.getDepOptimizationConfig = getDepOptimizationConfig;
|
|
12
13
|
const mrmime_1 = require("mrmime");
|
|
13
14
|
const node_path_1 = require("node:path");
|
|
15
|
+
const utils_1 = require("../esbuild/utils");
|
|
14
16
|
function pathnameWithoutBasePath(url, basePath) {
|
|
15
17
|
const parsedUrl = new URL(url, 'http://localhost');
|
|
16
18
|
const pathname = decodeURIComponent(parsedUrl.pathname);
|
|
@@ -26,3 +28,38 @@ function lookupMimeTypeFromRequest(url) {
|
|
|
26
28
|
}
|
|
27
29
|
return extension && (0, mrmime_1.lookup)(extension);
|
|
28
30
|
}
|
|
31
|
+
function getDepOptimizationConfig({ disabled, exclude, include, target, zoneless, prebundleTransformer, ssr, loader, thirdPartySourcemaps, }) {
|
|
32
|
+
const plugins = [
|
|
33
|
+
{
|
|
34
|
+
name: `angular-vite-optimize-deps${ssr ? '-ssr' : ''}${thirdPartySourcemaps ? '-vendor-sourcemap' : ''}`,
|
|
35
|
+
setup(build) {
|
|
36
|
+
build.onLoad({ filter: /\.[cm]?js$/ }, async (args) => {
|
|
37
|
+
return {
|
|
38
|
+
contents: await prebundleTransformer.transformFile(args.path),
|
|
39
|
+
loader: 'js',
|
|
40
|
+
};
|
|
41
|
+
});
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
];
|
|
45
|
+
return {
|
|
46
|
+
// Exclude any explicitly defined dependencies (currently build defined externals)
|
|
47
|
+
exclude,
|
|
48
|
+
// NB: to disable the deps optimizer, set optimizeDeps.noDiscovery to true and optimizeDeps.include as undefined.
|
|
49
|
+
// Include all implict dependencies from the external packages internal option
|
|
50
|
+
include: disabled ? undefined : include,
|
|
51
|
+
noDiscovery: disabled,
|
|
52
|
+
// Add an esbuild plugin to run the Angular linker on dependencies
|
|
53
|
+
esbuildOptions: {
|
|
54
|
+
// Set esbuild supported targets.
|
|
55
|
+
target,
|
|
56
|
+
supported: (0, utils_1.getFeatureSupport)(target, zoneless),
|
|
57
|
+
plugins,
|
|
58
|
+
loader,
|
|
59
|
+
define: {
|
|
60
|
+
'ngServerMode': `${ssr}`,
|
|
61
|
+
},
|
|
62
|
+
resolveExtensions: ['.mjs', '.js', '.cjs'],
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
}
|
|
@@ -97,7 +97,7 @@ async function autoCsp(html, unsafeEval = false) {
|
|
|
97
97
|
* loader script to the collection of hashes to add to the <meta> tag CSP.
|
|
98
98
|
*/
|
|
99
99
|
function emitLoaderScript() {
|
|
100
|
-
const loaderScript = createLoaderScript(scriptContent);
|
|
100
|
+
const loaderScript = createLoaderScript(scriptContent, /* enableTrustedTypes = */ false);
|
|
101
101
|
hashes.push(hashTextContent(loaderScript));
|
|
102
102
|
rewriter.emitRaw(`<script>${loaderScript}</script>`);
|
|
103
103
|
scriptContent = [];
|
|
@@ -151,7 +151,7 @@ async function autoCsp(html, unsafeEval = false) {
|
|
|
151
151
|
return;
|
|
152
152
|
}
|
|
153
153
|
}
|
|
154
|
-
if (tag.tagName === 'body' || tag.tagName === 'html') {
|
|
154
|
+
if (tag.tagName === 'head' || tag.tagName === 'body' || tag.tagName === 'html') {
|
|
155
155
|
// Write the loader script if a string of <script>s were the last opening tag of the document.
|
|
156
156
|
if (scriptContent.length > 0) {
|
|
157
157
|
emitLoaderScript();
|
|
@@ -249,7 +249,7 @@ function createLoaderScript(srcList, enableTrustedTypes = false) {
|
|
|
249
249
|
// URI encoding means value can't escape string, JS, or HTML context.
|
|
250
250
|
const srcAttr = encodeURI(s.src).replaceAll("'", "\\'");
|
|
251
251
|
// Can only be 'module' or a JS MIME type or an empty string.
|
|
252
|
-
const typeAttr = s.type ? "'" + s.type + "'" :
|
|
252
|
+
const typeAttr = s.type ? "'" + s.type + "'" : "''";
|
|
253
253
|
const asyncAttr = s.async ? 'true' : 'false';
|
|
254
254
|
const deferAttr = s.defer ? 'true' : 'false';
|
|
255
255
|
return `['${srcAttr}', ${typeAttr}, ${asyncAttr}, ${deferAttr}]`;
|
|
@@ -268,7 +268,7 @@ function createLoaderScript(srcList, enableTrustedTypes = false) {
|
|
|
268
268
|
s.type = scriptUrl[1];
|
|
269
269
|
s.async = !!scriptUrl[2];
|
|
270
270
|
s.defer = !!scriptUrl[3];
|
|
271
|
-
document.
|
|
271
|
+
document.lastElementChild.appendChild(s);
|
|
272
272
|
});\n`
|
|
273
273
|
: `
|
|
274
274
|
var scripts = [${srcListFormatted}];
|
|
@@ -278,6 +278,6 @@ function createLoaderScript(srcList, enableTrustedTypes = false) {
|
|
|
278
278
|
s.type = scriptUrl[1];
|
|
279
279
|
s.async = !!scriptUrl[2];
|
|
280
280
|
s.defer = !!scriptUrl[3];
|
|
281
|
-
document.
|
|
281
|
+
document.lastElementChild.appendChild(s);
|
|
282
282
|
});\n`;
|
|
283
283
|
}
|
|
@@ -10,7 +10,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
10
10
|
exports.normalizeCacheOptions = normalizeCacheOptions;
|
|
11
11
|
const node_path_1 = require("node:path");
|
|
12
12
|
/** Version placeholder is replaced during the build process with actual package version */
|
|
13
|
-
const VERSION = '19.0.
|
|
13
|
+
const VERSION = '19.0.5';
|
|
14
14
|
function hasCacheMetadata(value) {
|
|
15
15
|
return (!!value &&
|
|
16
16
|
typeof value === 'object' &&
|
|
@@ -19,6 +19,10 @@ const node_path_1 = require("node:path");
|
|
|
19
19
|
const node_url_1 = require("node:url");
|
|
20
20
|
const url_1 = require("url");
|
|
21
21
|
const javascript_transformer_1 = require("../../../tools/esbuild/javascript-transformer");
|
|
22
|
+
/**
|
|
23
|
+
* @note For some unknown reason, setting `globalThis.ngServerMode = true` does not work when using ESM loader hooks.
|
|
24
|
+
*/
|
|
25
|
+
const NG_SERVER_MODE_INIT_BYTES = new TextEncoder().encode('var ngServerMode=true;');
|
|
22
26
|
/**
|
|
23
27
|
* Node.js ESM loader to redirect imports to in memory files.
|
|
24
28
|
* @see: https://nodejs.org/api/esm.html#loaders for more information about loaders.
|
|
@@ -107,7 +111,11 @@ async function load(url, context, nextLoad) {
|
|
|
107
111
|
// need linking are ESM only.
|
|
108
112
|
if (format === 'module' && isFileProtocol(url)) {
|
|
109
113
|
const filePath = (0, url_1.fileURLToPath)(url);
|
|
110
|
-
|
|
114
|
+
let source = await javascriptTransformer.transformFile(filePath);
|
|
115
|
+
if (filePath.includes('@angular/')) {
|
|
116
|
+
// Prepend 'var ngServerMode=true;' to the source.
|
|
117
|
+
source = Buffer.concat([NG_SERVER_MODE_INIT_BYTES, source]);
|
|
118
|
+
}
|
|
111
119
|
return {
|
|
112
120
|
format,
|
|
113
121
|
shortCircuit: true,
|