@angular/build 19.0.4 → 19.0.6

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@angular/build",
3
- "version": "19.0.4",
3
+ "version": "19.0.6",
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.4",
26
+ "@angular-devkit/architect": "0.1900.6",
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.4",
60
+ "@angular/ssr": "^19.0.6",
61
61
  "less": "^4.2.0",
62
62
  "postcss": "^8.4.0",
63
63
  "tailwindcss": "^2.0.0 || ^3.0.0",
@@ -86,7 +86,6 @@
86
86
  "optional": true
87
87
  }
88
88
  },
89
- "packageManager": "yarn@4.5.0",
90
89
  "repository": {
91
90
  "type": "git",
92
91
  "url": "https://github.com/angular/angular-cli.git"
@@ -109,5 +108,8 @@
109
108
  "puppeteer": {
110
109
  "built": true
111
110
  }
111
+ },
112
+ "pnpm": {
113
+ "onlyBuiltDependencies": []
112
114
  }
113
115
  }
@@ -6,6 +6,29 @@
6
6
  * Use of this source code is governed by an MIT-style license that can be
7
7
  * found in the LICENSE file at https://angular.dev/license
8
8
  */
9
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ var desc = Object.getOwnPropertyDescriptor(m, k);
12
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
13
+ desc = { enumerable: true, get: function() { return m[k]; } };
14
+ }
15
+ Object.defineProperty(o, k2, desc);
16
+ }) : (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ o[k2] = m[k];
19
+ }));
20
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
21
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
22
+ }) : function(o, v) {
23
+ o["default"] = v;
24
+ });
25
+ var __importStar = (this && this.__importStar) || function (mod) {
26
+ if (mod && mod.__esModule) return mod;
27
+ var result = {};
28
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
29
+ __setModuleDefault(result, mod);
30
+ return result;
31
+ };
9
32
  Object.defineProperty(exports, "__esModule", { value: true });
10
33
  exports.executeBuild = executeBuild;
11
34
  const source_file_cache_1 = require("../../tools/esbuild/angular/source-file-cache");
@@ -21,7 +44,6 @@ const environment_options_1 = require("../../utils/environment-options");
21
44
  const resolve_assets_1 = require("../../utils/resolve-assets");
22
45
  const manifest_1 = require("../../utils/server-rendering/manifest");
23
46
  const supported_browsers_1 = require("../../utils/supported-browsers");
24
- const chunk_optimizer_1 = require("./chunk-optimizer");
25
47
  const execute_post_bundle_1 = require("./execute-post-bundle");
26
48
  const i18n_1 = require("./i18n");
27
49
  const setup_bundling_1 = require("./setup-bundling");
@@ -85,7 +107,8 @@ async function executeBuild(options, context, rebuildState) {
85
107
  bundlingResult = bundler_context_1.BundlerContext.mergeResults([bundlingResult, ...componentResults]);
86
108
  }
87
109
  if (options.optimizationOptions.scripts && environment_options_1.shouldOptimizeChunks) {
88
- bundlingResult = await (0, profiling_1.profileAsync)('OPTIMIZE_CHUNKS', () => (0, chunk_optimizer_1.optimizeChunks)(bundlingResult, options.sourcemapOptions.scripts ? !options.sourcemapOptions.hidden || 'hidden' : false));
110
+ const { optimizeChunks } = await Promise.resolve().then(() => __importStar(require('./chunk-optimizer')));
111
+ bundlingResult = await (0, profiling_1.profileAsync)('OPTIMIZE_CHUNKS', () => optimizeChunks(bundlingResult, options.sourcemapOptions.scripts ? !options.sourcemapOptions.hidden || 'hidden' : false));
89
112
  }
90
113
  const executionResult = new bundler_execution_result_1.ExecutionResult(bundlerContexts, componentStyleBundler, codeBundleCache, templateUpdates);
91
114
  executionResult.addWarnings(bundlingResult.warnings);
@@ -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, DepOptimizationConfig, InlineConfig } from 'vite';
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, utils_1.normalizeSourceMaps)(browserOptions.sourceMap ?? false);
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, utils_1.loadProxyConfiguration)(serverOptions.workspaceRoot, serverOptions.proxyConfig);
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
@@ -503,7 +504,14 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
503
504
  headers: serverOptions.headers,
504
505
  // Disable the websocket if live reload is disabled (false/undefined are the only valid values)
505
506
  ws: serverOptions.liveReload === false && serverOptions.hmr === false ? false : undefined,
506
- proxy,
507
+ // When server-side rendering (SSR) is enabled togather with SSL and Express is being used,
508
+ // we must configure Vite to use HTTP/1.1.
509
+ // This is necessary because Express does not support HTTP/2.
510
+ // We achieve this by defining an empty proxy.
511
+ // See: https://github.com/vitejs/vite/blob/c4b532cc900bf988073583511f57bd581755d5e3/packages/vite/src/node/http.ts#L106
512
+ proxy: serverOptions.ssl && ssrMode === plugins_1.ServerSsrMode.ExternalSsrMiddleware
513
+ ? (proxy ?? {})
514
+ : proxy,
507
515
  cors: {
508
516
  // Allow preflight requests to be proxied.
509
517
  preflightContinue: true,
@@ -530,7 +538,7 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
530
538
  noExternal: /.*/,
531
539
  // Exclude any Node.js built in module and provided dependencies (currently build defined externals)
532
540
  external: externalMetadata.explicitServer,
533
- optimizeDeps: getDepOptimizationConfig({
541
+ optimizeDeps: (0, utils_1.getDepOptimizationConfig)({
534
542
  // Only enable with caching since it causes prebundle dependencies to be cached
535
543
  disabled: serverOptions.prebundle === false,
536
544
  // Exclude any explicitly defined dependencies (currently build defined externals and node.js built-ins)
@@ -561,12 +569,13 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
561
569
  await (0, plugins_1.createAngularMemoryPlugin)({
562
570
  virtualProjectRoot,
563
571
  outputFiles,
572
+ templateUpdates,
564
573
  external: externalMetadata.explicitBrowser,
565
574
  skipViteClient: serverOptions.liveReload === false && serverOptions.hmr === false,
566
575
  }),
567
576
  ],
568
577
  // Browser only optimizeDeps. (This does not run for SSR dependencies).
569
- optimizeDeps: getDepOptimizationConfig({
578
+ optimizeDeps: (0, utils_1.getDepOptimizationConfig)({
570
579
  // Only enable with caching since it causes prebundle dependencies to be cached
571
580
  disabled: serverOptions.prebundle === false,
572
581
  // Exclude any explicitly defined dependencies (currently build defined externals)
@@ -599,60 +608,6 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
599
608
  }
600
609
  return configuration;
601
610
  }
602
- function getDepOptimizationConfig({ disabled, exclude, include, target, zoneless, prebundleTransformer, ssr, loader, thirdPartySourcemaps, }) {
603
- const plugins = [
604
- {
605
- name: 'angular-browser-node-built-in',
606
- setup(build) {
607
- // This namespace is configured by vite.
608
- // @see: https://github.com/vitejs/vite/blob/a1dd396da856401a12c921d0cd2c4e97cb63f1b5/packages/vite/src/node/optimizer/esbuildDepPlugin.ts#L109
609
- build.onLoad({ filter: /.*/, namespace: 'browser-external' }, (args) => {
610
- if (!(0, node_module_1.isBuiltin)(args.path)) {
611
- return;
612
- }
613
- return {
614
- errors: [
615
- {
616
- text: `The package "${args.path}" wasn't found on the file system but is built into node.`,
617
- },
618
- ],
619
- };
620
- });
621
- },
622
- },
623
- {
624
- name: `angular-vite-optimize-deps${ssr ? '-ssr' : ''}${thirdPartySourcemaps ? '-vendor-sourcemap' : ''}`,
625
- setup(build) {
626
- build.onLoad({ filter: /\.[cm]?js$/ }, async (args) => {
627
- return {
628
- contents: await prebundleTransformer.transformFile(args.path),
629
- loader: 'js',
630
- };
631
- });
632
- },
633
- },
634
- ];
635
- return {
636
- // Exclude any explicitly defined dependencies (currently build defined externals)
637
- exclude,
638
- // NB: to disable the deps optimizer, set optimizeDeps.noDiscovery to true and optimizeDeps.include as undefined.
639
- // Include all implict dependencies from the external packages internal option
640
- include: disabled ? undefined : include,
641
- noDiscovery: disabled,
642
- // Add an esbuild plugin to run the Angular linker on dependencies
643
- esbuildOptions: {
644
- // Set esbuild supported targets.
645
- target,
646
- supported: (0, internal_1.getFeatureSupport)(target, zoneless),
647
- plugins,
648
- loader,
649
- define: {
650
- 'ngServerMode': `${ssr}`,
651
- },
652
- resolveExtensions: ['.mjs', '.js', '.cjs'],
653
- },
654
- };
655
- }
656
611
  /**
657
612
  * Checks if the given value is an absolute URL.
658
613
  *
@@ -102,6 +102,7 @@ class AotCompilation extends angular_compilation_1.AngularCompilation {
102
102
  if (relativePath.startsWith('..')) {
103
103
  relativePath = componentFilename;
104
104
  }
105
+ relativePath = relativePath.replaceAll('\\', '/');
105
106
  const updateId = encodeURIComponent(`${host.getCanonicalFileName(relativePath)}@${node.name?.text}`);
106
107
  const updateText = angularCompiler.emitHmrUpdateModule(node);
107
108
  if (updateText === null) {
@@ -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: isNodePlatform
150
- ? {
151
- js: [
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: isNodePlatform
281
- ? {
282
- js: [
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
@@ -35,13 +40,31 @@ async function createAngularMemoryPlugin(options) {
35
40
  const [importerFile] = importer.split('?', 1);
36
41
  source = '/' + (0, node_path_1.join)((0, node_path_1.dirname)((0, node_path_1.relative)(virtualProjectRoot, importerFile)), source);
37
42
  }
43
+ else if (!ssr &&
44
+ source[0] === '/' &&
45
+ importer.endsWith('index.html') &&
46
+ normalizePath(importer).startsWith(virtualProjectRoot)) {
47
+ // This is only needed when using SSR and `angularSsrMiddleware` (old style) to correctly resolve
48
+ // .js files when using lazy-loading.
49
+ // Remove query if present
50
+ const [importerFile] = importer.split('?', 1);
51
+ source =
52
+ '/' + (0, node_path_1.join)((0, node_path_1.dirname)((0, node_path_1.relative)(virtualProjectRoot, importerFile)), (0, node_path_1.basename)(source));
53
+ }
38
54
  }
39
55
  const [file] = source.split('?', 1);
40
56
  if (outputFiles.has(file)) {
41
57
  return (0, node_path_1.join)(virtualProjectRoot, source);
42
58
  }
43
59
  },
44
- load(id) {
60
+ load(id, loadOptions) {
61
+ // For SSR component updates, return the component update module or empty if none
62
+ if (loadOptions?.ssr && id.startsWith(`\0${ANGULAR_PREFIX}`)) {
63
+ // Extract component identifier (first character is rollup virtual module null)
64
+ const requestUrl = new URL(id.slice(1), 'http://localhost');
65
+ const componentId = requestUrl.searchParams.get('c');
66
+ return (componentId && options.templateUpdates?.get(componentId)) ?? '';
67
+ }
45
68
  const [file] = id.split('?', 1);
46
69
  const relativeFile = '/' + normalizePath((0, node_path_1.relative)(virtualProjectRoot, file));
47
70
  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;
@@ -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 + "'" : undefined;
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.body.appendChild(s);
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.body.appendChild(s);
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.4';
13
+ const VERSION = '19.0.6';
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
- const source = await javascriptTransformer.transformFile(filePath);
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,
@@ -0,0 +1,6 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "types": ["node"]
5
+ }
6
+ }