@angular/build 19.0.0-next.3 → 19.0.0-next.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 +6 -5
- package/src/builders/dev-server/vite-server.d.ts +5 -1
- package/src/builders/dev-server/vite-server.js +35 -15
- package/src/tools/angular/compilation/parallel-compilation.d.ts +1 -1
- package/src/tools/angular/compilation/parallel-compilation.js +5 -0
- package/src/tools/esbuild/javascript-transformer.js +6 -0
- package/src/tools/sass/sass-service.js +6 -0
- package/src/tools/sass/worker.d.ts +13 -32
- package/src/tools/sass/worker.js +1 -0
- package/src/tools/vite/angular-memory-plugin.d.ts +1 -0
- package/src/tools/vite/angular-memory-plugin.js +2 -2
- package/src/tools/vite/middlewares/assets-middleware.d.ts +1 -1
- package/src/tools/vite/middlewares/assets-middleware.js +41 -2
- package/src/typings.d.ts +7 -0
- package/src/utils/normalize-cache.js +1 -1
- package/src/utils/server-rendering/manifest.js +2 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@angular/build",
|
|
3
|
-
"version": "19.0.0-next.
|
|
3
|
+
"version": "19.0.0-next.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.0-next.
|
|
26
|
+
"@angular-devkit/architect": "0.1900.0-next.5",
|
|
27
27
|
"@babel/core": "7.25.2",
|
|
28
28
|
"@babel/helper-annotate-as-pure": "7.24.7",
|
|
29
29
|
"@babel/helper-split-export-declaration": "7.24.7",
|
|
@@ -42,18 +42,19 @@
|
|
|
42
42
|
"parse5-html-rewriting-stream": "7.0.0",
|
|
43
43
|
"picomatch": "4.0.2",
|
|
44
44
|
"piscina": "4.6.1",
|
|
45
|
-
"rollup": "4.21.
|
|
45
|
+
"rollup": "4.21.3",
|
|
46
46
|
"sass": "1.78.0",
|
|
47
47
|
"semver": "7.6.3",
|
|
48
|
-
"vite": "5.4.
|
|
48
|
+
"vite": "5.4.4",
|
|
49
49
|
"watchpack": "2.4.2"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
|
52
|
+
"@angular/compiler": "^19.0.0-next.0",
|
|
52
53
|
"@angular/compiler-cli": "^19.0.0-next.0",
|
|
53
54
|
"@angular/localize": "^19.0.0-next.0",
|
|
54
55
|
"@angular/platform-server": "^19.0.0-next.0",
|
|
55
56
|
"@angular/service-worker": "^19.0.0-next.0",
|
|
56
|
-
"@angular/ssr": "^19.0.0-next.
|
|
57
|
+
"@angular/ssr": "^19.0.0-next.5",
|
|
57
58
|
"less": "^4.2.0",
|
|
58
59
|
"postcss": "^8.4.0",
|
|
59
60
|
"tailwindcss": "^2.0.0 || ^3.0.0",
|
|
@@ -20,6 +20,10 @@ interface OutputFileRecord {
|
|
|
20
20
|
servable: boolean;
|
|
21
21
|
type: BuildOutputFileType;
|
|
22
22
|
}
|
|
23
|
+
interface DevServerExternalResultMetadata extends Omit<ExternalResultMetadata, 'explicit'> {
|
|
24
|
+
explicitBrowser: string[];
|
|
25
|
+
explicitServer: string[];
|
|
26
|
+
}
|
|
23
27
|
export type BuilderAction = (options: ApplicationBuilderInternalOptions, context: BuilderContext, plugins?: Plugin[]) => AsyncIterable<Result>;
|
|
24
28
|
export declare function serveWithVite(serverOptions: NormalizedDevServerOptions, builderName: string, builderAction: BuilderAction, context: BuilderContext, transformers?: {
|
|
25
29
|
indexHtml?: (content: string) => Promise<string>;
|
|
@@ -27,6 +31,6 @@ export declare function serveWithVite(serverOptions: NormalizedDevServerOptions,
|
|
|
27
31
|
middleware?: Connect.NextHandleFunction[];
|
|
28
32
|
buildPlugins?: Plugin[];
|
|
29
33
|
}): AsyncIterableIterator<DevServerBuilderOutput>;
|
|
30
|
-
export declare function setupServer(serverOptions: NormalizedDevServerOptions, outputFiles: Map<string, OutputFileRecord>, assets: Map<string, string>, preserveSymlinks: boolean | undefined, externalMetadata:
|
|
34
|
+
export declare function setupServer(serverOptions: NormalizedDevServerOptions, outputFiles: Map<string, OutputFileRecord>, assets: Map<string, string>, preserveSymlinks: boolean | undefined, externalMetadata: DevServerExternalResultMetadata, ssr: boolean, prebundleTransformer: JavaScriptTransformer, target: string[], zoneless: boolean, usedComponentStyles: Map<string, string[]>, prebundleLoaderExtensions: EsbuildLoaderOption | undefined, extensionMiddleware?: Connect.NextHandleFunction[], indexHtmlTransformer?: (content: string) => Promise<string>, thirdPartySourcemaps?: boolean): Promise<InlineConfig>;
|
|
31
35
|
type EsbuildLoaderOption = Exclude<DepOptimizationConfig['esbuildOptions'], undefined>['loader'];
|
|
32
36
|
export {};
|
|
@@ -107,8 +107,10 @@ async function* serveWithVite(serverOptions, builderName, builderAction, context
|
|
|
107
107
|
const externalMetadata = {
|
|
108
108
|
implicitBrowser: [],
|
|
109
109
|
implicitServer: [],
|
|
110
|
-
|
|
110
|
+
explicitBrowser: [],
|
|
111
|
+
explicitServer: [],
|
|
111
112
|
};
|
|
113
|
+
const usedComponentStyles = new Map();
|
|
112
114
|
// Add cleanup logic via a builder teardown.
|
|
113
115
|
let deferred;
|
|
114
116
|
context.addTeardown(async () => {
|
|
@@ -187,15 +189,18 @@ async function* serveWithVite(serverOptions, builderName, builderAction, context
|
|
|
187
189
|
requiresServerRestart = implicitServerFiltered.some((dep) => !previousImplicitServer.has(dep));
|
|
188
190
|
}
|
|
189
191
|
// Empty Arrays to avoid growing unlimited with every re-build.
|
|
190
|
-
externalMetadata.
|
|
192
|
+
externalMetadata.explicitBrowser.length = 0;
|
|
193
|
+
externalMetadata.explicitServer.length = 0;
|
|
191
194
|
externalMetadata.implicitServer.length = 0;
|
|
192
195
|
externalMetadata.implicitBrowser.length = 0;
|
|
193
|
-
externalMetadata.
|
|
196
|
+
externalMetadata.explicitBrowser.push(...explicit);
|
|
197
|
+
externalMetadata.explicitServer.push(...explicit, ...nodeJsBuiltinModules);
|
|
194
198
|
externalMetadata.implicitServer.push(...implicitServerFiltered);
|
|
195
199
|
externalMetadata.implicitBrowser.push(...implicitBrowserFiltered);
|
|
196
200
|
// The below needs to be sorted as Vite uses these options are part of the hashing invalidation algorithm.
|
|
197
201
|
// See: https://github.com/vitejs/vite/blob/0873bae0cfe0f0718ad2f5743dd34a17e4ab563d/packages/vite/src/node/optimizer/index.ts#L1203-L1239
|
|
198
|
-
externalMetadata.
|
|
202
|
+
externalMetadata.explicitBrowser.sort();
|
|
203
|
+
externalMetadata.explicitServer.sort();
|
|
199
204
|
externalMetadata.implicitServer.sort();
|
|
200
205
|
externalMetadata.implicitBrowser.sort();
|
|
201
206
|
}
|
|
@@ -210,7 +215,7 @@ async function* serveWithVite(serverOptions, builderName, builderAction, context
|
|
|
210
215
|
await server.restart();
|
|
211
216
|
}
|
|
212
217
|
else {
|
|
213
|
-
await handleUpdate(normalizePath, generatedFiles, server, serverOptions, context.logger);
|
|
218
|
+
await handleUpdate(normalizePath, generatedFiles, server, serverOptions, context.logger, usedComponentStyles);
|
|
214
219
|
}
|
|
215
220
|
}
|
|
216
221
|
else {
|
|
@@ -234,7 +239,7 @@ async function* serveWithVite(serverOptions, builderName, builderAction, context
|
|
|
234
239
|
? browserOptions.polyfills
|
|
235
240
|
: [browserOptions.polyfills];
|
|
236
241
|
// Setup server and start listening
|
|
237
|
-
const serverConfiguration = await setupServer(serverOptions, generatedFiles, assetFiles, browserOptions.preserveSymlinks, externalMetadata, !!browserOptions.ssr, prebundleTransformer, target, (0, internal_1.isZonelessApp)(polyfills), browserOptions.loader, extensions?.middleware, transformers?.indexHtml, thirdPartySourcemaps);
|
|
242
|
+
const serverConfiguration = await setupServer(serverOptions, generatedFiles, assetFiles, browserOptions.preserveSymlinks, externalMetadata, !!browserOptions.ssr, prebundleTransformer, target, (0, internal_1.isZonelessApp)(polyfills), usedComponentStyles, browserOptions.loader, extensions?.middleware, transformers?.indexHtml, thirdPartySourcemaps);
|
|
238
243
|
server = await createServer(serverConfiguration);
|
|
239
244
|
await server.listen();
|
|
240
245
|
if (browserOptions.ssr && serverOptions.prebundle !== false) {
|
|
@@ -273,7 +278,7 @@ async function* serveWithVite(serverOptions, builderName, builderAction, context
|
|
|
273
278
|
}
|
|
274
279
|
await new Promise((resolve) => (deferred = resolve));
|
|
275
280
|
}
|
|
276
|
-
async function handleUpdate(normalizePath, generatedFiles, server, serverOptions, logger) {
|
|
281
|
+
async function handleUpdate(normalizePath, generatedFiles, server, serverOptions, logger, usedComponentStyles) {
|
|
277
282
|
const updatedFiles = [];
|
|
278
283
|
let isServerFileUpdated = false;
|
|
279
284
|
// Invalidate any updated files
|
|
@@ -298,7 +303,21 @@ async function handleUpdate(normalizePath, generatedFiles, server, serverOptions
|
|
|
298
303
|
const timestamp = Date.now();
|
|
299
304
|
server.hot.send({
|
|
300
305
|
type: 'update',
|
|
301
|
-
updates: updatedFiles.
|
|
306
|
+
updates: updatedFiles.flatMap((filePath) => {
|
|
307
|
+
// For component styles, an HMR update must be sent for each one with the corresponding
|
|
308
|
+
// component identifier search parameter (`ngcomp`). The Vite client code will not keep
|
|
309
|
+
// the existing search parameters when it performs an update and each one must be
|
|
310
|
+
// specified explicitly. Typically, there is only one each though as specific style files
|
|
311
|
+
// are not typically reused across components.
|
|
312
|
+
const componentIds = usedComponentStyles.get(filePath);
|
|
313
|
+
if (componentIds) {
|
|
314
|
+
return componentIds.map((id) => ({
|
|
315
|
+
type: 'css-update',
|
|
316
|
+
timestamp,
|
|
317
|
+
path: `${filePath}?ngcomp` + (id ? `=${id}` : ''),
|
|
318
|
+
acceptedPath: filePath,
|
|
319
|
+
}));
|
|
320
|
+
}
|
|
302
321
|
return {
|
|
303
322
|
type: 'css-update',
|
|
304
323
|
timestamp,
|
|
@@ -373,7 +392,7 @@ function analyzeResultFiles(normalizePath, htmlIndexPath, resultFiles, generated
|
|
|
373
392
|
}
|
|
374
393
|
}
|
|
375
394
|
}
|
|
376
|
-
async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks, externalMetadata, ssr, prebundleTransformer, target, zoneless, prebundleLoaderExtensions, extensionMiddleware, indexHtmlTransformer, thirdPartySourcemaps = false) {
|
|
395
|
+
async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks, externalMetadata, ssr, prebundleTransformer, target, zoneless, usedComponentStyles, prebundleLoaderExtensions, extensionMiddleware, indexHtmlTransformer, thirdPartySourcemaps = false) {
|
|
377
396
|
const proxy = await (0, utils_1.loadProxyConfiguration)(serverOptions.workspaceRoot, serverOptions.proxyConfig);
|
|
378
397
|
// dynamically import Vite for ESM compatibility
|
|
379
398
|
const { normalizePath } = await (0, load_esm_1.loadEsmModule)('vite');
|
|
@@ -433,18 +452,18 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
|
|
|
433
452
|
},
|
|
434
453
|
// This is needed when `externalDependencies` is used to prevent Vite load errors.
|
|
435
454
|
// NOTE: If Vite adds direct support for externals, this can be removed.
|
|
436
|
-
preTransformRequests: externalMetadata.
|
|
455
|
+
preTransformRequests: externalMetadata.explicitBrowser.length === 0,
|
|
437
456
|
},
|
|
438
457
|
ssr: {
|
|
439
458
|
// Note: `true` and `/.*/` have different sematics. When true, the `external` option is ignored.
|
|
440
459
|
noExternal: /.*/,
|
|
441
460
|
// Exclude any Node.js built in module and provided dependencies (currently build defined externals)
|
|
442
|
-
external: externalMetadata.
|
|
461
|
+
external: externalMetadata.explicitServer,
|
|
443
462
|
optimizeDeps: getDepOptimizationConfig({
|
|
444
463
|
// Only enable with caching since it causes prebundle dependencies to be cached
|
|
445
464
|
disabled: serverOptions.prebundle === false,
|
|
446
465
|
// Exclude any explicitly defined dependencies (currently build defined externals and node.js built-ins)
|
|
447
|
-
exclude: externalMetadata.
|
|
466
|
+
exclude: externalMetadata.explicitServer,
|
|
448
467
|
// Include all implict dependencies from the external packages internal option
|
|
449
468
|
include: externalMetadata.implicitServer,
|
|
450
469
|
ssr: true,
|
|
@@ -463,19 +482,20 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
|
|
|
463
482
|
outputFiles,
|
|
464
483
|
assets,
|
|
465
484
|
ssr,
|
|
466
|
-
external: externalMetadata.
|
|
485
|
+
external: externalMetadata.explicitBrowser,
|
|
467
486
|
indexHtmlTransformer,
|
|
468
487
|
extensionMiddleware,
|
|
469
488
|
normalizePath,
|
|
489
|
+
usedComponentStyles,
|
|
470
490
|
}),
|
|
471
|
-
(0, id_prefix_plugin_1.createRemoveIdPrefixPlugin)(externalMetadata.
|
|
491
|
+
(0, id_prefix_plugin_1.createRemoveIdPrefixPlugin)(externalMetadata.explicitBrowser),
|
|
472
492
|
],
|
|
473
493
|
// Browser only optimizeDeps. (This does not run for SSR dependencies).
|
|
474
494
|
optimizeDeps: getDepOptimizationConfig({
|
|
475
495
|
// Only enable with caching since it causes prebundle dependencies to be cached
|
|
476
496
|
disabled: serverOptions.prebundle === false,
|
|
477
497
|
// Exclude any explicitly defined dependencies (currently build defined externals)
|
|
478
|
-
exclude: externalMetadata.
|
|
498
|
+
exclude: externalMetadata.explicitBrowser,
|
|
479
499
|
// Include all implict dependencies from the external packages internal option
|
|
480
500
|
include: externalMetadata.implicitBrowser,
|
|
481
501
|
ssr: false,
|
|
@@ -22,7 +22,7 @@ export declare class ParallelCompilation extends AngularCompilation {
|
|
|
22
22
|
#private;
|
|
23
23
|
readonly jit: boolean;
|
|
24
24
|
constructor(jit: boolean);
|
|
25
|
-
initialize(tsconfig: string, hostOptions: AngularHostOptions, compilerOptionsTransformer?: (
|
|
25
|
+
initialize(tsconfig: string, hostOptions: AngularHostOptions, compilerOptionsTransformer?: (compilerOptions: CompilerOptions) => CompilerOptions): Promise<{
|
|
26
26
|
affectedFiles: ReadonlySet<SourceFile>;
|
|
27
27
|
compilerOptions: CompilerOptions;
|
|
28
28
|
referencedFiles: readonly string[];
|
|
@@ -40,6 +40,11 @@ class ParallelCompilation extends angular_compilation_1.AngularCompilation {
|
|
|
40
40
|
useAtomics: !process.versions.webcontainer,
|
|
41
41
|
filename: localRequire.resolve('./parallel-worker'),
|
|
42
42
|
recordTiming: false,
|
|
43
|
+
env: {
|
|
44
|
+
...process.env,
|
|
45
|
+
// Enable compile code caching if enabled for the main process (only exists on Node.js v22.8+)
|
|
46
|
+
'NODE_COMPILE_CACHE': (0, node_module_1.getCompileCacheDir)?.(),
|
|
47
|
+
},
|
|
43
48
|
});
|
|
44
49
|
}
|
|
45
50
|
initialize(tsconfig, hostOptions, compilerOptionsTransformer) {
|
|
@@ -13,6 +13,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
13
13
|
exports.JavaScriptTransformer = void 0;
|
|
14
14
|
const node_crypto_1 = require("node:crypto");
|
|
15
15
|
const promises_1 = require("node:fs/promises");
|
|
16
|
+
const node_module_1 = require("node:module");
|
|
16
17
|
const piscina_1 = __importDefault(require("piscina"));
|
|
17
18
|
/**
|
|
18
19
|
* A class that performs transformation of JavaScript files and raw data.
|
|
@@ -48,6 +49,11 @@ class JavaScriptTransformer {
|
|
|
48
49
|
// Shutdown idle threads after 1 second of inactivity
|
|
49
50
|
idleTimeout: 1000,
|
|
50
51
|
recordTiming: false,
|
|
52
|
+
env: {
|
|
53
|
+
...process.env,
|
|
54
|
+
// Enable compile code caching if enabled for the main process (only exists on Node.js v22.8+)
|
|
55
|
+
'NODE_COMPILE_CACHE': (0, node_module_1.getCompileCacheDir)?.(),
|
|
56
|
+
},
|
|
51
57
|
});
|
|
52
58
|
return this.#workerPool;
|
|
53
59
|
}
|
|
@@ -64,6 +64,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
64
64
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
65
65
|
exports.SassWorkerImplementation = void 0;
|
|
66
66
|
const node_assert_1 = __importDefault(require("node:assert"));
|
|
67
|
+
const node_module_1 = require("node:module");
|
|
67
68
|
const node_url_1 = require("node:url");
|
|
68
69
|
const node_worker_threads_1 = require("node:worker_threads");
|
|
69
70
|
const piscina_1 = require("piscina");
|
|
@@ -100,6 +101,11 @@ class SassWorkerImplementation {
|
|
|
100
101
|
// Shutdown idle threads after 1 second of inactivity
|
|
101
102
|
idleTimeout: 1000,
|
|
102
103
|
recordTiming: false,
|
|
104
|
+
env: {
|
|
105
|
+
...process.env,
|
|
106
|
+
// Enable compile code caching if enabled for the main process (only exists on Node.js v22.8+)
|
|
107
|
+
'NODE_COMPILE_CACHE': (0, node_module_1.getCompileCacheDir)?.(),
|
|
108
|
+
},
|
|
103
109
|
});
|
|
104
110
|
return this.#workerPool;
|
|
105
111
|
}
|
|
@@ -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
|
@@ -95,6 +95,7 @@ async function renderSassStylesheet(request) {
|
|
|
95
95
|
warnings,
|
|
96
96
|
result: {
|
|
97
97
|
...result,
|
|
98
|
+
sourceMap: result.sourceMap,
|
|
98
99
|
// URL is not serializable so to convert to string here and back to URL in the parent.
|
|
99
100
|
loadedUrls: result.loadedUrls.map((p) => (0, node_url_1.fileURLToPath)(p)),
|
|
100
101
|
},
|
|
@@ -17,5 +17,6 @@ export interface AngularMemoryPluginOptions {
|
|
|
17
17
|
extensionMiddleware?: Connect.NextHandleFunction[];
|
|
18
18
|
indexHtmlTransformer?: (content: string) => Promise<string>;
|
|
19
19
|
normalizePath: (path: string) => string;
|
|
20
|
+
usedComponentStyles: Map<string, string[]>;
|
|
20
21
|
}
|
|
21
22
|
export declare function createAngularMemoryPlugin(options: AngularMemoryPluginOptions): Plugin;
|
|
@@ -17,7 +17,7 @@ const promises_1 = require("node:fs/promises");
|
|
|
17
17
|
const node_path_1 = require("node:path");
|
|
18
18
|
const middlewares_1 = require("./middlewares");
|
|
19
19
|
function createAngularMemoryPlugin(options) {
|
|
20
|
-
const { workspaceRoot, virtualProjectRoot, outputFiles, assets, external, ssr, extensionMiddleware, indexHtmlTransformer, normalizePath, } = options;
|
|
20
|
+
const { workspaceRoot, virtualProjectRoot, outputFiles, assets, external, ssr, extensionMiddleware, indexHtmlTransformer, normalizePath, usedComponentStyles, } = options;
|
|
21
21
|
return {
|
|
22
22
|
name: 'vite:angular-memory',
|
|
23
23
|
// Ensures plugin hooks run before built-in Vite hooks
|
|
@@ -75,7 +75,7 @@ function createAngularMemoryPlugin(options) {
|
|
|
75
75
|
};
|
|
76
76
|
};
|
|
77
77
|
// Assets and resources get handled first
|
|
78
|
-
server.middlewares.use((0, middlewares_1.createAngularAssetsMiddleware)(server, assets, outputFiles));
|
|
78
|
+
server.middlewares.use((0, middlewares_1.createAngularAssetsMiddleware)(server, assets, outputFiles, usedComponentStyles));
|
|
79
79
|
if (extensionMiddleware?.length) {
|
|
80
80
|
extensionMiddleware.forEach((middleware) => server.middlewares.use(middleware));
|
|
81
81
|
}
|
|
@@ -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, string[]>): Connect.NextHandleFunction;
|
|
@@ -10,8 +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
|
-
|
|
15
|
+
const COMPONENT_REGEX = /%COMP%/g;
|
|
16
|
+
function createAngularAssetsMiddleware(server, assets, outputFiles, usedComponentStyles) {
|
|
15
17
|
return function (req, res, next) {
|
|
16
18
|
if (req.url === undefined || res.writableEnded) {
|
|
17
19
|
return;
|
|
@@ -53,13 +55,50 @@ function createAngularAssetsMiddleware(server, assets, outputFiles) {
|
|
|
53
55
|
if (extension !== '.js' && extension !== '.html') {
|
|
54
56
|
const outputFile = outputFiles.get(pathname);
|
|
55
57
|
if (outputFile?.servable) {
|
|
58
|
+
const data = outputFile.contents;
|
|
59
|
+
if (extension === '.css') {
|
|
60
|
+
// Inject component ID for view encapsulation if requested
|
|
61
|
+
const componentId = new URL(req.url, 'http://localhost').searchParams.get('ngcomp');
|
|
62
|
+
if (componentId !== null) {
|
|
63
|
+
// Record the component style usage for HMR updates
|
|
64
|
+
const usedIds = usedComponentStyles.get(pathname);
|
|
65
|
+
if (usedIds === undefined) {
|
|
66
|
+
usedComponentStyles.set(pathname, [componentId]);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
usedIds.push(componentId);
|
|
70
|
+
}
|
|
71
|
+
// Shim the stylesheet if a component ID is provided
|
|
72
|
+
if (componentId.length > 0) {
|
|
73
|
+
// Validate component ID
|
|
74
|
+
if (/[_.-A-Za-z0-9]+-c\d{9}$/.test(componentId)) {
|
|
75
|
+
(0, load_esm_1.loadEsmModule)('@angular/compiler')
|
|
76
|
+
.then((compilerModule) => {
|
|
77
|
+
const encapsulatedData = compilerModule
|
|
78
|
+
.encapsulateStyle(new TextDecoder().decode(data))
|
|
79
|
+
.replaceAll(COMPONENT_REGEX, componentId);
|
|
80
|
+
res.setHeader('Content-Type', 'text/css');
|
|
81
|
+
res.setHeader('Cache-Control', 'no-cache');
|
|
82
|
+
(0, utils_1.appendServerConfiguredHeaders)(server, res);
|
|
83
|
+
res.end(encapsulatedData);
|
|
84
|
+
})
|
|
85
|
+
.catch((e) => next(e));
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
// eslint-disable-next-line no-console
|
|
90
|
+
console.error('Invalid component stylesheet ID request: ' + componentId);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
56
95
|
const mimeType = (0, mrmime_1.lookup)(extension);
|
|
57
96
|
if (mimeType) {
|
|
58
97
|
res.setHeader('Content-Type', mimeType);
|
|
59
98
|
}
|
|
60
99
|
res.setHeader('Cache-Control', 'no-cache');
|
|
61
100
|
(0, utils_1.appendServerConfiguredHeaders)(server, res);
|
|
62
|
-
res.end(
|
|
101
|
+
res.end(data);
|
|
63
102
|
return;
|
|
64
103
|
}
|
|
65
104
|
}
|
package/src/typings.d.ts
CHANGED
|
@@ -17,3 +17,10 @@
|
|
|
17
17
|
declare module 'esbuild' {
|
|
18
18
|
export * from 'esbuild-wasm';
|
|
19
19
|
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Augment the Node.js module builtin types to support the v22.8+ compile cache functions
|
|
23
|
+
*/
|
|
24
|
+
declare module 'node:module' {
|
|
25
|
+
function getCompileCacheDir(): string | undefined;
|
|
26
|
+
}
|
|
@@ -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.0-next.
|
|
13
|
+
const VERSION = '19.0.0-next.5';
|
|
14
14
|
function hasCacheMetadata(value) {
|
|
15
15
|
return (!!value &&
|
|
16
16
|
typeof value === 'object' &&
|
|
@@ -70,15 +70,13 @@ function generateAngularServerAppManifest(additionalHtmlOutputFiles, outputFiles
|
|
|
70
70
|
for (const file of [...additionalHtmlOutputFiles.values(), ...outputFiles]) {
|
|
71
71
|
if (file.path === options_1.INDEX_HTML_SERVER ||
|
|
72
72
|
file.path === options_1.INDEX_HTML_CSR ||
|
|
73
|
-
file.path.endsWith('.css')) {
|
|
73
|
+
(inlineCriticalCss && file.path.endsWith('.css'))) {
|
|
74
74
|
serverAssetsContent.push(`['${file.path}', async () => ${JSON.stringify(file.text)}]`);
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
const manifestContent = `
|
|
78
|
-
import bootstrap from './main.server.mjs';
|
|
79
|
-
|
|
80
78
|
export default {
|
|
81
|
-
bootstrap: () =>
|
|
79
|
+
bootstrap: () => import('./main.server.mjs').then(m => m.default),
|
|
82
80
|
inlineCriticalCss: ${inlineCriticalCss},
|
|
83
81
|
routes: ${JSON.stringify(routes, undefined, 2)},
|
|
84
82
|
assets: new Map([${serverAssetsContent.join(', \n')}]),
|