@angular/build 19.0.0-next.1 → 19.0.0-next.11
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/LICENSE +5 -5
- package/package.json +26 -22
- package/src/builders/application/build-action.js +9 -9
- package/src/builders/application/chunk-optimizer.js +1 -4
- package/src/builders/application/execute-build.js +19 -2
- package/src/builders/application/execute-post-bundle.d.ts +2 -2
- package/src/builders/application/execute-post-bundle.js +58 -20
- package/src/builders/application/i18n.d.ts +2 -2
- package/src/builders/application/i18n.js +6 -16
- package/src/builders/application/index.js +8 -5
- package/src/builders/application/options.d.ts +38 -1
- package/src/builders/application/options.js +62 -4
- package/src/builders/application/results.d.ts +5 -3
- package/src/builders/application/schema.d.ts +72 -0
- package/src/builders/application/schema.js +29 -1
- package/src/builders/application/schema.json +38 -0
- package/src/builders/application/setup-bundling.js +12 -9
- package/src/builders/dev-server/internal.d.ts +0 -1
- package/src/builders/dev-server/internal.js +1 -3
- package/src/builders/dev-server/vite-server.d.ts +8 -2
- package/src/builders/dev-server/vite-server.js +132 -58
- package/src/builders/extract-i18n/application-extraction.js +3 -3
- package/src/tools/angular/angular-host.d.ts +2 -1
- package/src/tools/angular/angular-host.js +17 -1
- package/src/tools/angular/compilation/angular-compilation.d.ts +1 -0
- package/src/tools/angular/compilation/aot-compilation.d.ts +1 -0
- package/src/tools/angular/compilation/aot-compilation.js +9 -1
- package/src/tools/angular/compilation/parallel-compilation.d.ts +2 -1
- package/src/tools/angular/compilation/parallel-compilation.js +4 -12
- package/src/tools/angular/compilation/parallel-worker.d.ts +1 -0
- package/src/tools/angular/compilation/parallel-worker.js +5 -2
- package/src/tools/babel/plugins/add-code-coverage.d.ts +14 -0
- package/src/tools/babel/plugins/add-code-coverage.js +44 -0
- package/src/tools/babel/plugins/types.d.ts +20 -0
- package/src/tools/esbuild/angular/compiler-plugin.d.ts +2 -0
- package/src/tools/esbuild/angular/compiler-plugin.js +69 -10
- package/src/tools/esbuild/angular/component-stylesheets.d.ts +10 -4
- package/src/tools/esbuild/angular/component-stylesheets.js +49 -12
- package/src/tools/esbuild/angular/file-reference-tracker.d.ts +1 -1
- package/src/tools/esbuild/angular/jit-plugin-callbacks.d.ts +1 -1
- package/src/tools/esbuild/angular/jit-plugin-callbacks.js +2 -2
- package/src/tools/esbuild/application-code-bundle.d.ts +2 -6
- package/src/tools/esbuild/application-code-bundle.js +233 -71
- package/src/tools/esbuild/budget-stats.js +1 -1
- package/src/tools/esbuild/bundler-context.d.ts +4 -3
- package/src/tools/esbuild/bundler-context.js +24 -19
- package/src/tools/esbuild/bundler-execution-result.d.ts +5 -2
- package/src/tools/esbuild/bundler-execution-result.js +7 -3
- package/src/tools/esbuild/cache.d.ts +6 -1
- package/src/tools/esbuild/cache.js +7 -0
- package/src/tools/esbuild/compiler-plugin-options.js +6 -1
- package/src/tools/esbuild/global-scripts.js +1 -1
- package/src/tools/esbuild/global-styles.js +3 -0
- package/src/tools/esbuild/i18n-inliner.js +4 -4
- package/src/tools/esbuild/javascript-transformer-worker.d.ts +1 -0
- package/src/tools/esbuild/javascript-transformer-worker.js +5 -1
- package/src/tools/esbuild/javascript-transformer.d.ts +2 -2
- package/src/tools/esbuild/javascript-transformer.js +7 -12
- package/src/tools/esbuild/server-bundle-metadata-plugin.d.ts +22 -0
- package/src/tools/esbuild/server-bundle-metadata-plugin.js +36 -0
- package/src/tools/esbuild/stylesheets/bundle-options.d.ts +2 -0
- package/src/tools/esbuild/stylesheets/bundle-options.js +2 -1
- package/src/tools/esbuild/stylesheets/sass-language.js +4 -0
- package/src/tools/esbuild/stylesheets/stylesheet-plugin-factory.d.ts +9 -0
- package/src/tools/esbuild/utils.d.ts +9 -0
- package/src/tools/esbuild/utils.js +33 -4
- package/src/tools/sass/sass-service.js +11 -13
- package/src/tools/sass/worker.d.ts +13 -32
- package/src/tools/sass/worker.js +20 -0
- package/src/tools/vite/middlewares/assets-middleware.d.ts +1 -1
- package/src/tools/vite/middlewares/assets-middleware.js +43 -4
- package/src/tools/vite/middlewares/component-middleware.d.ts +9 -0
- package/src/tools/vite/middlewares/component-middleware.js +33 -0
- package/src/tools/vite/middlewares/headers-middleware.d.ts +19 -0
- package/src/tools/vite/middlewares/headers-middleware.js +34 -0
- package/src/tools/vite/middlewares/html-fallback-middleware.d.ts +1 -1
- package/src/tools/vite/middlewares/html-fallback-middleware.js +23 -7
- package/src/tools/vite/middlewares/index-html-middleware.js +1 -2
- package/src/tools/vite/middlewares/index.d.ts +3 -1
- package/src/tools/vite/middlewares/index.js +7 -2
- package/src/tools/vite/middlewares/ssr-middleware.d.ts +2 -4
- package/src/tools/vite/middlewares/ssr-middleware.js +75 -43
- package/src/tools/vite/plugins/angular-memory-plugin.d.ts +16 -0
- package/src/tools/vite/{angular-memory-plugin.js → plugins/angular-memory-plugin.js} +19 -40
- package/src/tools/vite/{i18n-locale-plugin.d.ts → plugins/i18n-locale-plugin.d.ts} +0 -4
- package/src/tools/vite/{i18n-locale-plugin.js → plugins/i18n-locale-plugin.js} +2 -3
- package/src/tools/vite/plugins/index.d.ts +12 -0
- package/src/tools/vite/plugins/index.js +21 -0
- package/src/tools/vite/plugins/setup-middlewares-plugin.d.ts +42 -0
- package/src/tools/vite/plugins/setup-middlewares-plugin.js +63 -0
- package/src/{utils/server-rendering/main-bundle-exports.js → tools/vite/plugins/ssr-transform-plugin.d.ts} +2 -2
- package/src/tools/vite/plugins/ssr-transform-plugin.js +38 -0
- package/src/tools/vite/utils.d.ts +0 -3
- package/src/tools/vite/utils.js +0 -12
- package/src/typings.d.ts +26 -0
- package/src/utils/environment-options.d.ts +2 -0
- package/src/utils/environment-options.js +5 -1
- package/src/utils/index-file/index-html-generator.js +5 -0
- package/src/utils/index-file/inline-critical-css.js +43 -33
- package/src/utils/index-file/ngcm-attribute.d.ts +15 -0
- package/src/utils/index-file/ngcm-attribute.js +37 -0
- package/src/utils/index-file/valid-self-closing-tags.js +28 -0
- package/src/utils/normalize-cache.js +1 -1
- package/src/utils/server-rendering/fetch-patch.d.ts +1 -1
- package/src/utils/server-rendering/fetch-patch.js +5 -6
- package/src/utils/server-rendering/launch-server.d.ts +14 -0
- package/src/utils/server-rendering/launch-server.js +63 -0
- package/src/utils/server-rendering/load-esm-from-memory.d.ts +18 -2
- package/src/utils/server-rendering/manifest.d.ts +50 -0
- package/src/utils/server-rendering/manifest.js +126 -0
- package/src/utils/server-rendering/models.d.ts +27 -0
- package/src/utils/server-rendering/models.js +22 -0
- package/src/utils/server-rendering/prerender.d.ts +26 -10
- package/src/utils/server-rendering/prerender.js +122 -75
- package/src/utils/server-rendering/render-worker.d.ts +9 -8
- package/src/utils/server-rendering/render-worker.js +19 -14
- package/src/utils/server-rendering/routes-extractor-worker.d.ts +6 -10
- package/src/utils/server-rendering/routes-extractor-worker.js +16 -33
- package/src/utils/server-rendering/utils.d.ts +11 -0
- package/src/utils/server-rendering/utils.js +17 -0
- package/src/utils/supported-browsers.js +1 -0
- package/src/utils/worker-pool.d.ts +12 -0
- package/src/utils/worker-pool.js +43 -0
- package/src/tools/vite/angular-memory-plugin.d.ts +0 -21
- package/src/utils/server-rendering/main-bundle-exports.d.ts +0 -27
- package/src/utils/server-rendering/render-page.d.ts +0 -26
- package/src/utils/server-rendering/render-page.js +0 -114
- /package/src/tools/vite/{id-prefix-plugin.d.ts → plugins/id-prefix-plugin.d.ts} +0 -0
- /package/src/tools/vite/{id-prefix-plugin.js → plugins/id-prefix-plugin.js} +0 -0
|
@@ -45,6 +45,9 @@ function createGlobalStylesBundleOptions(options, target, initial) {
|
|
|
45
45
|
bundles: '[name]',
|
|
46
46
|
},
|
|
47
47
|
includePaths: stylePreprocessorOptions?.includePaths,
|
|
48
|
+
// string[] | undefined' is not assignable to type '(Version | DeprecationOrId)[] | undefined'.
|
|
49
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
50
|
+
sass: stylePreprocessorOptions?.sass,
|
|
48
51
|
tailwindConfiguration,
|
|
49
52
|
postcssConfiguration,
|
|
50
53
|
cacheOptions,
|
|
@@ -12,7 +12,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
12
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
13
|
exports.I18nInliner = void 0;
|
|
14
14
|
const node_assert_1 = __importDefault(require("node:assert"));
|
|
15
|
-
const
|
|
15
|
+
const worker_pool_1 = require("../../utils/worker-pool");
|
|
16
16
|
const bundler_context_1 = require("./bundler-context");
|
|
17
17
|
const utils_1 = require("./utils");
|
|
18
18
|
/**
|
|
@@ -36,7 +36,8 @@ class I18nInliner {
|
|
|
36
36
|
const files = new Map();
|
|
37
37
|
const pendingMaps = [];
|
|
38
38
|
for (const file of options.outputFiles) {
|
|
39
|
-
if (file.type === bundler_context_1.BuildOutputFileType.Root) {
|
|
39
|
+
if (file.type === bundler_context_1.BuildOutputFileType.Root || file.type === bundler_context_1.BuildOutputFileType.ServerRoot) {
|
|
40
|
+
// Skip also the server entry-point.
|
|
40
41
|
// Skip stats and similar files.
|
|
41
42
|
continue;
|
|
42
43
|
}
|
|
@@ -74,7 +75,7 @@ class I18nInliner {
|
|
|
74
75
|
}
|
|
75
76
|
}
|
|
76
77
|
this.#localizeFiles = files;
|
|
77
|
-
this.#workerPool = new
|
|
78
|
+
this.#workerPool = new worker_pool_1.WorkerPool({
|
|
78
79
|
filename: require.resolve('./i18n-inliner-worker'),
|
|
79
80
|
maxThreads,
|
|
80
81
|
// Extract options to ensure only the named options are serialized and sent to the worker
|
|
@@ -83,7 +84,6 @@ class I18nInliner {
|
|
|
83
84
|
shouldOptimize: options.shouldOptimize,
|
|
84
85
|
files,
|
|
85
86
|
},
|
|
86
|
-
recordTiming: false,
|
|
87
87
|
});
|
|
88
88
|
}
|
|
89
89
|
/**
|
|
@@ -14,6 +14,7 @@ interface JavaScriptTransformRequest {
|
|
|
14
14
|
skipLinker?: boolean;
|
|
15
15
|
sideEffects?: boolean;
|
|
16
16
|
jit: boolean;
|
|
17
|
+
instrumentForCoverage?: boolean;
|
|
17
18
|
}
|
|
18
19
|
export default function transformJavaScript(request: JavaScriptTransformRequest): Promise<unknown>;
|
|
19
20
|
export {};
|
|
@@ -63,8 +63,12 @@ async function transformWithBabel(filename, data, options) {
|
|
|
63
63
|
// @ts-expect-error Import attribute syntax plugin does not currently have type definitions
|
|
64
64
|
const { default: importAttributePlugin } = await Promise.resolve().then(() => __importStar(require('@babel/plugin-syntax-import-attributes')));
|
|
65
65
|
const plugins = [importAttributePlugin];
|
|
66
|
-
|
|
66
|
+
if (options.instrumentForCoverage) {
|
|
67
|
+
const { default: coveragePlugin } = await Promise.resolve().then(() => __importStar(require('../babel/plugins/add-code-coverage.js')));
|
|
68
|
+
plugins.push(coveragePlugin);
|
|
69
|
+
}
|
|
67
70
|
if (shouldLink) {
|
|
71
|
+
// Lazy load the linker plugin only when linking is required
|
|
68
72
|
const linkerPlugin = await createLinkerPlugin(options);
|
|
69
73
|
plugins.push(linkerPlugin);
|
|
70
74
|
}
|
|
@@ -35,7 +35,7 @@ export declare class JavaScriptTransformer {
|
|
|
35
35
|
* @param sideEffects If false, and `advancedOptimizations` is enabled tslib decorators are wrapped.
|
|
36
36
|
* @returns A promise that resolves to a UTF-8 encoded Uint8Array containing the result.
|
|
37
37
|
*/
|
|
38
|
-
transformFile(filename: string, skipLinker?: boolean, sideEffects?: boolean): Promise<Uint8Array>;
|
|
38
|
+
transformFile(filename: string, skipLinker?: boolean, sideEffects?: boolean, instrumentForCoverage?: boolean): Promise<Uint8Array>;
|
|
39
39
|
/**
|
|
40
40
|
* Performs JavaScript transformations on the provided data of a file. The file does not need
|
|
41
41
|
* to exist on the filesystem.
|
|
@@ -45,7 +45,7 @@ export declare class JavaScriptTransformer {
|
|
|
45
45
|
* @param sideEffects If false, and `advancedOptimizations` is enabled tslib decorators are wrapped.
|
|
46
46
|
* @returns A promise that resolves to a UTF-8 encoded Uint8Array containing the result.
|
|
47
47
|
*/
|
|
48
|
-
transformData(filename: string, data: string, skipLinker: boolean, sideEffects?: boolean): Promise<Uint8Array>;
|
|
48
|
+
transformData(filename: string, data: string, skipLinker: boolean, sideEffects?: boolean, instrumentForCoverage?: boolean): Promise<Uint8Array>;
|
|
49
49
|
/**
|
|
50
50
|
* Stops all active transformation tasks and shuts down all workers.
|
|
51
51
|
* @returns A void promise that resolves when closing is complete.
|
|
@@ -6,14 +6,11 @@
|
|
|
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 __importDefault = (this && this.__importDefault) || function (mod) {
|
|
10
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
11
|
-
};
|
|
12
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
10
|
exports.JavaScriptTransformer = void 0;
|
|
14
11
|
const node_crypto_1 = require("node:crypto");
|
|
15
12
|
const promises_1 = require("node:fs/promises");
|
|
16
|
-
const
|
|
13
|
+
const worker_pool_1 = require("../../utils/worker-pool");
|
|
17
14
|
/**
|
|
18
15
|
* A class that performs transformation of JavaScript files and raw data.
|
|
19
16
|
* A worker pool is used to distribute the transformation actions and allow
|
|
@@ -41,13 +38,9 @@ class JavaScriptTransformer {
|
|
|
41
38
|
this.#fileCacheKeyBase = Buffer.from(JSON.stringify(this.#commonOptions), 'utf-8');
|
|
42
39
|
}
|
|
43
40
|
#ensureWorkerPool() {
|
|
44
|
-
this.#workerPool ??= new
|
|
41
|
+
this.#workerPool ??= new worker_pool_1.WorkerPool({
|
|
45
42
|
filename: require.resolve('./javascript-transformer-worker'),
|
|
46
|
-
minThreads: 1,
|
|
47
43
|
maxThreads: this.maxThreads,
|
|
48
|
-
// Shutdown idle threads after 1 second of inactivity
|
|
49
|
-
idleTimeout: 1000,
|
|
50
|
-
recordTiming: false,
|
|
51
44
|
});
|
|
52
45
|
return this.#workerPool;
|
|
53
46
|
}
|
|
@@ -59,7 +52,7 @@ class JavaScriptTransformer {
|
|
|
59
52
|
* @param sideEffects If false, and `advancedOptimizations` is enabled tslib decorators are wrapped.
|
|
60
53
|
* @returns A promise that resolves to a UTF-8 encoded Uint8Array containing the result.
|
|
61
54
|
*/
|
|
62
|
-
async transformFile(filename, skipLinker, sideEffects) {
|
|
55
|
+
async transformFile(filename, skipLinker, sideEffects, instrumentForCoverage) {
|
|
63
56
|
const data = await (0, promises_1.readFile)(filename);
|
|
64
57
|
let result;
|
|
65
58
|
let cacheKey;
|
|
@@ -86,6 +79,7 @@ class JavaScriptTransformer {
|
|
|
86
79
|
data,
|
|
87
80
|
skipLinker,
|
|
88
81
|
sideEffects,
|
|
82
|
+
instrumentForCoverage,
|
|
89
83
|
...this.#commonOptions,
|
|
90
84
|
}, {
|
|
91
85
|
// The below is disable as with Yarn PNP this causes build failures with the below message
|
|
@@ -113,10 +107,10 @@ class JavaScriptTransformer {
|
|
|
113
107
|
* @param sideEffects If false, and `advancedOptimizations` is enabled tslib decorators are wrapped.
|
|
114
108
|
* @returns A promise that resolves to a UTF-8 encoded Uint8Array containing the result.
|
|
115
109
|
*/
|
|
116
|
-
async transformData(filename, data, skipLinker, sideEffects) {
|
|
110
|
+
async transformData(filename, data, skipLinker, sideEffects, instrumentForCoverage) {
|
|
117
111
|
// Perform a quick test to determine if the data needs any transformations.
|
|
118
112
|
// This allows directly returning the data without the worker communication overhead.
|
|
119
|
-
if (skipLinker && !this.#commonOptions.advancedOptimizations) {
|
|
113
|
+
if (skipLinker && !this.#commonOptions.advancedOptimizations && !instrumentForCoverage) {
|
|
120
114
|
const keepSourcemap = this.#commonOptions.sourcemap &&
|
|
121
115
|
(!!this.#commonOptions.thirdPartySourcemaps || !/[\\/]node_modules[\\/]/.test(filename));
|
|
122
116
|
return Buffer.from(keepSourcemap ? data : data.replace(/^\/\/# sourceMappingURL=[^\r\n]*/gm, ''), 'utf-8');
|
|
@@ -126,6 +120,7 @@ class JavaScriptTransformer {
|
|
|
126
120
|
data,
|
|
127
121
|
skipLinker,
|
|
128
122
|
sideEffects,
|
|
123
|
+
instrumentForCoverage,
|
|
129
124
|
...this.#commonOptions,
|
|
130
125
|
});
|
|
131
126
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright Google LLC All Rights Reserved.
|
|
4
|
+
*
|
|
5
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
6
|
+
* found in the LICENSE file at https://angular.dev/license
|
|
7
|
+
*/
|
|
8
|
+
import type { Plugin } from 'esbuild';
|
|
9
|
+
/**
|
|
10
|
+
* Generates an esbuild plugin that appends metadata to the output bundle,
|
|
11
|
+
* marking it with server-side rendering (SSR) details for Angular SSR scenarios.
|
|
12
|
+
*
|
|
13
|
+
* @param options Optional configuration object.
|
|
14
|
+
* - `ssrEntryBundle`: If `true`, marks the bundle as an SSR entry point.
|
|
15
|
+
*
|
|
16
|
+
* @note We can't rely on `platform: node` or `platform: neutral`, as the latter
|
|
17
|
+
* is used for non-SSR-related code too (e.g., global scripts).
|
|
18
|
+
* @returns An esbuild plugin that injects SSR metadata into the build result's metafile.
|
|
19
|
+
*/
|
|
20
|
+
export declare function createServerBundleMetadata(options?: {
|
|
21
|
+
ssrEntryBundle?: boolean;
|
|
22
|
+
}): Plugin;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @license
|
|
4
|
+
* Copyright Google LLC All Rights Reserved.
|
|
5
|
+
*
|
|
6
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
7
|
+
* found in the LICENSE file at https://angular.dev/license
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.createServerBundleMetadata = createServerBundleMetadata;
|
|
11
|
+
/**
|
|
12
|
+
* Generates an esbuild plugin that appends metadata to the output bundle,
|
|
13
|
+
* marking it with server-side rendering (SSR) details for Angular SSR scenarios.
|
|
14
|
+
*
|
|
15
|
+
* @param options Optional configuration object.
|
|
16
|
+
* - `ssrEntryBundle`: If `true`, marks the bundle as an SSR entry point.
|
|
17
|
+
*
|
|
18
|
+
* @note We can't rely on `platform: node` or `platform: neutral`, as the latter
|
|
19
|
+
* is used for non-SSR-related code too (e.g., global scripts).
|
|
20
|
+
* @returns An esbuild plugin that injects SSR metadata into the build result's metafile.
|
|
21
|
+
*/
|
|
22
|
+
function createServerBundleMetadata(options) {
|
|
23
|
+
return {
|
|
24
|
+
name: 'angular-server-bundle-metadata',
|
|
25
|
+
setup(build) {
|
|
26
|
+
build.onEnd((result) => {
|
|
27
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
28
|
+
const metafile = result.metafile;
|
|
29
|
+
if (metafile) {
|
|
30
|
+
metafile['ng-ssr-entry-bundle'] = !!options?.ssrEntryBundle;
|
|
31
|
+
metafile['ng-platform-server'] = true;
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
}
|
|
@@ -9,6 +9,7 @@ import type { BuildOptions } from 'esbuild';
|
|
|
9
9
|
import { NormalizedCachedOptions } from '../../../utils/normalize-cache';
|
|
10
10
|
import { PostcssConfiguration } from '../../../utils/postcss-configuration';
|
|
11
11
|
import { LoadResultCache } from '../load-result-cache';
|
|
12
|
+
import { StylesheetPluginsass } from './stylesheet-plugin-factory';
|
|
12
13
|
export interface BundleStylesheetOptions {
|
|
13
14
|
workspaceRoot: string;
|
|
14
15
|
optimization: boolean;
|
|
@@ -20,6 +21,7 @@ export interface BundleStylesheetOptions {
|
|
|
20
21
|
media: string;
|
|
21
22
|
};
|
|
22
23
|
includePaths?: string[];
|
|
24
|
+
sass?: StylesheetPluginsass;
|
|
23
25
|
externalDependencies?: string[];
|
|
24
26
|
target: string[];
|
|
25
27
|
tailwindConfiguration?: {
|
|
@@ -27,6 +27,7 @@ function createStylesheetBundleOptions(options, cache, inlineComponentData) {
|
|
|
27
27
|
inlineComponentData,
|
|
28
28
|
tailwindConfiguration: options.tailwindConfiguration,
|
|
29
29
|
postcssConfiguration: options.postcssConfiguration,
|
|
30
|
+
sass: options.sass,
|
|
30
31
|
}, cache);
|
|
31
32
|
const plugins = [
|
|
32
33
|
pluginFactory.create(sass_language_1.SassStylesheetLanguage),
|
|
@@ -53,7 +54,7 @@ function createStylesheetBundleOptions(options, cache, inlineComponentData) {
|
|
|
53
54
|
preserveSymlinks: options.preserveSymlinks,
|
|
54
55
|
external: options.externalDependencies,
|
|
55
56
|
publicPath: options.publicPath,
|
|
56
|
-
conditions: ['style', 'sass', 'less'],
|
|
57
|
+
conditions: ['style', 'sass', 'less', options.optimization ? 'production' : 'development'],
|
|
57
58
|
mainFields: ['style', 'sass'],
|
|
58
59
|
// Unlike JS, CSS does not have implicit file extensions in the general case.
|
|
59
60
|
// Preprocessor specific behavior is handled in each stylesheet language plugin.
|
|
@@ -99,6 +99,7 @@ async function compileString(data, filePath, syntax, options, resolveUrl) {
|
|
|
99
99
|
const resolutionCache = new cache_1.MemoryCache();
|
|
100
100
|
const packageRootCache = new cache_1.MemoryCache();
|
|
101
101
|
const warnings = [];
|
|
102
|
+
const { silenceDeprecations, futureDeprecations, fatalDeprecations } = options.sass ?? {};
|
|
102
103
|
try {
|
|
103
104
|
const { css, sourceMap, loadedUrls } = await sassWorkerPool.compileStringAsync(data, {
|
|
104
105
|
url: (0, node_url_1.pathToFileURL)(filePath),
|
|
@@ -107,6 +108,9 @@ async function compileString(data, filePath, syntax, options, resolveUrl) {
|
|
|
107
108
|
loadPaths: options.includePaths,
|
|
108
109
|
sourceMap: options.sourcemap,
|
|
109
110
|
sourceMapIncludeSources: options.sourcemap,
|
|
111
|
+
silenceDeprecations,
|
|
112
|
+
fatalDeprecations,
|
|
113
|
+
futureDeprecations,
|
|
110
114
|
quietDeps: true,
|
|
111
115
|
importers: [
|
|
112
116
|
{
|
|
@@ -6,8 +6,13 @@
|
|
|
6
6
|
* found in the LICENSE file at https://angular.dev/license
|
|
7
7
|
*/
|
|
8
8
|
import type { OnLoadResult, Plugin, PluginBuild } from 'esbuild';
|
|
9
|
+
import type { Options } from 'sass';
|
|
9
10
|
import type { PostcssConfiguration } from '../../../utils/postcss-configuration';
|
|
10
11
|
import { LoadResultCache } from '../load-result-cache';
|
|
12
|
+
/**
|
|
13
|
+
* Configuration options for handling Sass-specific deprecations in a stylesheet plugin.
|
|
14
|
+
*/
|
|
15
|
+
export type StylesheetPluginsass = Pick<Options<'async'>, 'futureDeprecations' | 'fatalDeprecations' | 'silenceDeprecations'>;
|
|
11
16
|
/**
|
|
12
17
|
* An object containing the plugin options to use when processing stylesheets.
|
|
13
18
|
*/
|
|
@@ -42,6 +47,10 @@ export interface StylesheetPluginOptions {
|
|
|
42
47
|
* and any tailwind usage must be manually configured in the custom postcss usage.
|
|
43
48
|
*/
|
|
44
49
|
postcssConfiguration?: PostcssConfiguration;
|
|
50
|
+
/**
|
|
51
|
+
* Optional Options for configuring Sass behavior.
|
|
52
|
+
*/
|
|
53
|
+
sass?: StylesheetPluginsass;
|
|
45
54
|
}
|
|
46
55
|
export interface StylesheetLanguage {
|
|
47
56
|
name: string;
|
|
@@ -47,3 +47,12 @@ export declare function logMessages(logger: BuilderContext['logger'], executionR
|
|
|
47
47
|
*/
|
|
48
48
|
export declare function isZonelessApp(polyfills: string[] | undefined): boolean;
|
|
49
49
|
export declare function getEntryPointName(entryPoint: string): string;
|
|
50
|
+
/**
|
|
51
|
+
* A set of server-generated dependencies that are treated as external.
|
|
52
|
+
*
|
|
53
|
+
* These dependencies are marked as external because they are produced by a
|
|
54
|
+
* separate bundling process and are not included in the primary bundle. This
|
|
55
|
+
* ensures that these generated files are resolved from an external source rather
|
|
56
|
+
* than being part of the main bundle.
|
|
57
|
+
*/
|
|
58
|
+
export declare const SERVER_GENERATED_EXTERNALS: Set<string>;
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* found in the LICENSE file at https://angular.dev/license
|
|
8
8
|
*/
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.SERVER_GENERATED_EXTERNALS = void 0;
|
|
10
11
|
exports.logBuildStats = logBuildStats;
|
|
11
12
|
exports.getChunkNameFromMetafile = getChunkNameFromMetafile;
|
|
12
13
|
exports.calculateEstimatedTransferSizes = calculateEstimatedTransferSizes;
|
|
@@ -29,12 +30,15 @@ const node_path_1 = require("node:path");
|
|
|
29
30
|
const node_url_1 = require("node:url");
|
|
30
31
|
const node_zlib_1 = require("node:zlib");
|
|
31
32
|
const semver_1 = require("semver");
|
|
33
|
+
const schema_1 = require("../../builders/application/schema");
|
|
34
|
+
const manifest_1 = require("../../utils/server-rendering/manifest");
|
|
32
35
|
const stats_table_1 = require("../../utils/stats-table");
|
|
33
36
|
const bundler_context_1 = require("./bundler-context");
|
|
34
37
|
function logBuildStats(metafile, outputFiles, initial, budgetFailures, colors, changedFiles, estimatedTransferSizes, ssrOutputEnabled, verbose) {
|
|
35
38
|
const browserStats = [];
|
|
36
39
|
const serverStats = [];
|
|
37
40
|
let unchangedCount = 0;
|
|
41
|
+
let componentStyleChange = false;
|
|
38
42
|
for (const { path: file, size, type } of outputFiles) {
|
|
39
43
|
// Only display JavaScript and CSS files
|
|
40
44
|
if (!/\.(?:css|m?js)$/.test(file)) {
|
|
@@ -45,11 +49,16 @@ function logBuildStats(metafile, outputFiles, initial, budgetFailures, colors, c
|
|
|
45
49
|
++unchangedCount;
|
|
46
50
|
continue;
|
|
47
51
|
}
|
|
48
|
-
const isPlatformServer = type === bundler_context_1.BuildOutputFileType.
|
|
52
|
+
const isPlatformServer = type === bundler_context_1.BuildOutputFileType.ServerApplication || type === bundler_context_1.BuildOutputFileType.ServerRoot;
|
|
49
53
|
if (isPlatformServer && !ssrOutputEnabled) {
|
|
50
54
|
// Only log server build stats when SSR is enabled.
|
|
51
55
|
continue;
|
|
52
56
|
}
|
|
57
|
+
// Skip logging external component stylesheets used for HMR
|
|
58
|
+
if (metafile.outputs[file] && 'ng-component' in metafile.outputs[file]) {
|
|
59
|
+
componentStyleChange = true;
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
53
62
|
const name = initial.get(file)?.name ?? getChunkNameFromMetafile(metafile, file);
|
|
54
63
|
const stat = {
|
|
55
64
|
initial: initial.has(file),
|
|
@@ -67,7 +76,12 @@ function logBuildStats(metafile, outputFiles, initial, budgetFailures, colors, c
|
|
|
67
76
|
return tableText + '\n';
|
|
68
77
|
}
|
|
69
78
|
else if (changedFiles !== undefined) {
|
|
70
|
-
|
|
79
|
+
if (componentStyleChange) {
|
|
80
|
+
return '\nComponent stylesheet(s) changed.\n';
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
return '\nNo output file changes.\n';
|
|
84
|
+
}
|
|
71
85
|
}
|
|
72
86
|
if (unchangedCount > 0) {
|
|
73
87
|
return `Unchanged output files: ${unchangedCount}`;
|
|
@@ -340,7 +354,7 @@ function getSupportedNodeTargets() {
|
|
|
340
354
|
return SUPPORTED_NODE_VERSIONS.split('||').map((v) => 'node' + (0, semver_1.coerce)(v)?.version);
|
|
341
355
|
}
|
|
342
356
|
async function createJsonBuildManifest(result, normalizedOptions) {
|
|
343
|
-
const { colors: color, outputOptions: { base, server, browser }, ssrOptions, } = normalizedOptions;
|
|
357
|
+
const { colors: color, outputOptions: { base, server, browser }, ssrOptions, outputMode, } = normalizedOptions;
|
|
344
358
|
const { warnings, errors, prerenderedRoutes } = result;
|
|
345
359
|
const manifest = {
|
|
346
360
|
errors: errors.length ? await (0, esbuild_1.formatMessages)(errors, { kind: 'error', color }) : [],
|
|
@@ -348,7 +362,9 @@ async function createJsonBuildManifest(result, normalizedOptions) {
|
|
|
348
362
|
outputPaths: {
|
|
349
363
|
root: (0, node_url_1.pathToFileURL)(base),
|
|
350
364
|
browser: (0, node_url_1.pathToFileURL)((0, node_path_1.join)(base, browser)),
|
|
351
|
-
server:
|
|
365
|
+
server: outputMode !== schema_1.OutputMode.Static && ssrOptions
|
|
366
|
+
? (0, node_url_1.pathToFileURL)((0, node_path_1.join)(base, server))
|
|
367
|
+
: undefined,
|
|
352
368
|
},
|
|
353
369
|
prerenderedRoutes,
|
|
354
370
|
};
|
|
@@ -385,3 +401,16 @@ function getEntryPointName(entryPoint) {
|
|
|
385
401
|
.replace(/\.[cm]?[jt]s$/, '')
|
|
386
402
|
.replace(/[\\/.]/g, '-');
|
|
387
403
|
}
|
|
404
|
+
/**
|
|
405
|
+
* A set of server-generated dependencies that are treated as external.
|
|
406
|
+
*
|
|
407
|
+
* These dependencies are marked as external because they are produced by a
|
|
408
|
+
* separate bundling process and are not included in the primary bundle. This
|
|
409
|
+
* ensures that these generated files are resolved from an external source rather
|
|
410
|
+
* than being part of the main bundle.
|
|
411
|
+
*/
|
|
412
|
+
exports.SERVER_GENERATED_EXTERNALS = new Set([
|
|
413
|
+
'./polyfills.server.mjs',
|
|
414
|
+
'./' + manifest_1.SERVER_APP_MANIFEST_FILENAME,
|
|
415
|
+
'./' + manifest_1.SERVER_APP_ENGINE_MANIFEST_FILENAME,
|
|
416
|
+
]);
|
|
@@ -34,17 +34,22 @@ var __disposeResources = (this && this.__disposeResources) || (function (Suppres
|
|
|
34
34
|
env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
|
|
35
35
|
env.hasError = true;
|
|
36
36
|
}
|
|
37
|
+
var r, s = 0;
|
|
37
38
|
function next() {
|
|
38
|
-
while (env.stack.
|
|
39
|
-
var rec = env.stack.pop();
|
|
39
|
+
while (r = env.stack.pop()) {
|
|
40
40
|
try {
|
|
41
|
-
|
|
42
|
-
if (
|
|
41
|
+
if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
|
|
42
|
+
if (r.dispose) {
|
|
43
|
+
var result = r.dispose.call(r.value);
|
|
44
|
+
if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
|
|
45
|
+
}
|
|
46
|
+
else s |= 1;
|
|
43
47
|
}
|
|
44
48
|
catch (e) {
|
|
45
49
|
fail(e);
|
|
46
50
|
}
|
|
47
51
|
}
|
|
52
|
+
if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
|
|
48
53
|
if (env.hasError) throw env.error;
|
|
49
54
|
}
|
|
50
55
|
return next();
|
|
@@ -61,8 +66,8 @@ exports.SassWorkerImplementation = void 0;
|
|
|
61
66
|
const node_assert_1 = __importDefault(require("node:assert"));
|
|
62
67
|
const node_url_1 = require("node:url");
|
|
63
68
|
const node_worker_threads_1 = require("node:worker_threads");
|
|
64
|
-
const piscina_1 = require("piscina");
|
|
65
69
|
const environment_options_1 = require("../../utils/environment-options");
|
|
70
|
+
const worker_pool_1 = require("../../utils/worker-pool");
|
|
66
71
|
// Polyfill Symbol.dispose if not present
|
|
67
72
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
68
73
|
Symbol.dispose ??= Symbol('Symbol Dispose');
|
|
@@ -85,16 +90,9 @@ class SassWorkerImplementation {
|
|
|
85
90
|
this.maxThreads = maxThreads;
|
|
86
91
|
}
|
|
87
92
|
#ensureWorkerPool() {
|
|
88
|
-
this.#workerPool ??= new
|
|
93
|
+
this.#workerPool ??= new worker_pool_1.WorkerPool({
|
|
89
94
|
filename: require.resolve('./worker'),
|
|
90
|
-
minThreads: 1,
|
|
91
95
|
maxThreads: this.maxThreads,
|
|
92
|
-
// Web containers do not support transferable objects with receiveOnMessagePort which
|
|
93
|
-
// is used when the Atomics based wait loop is enable.
|
|
94
|
-
useAtomics: !process.versions.webcontainer,
|
|
95
|
-
// Shutdown idle threads after 1 second of inactivity
|
|
96
|
-
idleTimeout: 1000,
|
|
97
|
-
recordTiming: false,
|
|
98
96
|
});
|
|
99
97
|
return this.#workerPool;
|
|
100
98
|
}
|
|
@@ -5,6 +5,7 @@
|
|
|
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 { RawSourceMap } from '@ampproject/remapping';
|
|
8
9
|
import { MessagePort } from 'node:worker_threads';
|
|
9
10
|
import { SourceSpan, StringOptions } from 'sass';
|
|
10
11
|
import type { SerializableWarningMessage } from './sass-service';
|
|
@@ -38,45 +39,25 @@ interface RenderRequestMessage {
|
|
|
38
39
|
*/
|
|
39
40
|
rebase: boolean;
|
|
40
41
|
}
|
|
41
|
-
|
|
42
|
+
interface RenderResult {
|
|
42
43
|
warnings: SerializableWarningMessage[] | undefined;
|
|
43
44
|
result: {
|
|
44
|
-
loadedUrls: string[];
|
|
45
45
|
css: string;
|
|
46
|
-
|
|
46
|
+
loadedUrls: string[];
|
|
47
|
+
sourceMap?: RawSourceMap;
|
|
47
48
|
};
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
}
|
|
50
|
+
interface RenderError {
|
|
50
51
|
warnings: SerializableWarningMessage[] | undefined;
|
|
51
52
|
error: {
|
|
52
|
-
|
|
53
|
+
message: string;
|
|
54
|
+
stack?: string;
|
|
55
|
+
span?: Omit<SourceSpan, 'url'> & {
|
|
53
56
|
url?: string;
|
|
54
57
|
};
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
sassMessage: string;
|
|
58
|
-
sassStack: string;
|
|
59
|
-
};
|
|
60
|
-
result?: undefined;
|
|
61
|
-
} | {
|
|
62
|
-
warnings: SerializableWarningMessage[] | undefined;
|
|
63
|
-
error: {
|
|
64
|
-
message: string;
|
|
65
|
-
stack: string | undefined;
|
|
66
|
-
span?: undefined;
|
|
67
|
-
sassMessage?: undefined;
|
|
68
|
-
sassStack?: undefined;
|
|
58
|
+
sassMessage?: string;
|
|
59
|
+
sassStack?: string;
|
|
69
60
|
};
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
warnings: SerializableWarningMessage[] | undefined;
|
|
73
|
-
error: {
|
|
74
|
-
message: string;
|
|
75
|
-
span?: undefined;
|
|
76
|
-
stack?: undefined;
|
|
77
|
-
sassMessage?: undefined;
|
|
78
|
-
sassStack?: undefined;
|
|
79
|
-
};
|
|
80
|
-
result?: undefined;
|
|
81
|
-
}>;
|
|
61
|
+
}
|
|
62
|
+
export default function renderSassStylesheet(request: RenderRequestMessage): Promise<RenderResult | RenderError>;
|
|
82
63
|
export {};
|
package/src/tools/sass/worker.js
CHANGED
|
@@ -40,6 +40,25 @@ async function renderSassStylesheet(request) {
|
|
|
40
40
|
containingUrl: containingUrl ? (0, node_url_1.fileURLToPath)(containingUrl) : null,
|
|
41
41
|
},
|
|
42
42
|
});
|
|
43
|
+
// Wait for the main thread to set the signal to 1 and notify, which tells
|
|
44
|
+
// us that a message can be received on the port.
|
|
45
|
+
// If the main thread is fast, the signal will already be set to 1, and no
|
|
46
|
+
// sleep/notify is necessary.
|
|
47
|
+
// However, there can be a race condition here:
|
|
48
|
+
// - the main thread sets the signal to 1, but does not get to the notify instruction yet
|
|
49
|
+
// - the worker does not pause because the signal is set to 1
|
|
50
|
+
// - the worker very soon enters this method again
|
|
51
|
+
// - this method sets the signal to 0 and sends the message
|
|
52
|
+
// - the signal is 0 and so the `Atomics.wait` call blocks
|
|
53
|
+
// - only now the main thread runs the `notify` from the first invocation, so the
|
|
54
|
+
// worker continues.
|
|
55
|
+
// - but there is no message yet in the port, because the thread should not have been
|
|
56
|
+
// waken up yet.
|
|
57
|
+
// To combat this, wait for a non-0 value _twice_.
|
|
58
|
+
// Almost every time, this immediately continues with "not-equal", because
|
|
59
|
+
// the signal is still set to 1, except during the race condition, when the second
|
|
60
|
+
// wait will wait for the correct notify.
|
|
61
|
+
Atomics.wait(importerChannel.signal, 0, 0);
|
|
43
62
|
Atomics.wait(importerChannel.signal, 0, 0);
|
|
44
63
|
const result = (0, node_worker_threads_1.receiveMessageOnPort)(importerChannel.port)?.message;
|
|
45
64
|
return result ? (0, node_url_1.pathToFileURL)(result) : null;
|
|
@@ -95,6 +114,7 @@ async function renderSassStylesheet(request) {
|
|
|
95
114
|
warnings,
|
|
96
115
|
result: {
|
|
97
116
|
...result,
|
|
117
|
+
sourceMap: result.sourceMap,
|
|
98
118
|
// URL is not serializable so to convert to string here and back to URL in the parent.
|
|
99
119
|
loadedUrls: result.loadedUrls.map((p) => (0, node_url_1.fileURLToPath)(p)),
|
|
100
120
|
},
|
|
@@ -7,4 +7,4 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import type { Connect, ViteDevServer } from 'vite';
|
|
9
9
|
import { AngularMemoryOutputFiles } from '../utils';
|
|
10
|
-
export declare function createAngularAssetsMiddleware(server: ViteDevServer, assets: Map<string, string>, outputFiles: AngularMemoryOutputFiles): Connect.NextHandleFunction;
|
|
10
|
+
export declare function createAngularAssetsMiddleware(server: ViteDevServer, assets: Map<string, string>, outputFiles: AngularMemoryOutputFiles, usedComponentStyles: Map<string, Set<string>>): Connect.NextHandleFunction;
|
|
@@ -10,9 +10,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
10
10
|
exports.createAngularAssetsMiddleware = createAngularAssetsMiddleware;
|
|
11
11
|
const mrmime_1 = require("mrmime");
|
|
12
12
|
const node_path_1 = require("node:path");
|
|
13
|
+
const load_esm_1 = require("../../../utils/load-esm");
|
|
13
14
|
const utils_1 = require("../utils");
|
|
14
|
-
function createAngularAssetsMiddleware(server, assets, outputFiles) {
|
|
15
|
-
return function (req, res, next) {
|
|
15
|
+
function createAngularAssetsMiddleware(server, assets, outputFiles, usedComponentStyles) {
|
|
16
|
+
return function angularAssetsMiddleware(req, res, next) {
|
|
16
17
|
if (req.url === undefined || res.writableEnded) {
|
|
17
18
|
return;
|
|
18
19
|
}
|
|
@@ -47,19 +48,57 @@ function createAngularAssetsMiddleware(server, assets, outputFiles) {
|
|
|
47
48
|
next();
|
|
48
49
|
return;
|
|
49
50
|
}
|
|
51
|
+
// Support HTTP HEAD requests for the virtual output files from the Angular build
|
|
52
|
+
if (req.method === 'HEAD' && outputFiles.get(pathname)?.servable) {
|
|
53
|
+
// While a GET will also generate content, the rest of the response is equivalent
|
|
54
|
+
req.method = 'GET';
|
|
55
|
+
}
|
|
50
56
|
// Resource files are handled directly.
|
|
51
57
|
// Global stylesheets (CSS files) are currently considered resources to workaround
|
|
52
58
|
// dev server sourcemap issues with stylesheets.
|
|
53
59
|
if (extension !== '.js' && extension !== '.html') {
|
|
54
60
|
const outputFile = outputFiles.get(pathname);
|
|
55
61
|
if (outputFile?.servable) {
|
|
62
|
+
const data = outputFile.contents;
|
|
63
|
+
if (extension === '.css') {
|
|
64
|
+
// Inject component ID for view encapsulation if requested
|
|
65
|
+
const componentId = new URL(req.url, 'http://localhost').searchParams.get('ngcomp');
|
|
66
|
+
if (componentId !== null) {
|
|
67
|
+
// Record the component style usage for HMR updates
|
|
68
|
+
const usedIds = usedComponentStyles.get(pathname);
|
|
69
|
+
if (usedIds === undefined) {
|
|
70
|
+
usedComponentStyles.set(pathname, new Set([componentId]));
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
usedIds.add(componentId);
|
|
74
|
+
}
|
|
75
|
+
// Shim the stylesheet if a component ID is provided
|
|
76
|
+
if (componentId.length > 0) {
|
|
77
|
+
// Validate component ID
|
|
78
|
+
if (/^[_.\-\p{Letter}\d]+-c\d{9}$/u.test(componentId)) {
|
|
79
|
+
(0, load_esm_1.loadEsmModule)('@angular/compiler')
|
|
80
|
+
.then((compilerModule) => {
|
|
81
|
+
const encapsulatedData = compilerModule.encapsulateStyle(new TextDecoder().decode(data), componentId);
|
|
82
|
+
res.setHeader('Content-Type', 'text/css');
|
|
83
|
+
res.setHeader('Cache-Control', 'no-cache');
|
|
84
|
+
res.end(encapsulatedData);
|
|
85
|
+
})
|
|
86
|
+
.catch((e) => next(e));
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
// eslint-disable-next-line no-console
|
|
91
|
+
console.error('Invalid component stylesheet ID request: ' + componentId);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
56
96
|
const mimeType = (0, mrmime_1.lookup)(extension);
|
|
57
97
|
if (mimeType) {
|
|
58
98
|
res.setHeader('Content-Type', mimeType);
|
|
59
99
|
}
|
|
60
100
|
res.setHeader('Cache-Control', 'no-cache');
|
|
61
|
-
|
|
62
|
-
res.end(outputFile.contents);
|
|
101
|
+
res.end(data);
|
|
63
102
|
return;
|
|
64
103
|
}
|
|
65
104
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright Google LLC All Rights Reserved.
|
|
4
|
+
*
|
|
5
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
6
|
+
* found in the LICENSE file at https://angular.dev/license
|
|
7
|
+
*/
|
|
8
|
+
import type { Connect } from 'vite';
|
|
9
|
+
export declare function createAngularComponentMiddleware(templateUpdates: ReadonlyMap<string, string>): Connect.NextHandleFunction;
|