@angular/build 18.1.0-rc.0 → 18.1.0
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 +11 -9
- package/src/builders/application/chunk-optimizer.d.ts +9 -0
- package/src/builders/application/chunk-optimizer.js +169 -0
- package/src/builders/application/execute-build.js +9 -3
- package/src/builders/application/execute-post-bundle.js +4 -4
- package/src/builders/dev-server/vite-server.js +0 -1
- package/src/tools/angular/compilation/aot-compilation.js +3 -1
- package/src/tools/angular/compilation/parallel-worker.d.ts +1 -0
- package/src/tools/angular/compilation/parallel-worker.js +2 -1
- package/src/tools/esbuild/angular/compiler-plugin.js +3 -1
- package/src/tools/esbuild/application-code-bundle.js +7 -2
- package/src/tools/esbuild/budget-stats.d.ts +2 -2
- package/src/tools/esbuild/budget-stats.js +19 -14
- package/src/tools/esbuild/bundler-context.d.ts +1 -0
- package/src/tools/esbuild/bundler-execution-result.d.ts +1 -1
- package/src/tools/esbuild/bundler-execution-result.js +1 -1
- package/src/tools/esbuild/i18n-inliner.js +2 -2
- package/src/tools/esbuild/javascript-transformer-worker.js +3 -1
- package/src/tools/esbuild/utils.d.ts +4 -3
- package/src/tools/esbuild/utils.js +97 -56
- package/src/tools/esbuild/wasm-plugin.d.ts +28 -0
- package/src/tools/esbuild/wasm-plugin.js +210 -0
- package/src/tools/esbuild/wasm.d.ts +25 -0
- package/src/tools/vite/angular-memory-plugin.d.ts +2 -5
- package/src/tools/vite/angular-memory-plugin.js +7 -161
- package/src/tools/vite/middlewares/assets-middleware.d.ts +10 -0
- package/src/tools/vite/middlewares/assets-middleware.js +94 -0
- package/src/tools/vite/middlewares/html-fallback-middleware.d.ts +10 -0
- package/src/tools/vite/middlewares/html-fallback-middleware.js +24 -0
- package/src/tools/vite/middlewares/index-html-middleware.d.ts +10 -0
- package/src/tools/vite/middlewares/index-html-middleware.js +43 -0
- package/src/tools/vite/middlewares/index.d.ts +11 -0
- package/src/tools/vite/middlewares/index.js +18 -0
- package/src/tools/vite/middlewares/ssr-middleware.d.ts +12 -0
- package/src/tools/vite/middlewares/ssr-middleware.js +57 -0
- package/src/tools/vite/utils.d.ts +16 -0
- package/src/tools/vite/utils.js +40 -0
- package/src/utils/environment-options.d.ts +1 -0
- package/src/utils/environment-options.js +4 -2
- package/src/utils/normalize-cache.js +1 -1
|
@@ -12,14 +12,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
12
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
13
|
exports.createAngularMemoryPlugin = createAngularMemoryPlugin;
|
|
14
14
|
const remapping_1 = __importDefault(require("@ampproject/remapping"));
|
|
15
|
-
const mrmime_1 = require("mrmime");
|
|
16
15
|
const node_assert_1 = __importDefault(require("node:assert"));
|
|
17
16
|
const promises_1 = require("node:fs/promises");
|
|
18
17
|
const node_path_1 = require("node:path");
|
|
19
|
-
const
|
|
20
|
-
// eslint-disable-next-line max-lines-per-function
|
|
18
|
+
const middlewares_1 = require("./middlewares");
|
|
21
19
|
function createAngularMemoryPlugin(options) {
|
|
22
|
-
const { workspaceRoot, virtualProjectRoot, outputFiles, assets, external, ssr, extensionMiddleware,
|
|
20
|
+
const { workspaceRoot, virtualProjectRoot, outputFiles, assets, external, ssr, extensionMiddleware, indexHtmlTransformer, normalizePath, } = options;
|
|
23
21
|
return {
|
|
24
22
|
name: 'vite:angular-memory',
|
|
25
23
|
// Ensures plugin hooks run before built-in Vite hooks
|
|
@@ -31,7 +29,7 @@ function createAngularMemoryPlugin(options) {
|
|
|
31
29
|
// `/@id/${source}` but is currently closer to a raw external than a resolved file path.
|
|
32
30
|
return source;
|
|
33
31
|
}
|
|
34
|
-
if (importer && source[0] === '.' && importer.startsWith(virtualProjectRoot)) {
|
|
32
|
+
if (importer && source[0] === '.' && normalizePath(importer).startsWith(virtualProjectRoot)) {
|
|
35
33
|
// Remove query if present
|
|
36
34
|
const [importerFile] = importer.split('?', 1);
|
|
37
35
|
source =
|
|
@@ -77,143 +75,19 @@ function createAngularMemoryPlugin(options) {
|
|
|
77
75
|
};
|
|
78
76
|
};
|
|
79
77
|
// Assets and resources get handled first
|
|
80
|
-
server.middlewares.use(
|
|
81
|
-
if (req.url === undefined || res.writableEnded) {
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
// Parse the incoming request.
|
|
85
|
-
// The base of the URL is unused but required to parse the URL.
|
|
86
|
-
const pathname = pathnameWithoutBasePath(req.url, server.config.base);
|
|
87
|
-
const extension = (0, node_path_1.extname)(pathname);
|
|
88
|
-
// Rewrite all build assets to a vite raw fs URL
|
|
89
|
-
const assetSourcePath = assets.get(pathname);
|
|
90
|
-
if (assetSourcePath !== undefined) {
|
|
91
|
-
// Workaround to disable Vite transformer middleware.
|
|
92
|
-
// See: https://github.com/vitejs/vite/blob/746a1daab0395f98f0afbdee8f364cb6cf2f3b3f/packages/vite/src/node/server/middlewares/transform.ts#L201 and
|
|
93
|
-
// https://github.com/vitejs/vite/blob/746a1daab0395f98f0afbdee8f364cb6cf2f3b3f/packages/vite/src/node/server/transformRequest.ts#L204-L206
|
|
94
|
-
req.headers.accept = 'text/html';
|
|
95
|
-
// The encoding needs to match what happens in the vite static middleware.
|
|
96
|
-
// ref: https://github.com/vitejs/vite/blob/d4f13bd81468961c8c926438e815ab6b1c82735e/packages/vite/src/node/server/middlewares/static.ts#L163
|
|
97
|
-
req.url = `${server.config.base}@fs/${encodeURI(assetSourcePath)}`;
|
|
98
|
-
next();
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
// HTML fallbacking
|
|
102
|
-
// This matches what happens in the vite html fallback middleware.
|
|
103
|
-
// ref: https://github.com/vitejs/vite/blob/main/packages/vite/src/node/server/middlewares/htmlFallback.ts#L9
|
|
104
|
-
const htmlAssetSourcePath = pathname[pathname.length - 1] === '/'
|
|
105
|
-
? // Trailing slash check for `index.html`.
|
|
106
|
-
assets.get(pathname + 'index.html')
|
|
107
|
-
: // Non-trailing slash check for fallback `.html`
|
|
108
|
-
assets.get(pathname + '.html');
|
|
109
|
-
if (htmlAssetSourcePath) {
|
|
110
|
-
req.url = `${server.config.base}@fs/${encodeURI(htmlAssetSourcePath)}`;
|
|
111
|
-
next();
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
// Resource files are handled directly.
|
|
115
|
-
// Global stylesheets (CSS files) are currently considered resources to workaround
|
|
116
|
-
// dev server sourcemap issues with stylesheets.
|
|
117
|
-
if (extension !== '.js' && extension !== '.html') {
|
|
118
|
-
const outputFile = outputFiles.get(pathname);
|
|
119
|
-
if (outputFile?.servable) {
|
|
120
|
-
const mimeType = (0, mrmime_1.lookup)(extension);
|
|
121
|
-
if (mimeType) {
|
|
122
|
-
res.setHeader('Content-Type', mimeType);
|
|
123
|
-
}
|
|
124
|
-
res.setHeader('Cache-Control', 'no-cache');
|
|
125
|
-
if (extraHeaders) {
|
|
126
|
-
Object.entries(extraHeaders).forEach(([name, value]) => res.setHeader(name, value));
|
|
127
|
-
}
|
|
128
|
-
res.end(outputFile.contents);
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
next();
|
|
133
|
-
});
|
|
78
|
+
server.middlewares.use((0, middlewares_1.createAngularAssetsMiddleware)(server, assets, outputFiles));
|
|
134
79
|
if (extensionMiddleware?.length) {
|
|
135
80
|
extensionMiddleware.forEach((middleware) => server.middlewares.use(middleware));
|
|
136
81
|
}
|
|
137
82
|
// Returning a function, installs middleware after the main transform middleware but
|
|
138
83
|
// before the built-in HTML middleware
|
|
139
84
|
return () => {
|
|
140
|
-
server.middlewares.use(angularHtmlFallbackMiddleware);
|
|
141
|
-
function angularSSRMiddleware(req, res, next) {
|
|
142
|
-
const url = req.originalUrl;
|
|
143
|
-
if (!req.url ||
|
|
144
|
-
// Skip if path is not defined.
|
|
145
|
-
!url ||
|
|
146
|
-
// Skip if path is like a file.
|
|
147
|
-
// NOTE: We use a mime type lookup to mitigate against matching requests like: /browse/pl.0ef59752c0cd457dbf1391f08cbd936f
|
|
148
|
-
lookupMimeTypeFromRequest(url)) {
|
|
149
|
-
next();
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
const rawHtml = outputFiles.get('/index.server.html')?.contents;
|
|
153
|
-
if (!rawHtml) {
|
|
154
|
-
next();
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
transformIndexHtmlAndAddHeaders(req.url, rawHtml, res, next, async (html) => {
|
|
158
|
-
const resolvedUrls = server.resolvedUrls;
|
|
159
|
-
const baseUrl = resolvedUrls?.local[0] ?? resolvedUrls?.network[0];
|
|
160
|
-
const { content } = await (0, render_page_1.renderPage)({
|
|
161
|
-
document: html,
|
|
162
|
-
route: new URL(req.originalUrl ?? '/', baseUrl).toString(),
|
|
163
|
-
serverContext: 'ssr',
|
|
164
|
-
loadBundle: (uri) =>
|
|
165
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
166
|
-
server.ssrLoadModule(uri.slice(1)),
|
|
167
|
-
// Files here are only needed for critical CSS inlining.
|
|
168
|
-
outputFiles: {},
|
|
169
|
-
// TODO: add support for critical css inlining.
|
|
170
|
-
inlineCriticalCss: false,
|
|
171
|
-
});
|
|
172
|
-
return indexHtmlTransformer && content ? await indexHtmlTransformer(content) : content;
|
|
173
|
-
});
|
|
174
|
-
}
|
|
85
|
+
server.middlewares.use(middlewares_1.angularHtmlFallbackMiddleware);
|
|
175
86
|
if (ssr) {
|
|
176
|
-
server.middlewares.use(
|
|
87
|
+
server.middlewares.use((0, middlewares_1.createAngularSSRMiddleware)(server, outputFiles, indexHtmlTransformer));
|
|
177
88
|
}
|
|
178
|
-
server.middlewares.use(
|
|
179
|
-
if (!req.url) {
|
|
180
|
-
next();
|
|
181
|
-
return;
|
|
182
|
-
}
|
|
183
|
-
// Parse the incoming request.
|
|
184
|
-
// The base of the URL is unused but required to parse the URL.
|
|
185
|
-
const pathname = pathnameWithoutBasePath(req.url, server.config.base);
|
|
186
|
-
if (pathname === '/' || pathname === `/index.html`) {
|
|
187
|
-
const rawHtml = outputFiles.get('/index.html')?.contents;
|
|
188
|
-
if (rawHtml) {
|
|
189
|
-
transformIndexHtmlAndAddHeaders(req.url, rawHtml, res, next, indexHtmlTransformer);
|
|
190
|
-
return;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
next();
|
|
194
|
-
});
|
|
89
|
+
server.middlewares.use((0, middlewares_1.createAngularIndexHtmlMiddleware)(server, outputFiles, indexHtmlTransformer));
|
|
195
90
|
};
|
|
196
|
-
function transformIndexHtmlAndAddHeaders(url, rawHtml, res, next, additionalTransformer) {
|
|
197
|
-
server
|
|
198
|
-
.transformIndexHtml(url, Buffer.from(rawHtml).toString('utf-8'))
|
|
199
|
-
.then(async (processedHtml) => {
|
|
200
|
-
if (additionalTransformer) {
|
|
201
|
-
const content = await additionalTransformer(processedHtml);
|
|
202
|
-
if (!content) {
|
|
203
|
-
next();
|
|
204
|
-
return;
|
|
205
|
-
}
|
|
206
|
-
processedHtml = content;
|
|
207
|
-
}
|
|
208
|
-
res.setHeader('Content-Type', 'text/html');
|
|
209
|
-
res.setHeader('Cache-Control', 'no-cache');
|
|
210
|
-
if (extraHeaders) {
|
|
211
|
-
Object.entries(extraHeaders).forEach(([name, value]) => res.setHeader(name, value));
|
|
212
|
-
}
|
|
213
|
-
res.end(processedHtml);
|
|
214
|
-
})
|
|
215
|
-
.catch((error) => next(error));
|
|
216
|
-
}
|
|
217
91
|
},
|
|
218
92
|
};
|
|
219
93
|
}
|
|
@@ -237,31 +111,3 @@ async function loadViteClientCode(file) {
|
|
|
237
111
|
(0, node_assert_1.default)(originalContents !== updatedContents, 'Failed to update Vite client error overlay text.');
|
|
238
112
|
return updatedContents;
|
|
239
113
|
}
|
|
240
|
-
function pathnameWithoutBasePath(url, basePath) {
|
|
241
|
-
const parsedUrl = new URL(url, 'http://localhost');
|
|
242
|
-
const pathname = decodeURIComponent(parsedUrl.pathname);
|
|
243
|
-
// slice(basePath.length - 1) to retain the trailing slash
|
|
244
|
-
return basePath !== '/' && pathname.startsWith(basePath)
|
|
245
|
-
? pathname.slice(basePath.length - 1)
|
|
246
|
-
: pathname;
|
|
247
|
-
}
|
|
248
|
-
function angularHtmlFallbackMiddleware(req, res, next) {
|
|
249
|
-
// Similar to how it is handled in vite
|
|
250
|
-
// https://github.com/vitejs/vite/blob/main/packages/vite/src/node/server/middlewares/htmlFallback.ts#L15C19-L15C45
|
|
251
|
-
if ((req.method === 'GET' || req.method === 'HEAD') &&
|
|
252
|
-
(!req.url || !lookupMimeTypeFromRequest(req.url)) &&
|
|
253
|
-
(!req.headers.accept ||
|
|
254
|
-
req.headers.accept.includes('text/html') ||
|
|
255
|
-
req.headers.accept.includes('text/*') ||
|
|
256
|
-
req.headers.accept.includes('*/*'))) {
|
|
257
|
-
req.url = '/index.html';
|
|
258
|
-
}
|
|
259
|
-
next();
|
|
260
|
-
}
|
|
261
|
-
function lookupMimeTypeFromRequest(url) {
|
|
262
|
-
const extension = (0, node_path_1.extname)(url.split('?')[0]);
|
|
263
|
-
if (extension === '.ico') {
|
|
264
|
-
return 'image/x-icon';
|
|
265
|
-
}
|
|
266
|
-
return extension && (0, mrmime_1.lookup)(extension);
|
|
267
|
-
}
|
|
@@ -0,0 +1,10 @@
|
|
|
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, ViteDevServer } from 'vite';
|
|
9
|
+
import { AngularMemoryOutputFiles } from '../utils';
|
|
10
|
+
export declare function createAngularAssetsMiddleware(server: ViteDevServer, assets: Map<string, string>, outputFiles: AngularMemoryOutputFiles): Connect.NextHandleFunction;
|
|
@@ -0,0 +1,94 @@
|
|
|
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.createAngularAssetsMiddleware = createAngularAssetsMiddleware;
|
|
11
|
+
const mrmime_1 = require("mrmime");
|
|
12
|
+
const node_path_1 = require("node:path");
|
|
13
|
+
const utils_1 = require("../utils");
|
|
14
|
+
function createAngularAssetsMiddleware(server, assets, outputFiles) {
|
|
15
|
+
return function (req, res, next) {
|
|
16
|
+
if (req.url === undefined || res.writableEnded) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
// Parse the incoming request.
|
|
20
|
+
// The base of the URL is unused but required to parse the URL.
|
|
21
|
+
const pathname = (0, utils_1.pathnameWithoutBasePath)(req.url, server.config.base);
|
|
22
|
+
const extension = (0, node_path_1.extname)(pathname);
|
|
23
|
+
const pathnameHasTrailingSlash = pathname[pathname.length - 1] === '/';
|
|
24
|
+
// Rewrite all build assets to a vite raw fs URL
|
|
25
|
+
const assetSourcePath = assets.get(pathname);
|
|
26
|
+
if (assetSourcePath !== undefined) {
|
|
27
|
+
// Workaround to disable Vite transformer middleware.
|
|
28
|
+
// See: https://github.com/vitejs/vite/blob/746a1daab0395f98f0afbdee8f364cb6cf2f3b3f/packages/vite/src/node/server/middlewares/transform.ts#L201 and
|
|
29
|
+
// https://github.com/vitejs/vite/blob/746a1daab0395f98f0afbdee8f364cb6cf2f3b3f/packages/vite/src/node/server/transformRequest.ts#L204-L206
|
|
30
|
+
req.headers.accept = 'text/html';
|
|
31
|
+
// The encoding needs to match what happens in the vite static middleware.
|
|
32
|
+
// ref: https://github.com/vitejs/vite/blob/d4f13bd81468961c8c926438e815ab6b1c82735e/packages/vite/src/node/server/middlewares/static.ts#L163
|
|
33
|
+
req.url = `${server.config.base}@fs/${encodeURI(assetSourcePath)}`;
|
|
34
|
+
next();
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
// HTML fallbacking
|
|
38
|
+
// This matches what happens in the vite html fallback middleware.
|
|
39
|
+
// ref: https://github.com/vitejs/vite/blob/main/packages/vite/src/node/server/middlewares/htmlFallback.ts#L9
|
|
40
|
+
const htmlAssetSourcePath = pathnameHasTrailingSlash
|
|
41
|
+
? // Trailing slash check for `index.html`.
|
|
42
|
+
assets.get(pathname + 'index.html')
|
|
43
|
+
: // Non-trailing slash check for fallback `.html`
|
|
44
|
+
assets.get(pathname + '.html');
|
|
45
|
+
if (htmlAssetSourcePath) {
|
|
46
|
+
req.url = `${server.config.base}@fs/${encodeURI(htmlAssetSourcePath)}`;
|
|
47
|
+
next();
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
// Resource files are handled directly.
|
|
51
|
+
// Global stylesheets (CSS files) are currently considered resources to workaround
|
|
52
|
+
// dev server sourcemap issues with stylesheets.
|
|
53
|
+
if (extension !== '.js' && extension !== '.html') {
|
|
54
|
+
const outputFile = outputFiles.get(pathname);
|
|
55
|
+
if (outputFile?.servable) {
|
|
56
|
+
const mimeType = (0, mrmime_1.lookup)(extension);
|
|
57
|
+
if (mimeType) {
|
|
58
|
+
res.setHeader('Content-Type', mimeType);
|
|
59
|
+
}
|
|
60
|
+
res.setHeader('Cache-Control', 'no-cache');
|
|
61
|
+
(0, utils_1.appendServerConfiguredHeaders)(server, res);
|
|
62
|
+
res.end(outputFile.contents);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// If the path has no trailing slash and it matches a servable directory redirect to the same path with slash.
|
|
67
|
+
// This matches the default express static behaviour.
|
|
68
|
+
// See: https://github.com/expressjs/serve-static/blob/89fc94567fae632718a2157206c52654680e9d01/index.js#L182
|
|
69
|
+
if (!pathnameHasTrailingSlash) {
|
|
70
|
+
for (const assetPath of assets.keys()) {
|
|
71
|
+
if (pathname === assetPath.substring(0, assetPath.lastIndexOf('/'))) {
|
|
72
|
+
const location = req.url + '/';
|
|
73
|
+
res.statusCode = 301;
|
|
74
|
+
res.setHeader('Content-Type', 'text/html');
|
|
75
|
+
res.setHeader('Location', location);
|
|
76
|
+
res.end(`
|
|
77
|
+
<!DOCTYPE html>
|
|
78
|
+
<html lang="en">
|
|
79
|
+
<head>
|
|
80
|
+
<meta charset="utf-8">
|
|
81
|
+
<title>Redirecting</title>
|
|
82
|
+
</head>
|
|
83
|
+
<body>
|
|
84
|
+
<pre>Redirecting to <a href="${location}">${location}</a></pre>
|
|
85
|
+
</body>
|
|
86
|
+
</html>
|
|
87
|
+
`);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
next();
|
|
93
|
+
};
|
|
94
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
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 { ServerResponse } from 'node:http';
|
|
9
|
+
import type { Connect } from 'vite';
|
|
10
|
+
export declare function angularHtmlFallbackMiddleware(req: Connect.IncomingMessage, res: ServerResponse, next: Connect.NextFunction): void;
|
|
@@ -0,0 +1,24 @@
|
|
|
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.angularHtmlFallbackMiddleware = angularHtmlFallbackMiddleware;
|
|
11
|
+
const utils_1 = require("../utils");
|
|
12
|
+
function angularHtmlFallbackMiddleware(req, res, next) {
|
|
13
|
+
// Similar to how it is handled in vite
|
|
14
|
+
// https://github.com/vitejs/vite/blob/main/packages/vite/src/node/server/middlewares/htmlFallback.ts#L15C19-L15C45
|
|
15
|
+
if ((req.method === 'GET' || req.method === 'HEAD') &&
|
|
16
|
+
(!req.url || !(0, utils_1.lookupMimeTypeFromRequest)(req.url)) &&
|
|
17
|
+
(!req.headers.accept ||
|
|
18
|
+
req.headers.accept.includes('text/html') ||
|
|
19
|
+
req.headers.accept.includes('text/*') ||
|
|
20
|
+
req.headers.accept.includes('*/*'))) {
|
|
21
|
+
req.url = '/index.html';
|
|
22
|
+
}
|
|
23
|
+
next();
|
|
24
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
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, ViteDevServer } from 'vite';
|
|
9
|
+
import { AngularMemoryOutputFiles } from '../utils';
|
|
10
|
+
export declare function createAngularIndexHtmlMiddleware(server: ViteDevServer, outputFiles: AngularMemoryOutputFiles, indexHtmlTransformer: ((content: string) => Promise<string>) | undefined): Connect.NextHandleFunction;
|
|
@@ -0,0 +1,43 @@
|
|
|
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.createAngularIndexHtmlMiddleware = createAngularIndexHtmlMiddleware;
|
|
11
|
+
const utils_1 = require("../utils");
|
|
12
|
+
function createAngularIndexHtmlMiddleware(server, outputFiles, indexHtmlTransformer) {
|
|
13
|
+
return function (req, res, next) {
|
|
14
|
+
if (!req.url) {
|
|
15
|
+
next();
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
// Parse the incoming request.
|
|
19
|
+
// The base of the URL is unused but required to parse the URL.
|
|
20
|
+
const pathname = (0, utils_1.pathnameWithoutBasePath)(req.url, server.config.base);
|
|
21
|
+
if (pathname !== '/' && pathname !== '/index.html') {
|
|
22
|
+
next();
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const rawHtml = outputFiles.get('/index.html')?.contents;
|
|
26
|
+
if (!rawHtml) {
|
|
27
|
+
next();
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
server
|
|
31
|
+
.transformIndexHtml(req.url, Buffer.from(rawHtml).toString('utf-8'))
|
|
32
|
+
.then(async (processedHtml) => {
|
|
33
|
+
if (indexHtmlTransformer) {
|
|
34
|
+
processedHtml = await indexHtmlTransformer(processedHtml);
|
|
35
|
+
}
|
|
36
|
+
res.setHeader('Content-Type', 'text/html');
|
|
37
|
+
res.setHeader('Cache-Control', 'no-cache');
|
|
38
|
+
(0, utils_1.appendServerConfiguredHeaders)(server, res);
|
|
39
|
+
res.end(processedHtml);
|
|
40
|
+
})
|
|
41
|
+
.catch((error) => next(error));
|
|
42
|
+
};
|
|
43
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
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
|
+
export { createAngularAssetsMiddleware } from './assets-middleware';
|
|
9
|
+
export { angularHtmlFallbackMiddleware } from './html-fallback-middleware';
|
|
10
|
+
export { createAngularIndexHtmlMiddleware } from './index-html-middleware';
|
|
11
|
+
export { createAngularSSRMiddleware } from './ssr-middleware';
|
|
@@ -0,0 +1,18 @@
|
|
|
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.createAngularSSRMiddleware = exports.createAngularIndexHtmlMiddleware = exports.angularHtmlFallbackMiddleware = exports.createAngularAssetsMiddleware = void 0;
|
|
11
|
+
var assets_middleware_1 = require("./assets-middleware");
|
|
12
|
+
Object.defineProperty(exports, "createAngularAssetsMiddleware", { enumerable: true, get: function () { return assets_middleware_1.createAngularAssetsMiddleware; } });
|
|
13
|
+
var html_fallback_middleware_1 = require("./html-fallback-middleware");
|
|
14
|
+
Object.defineProperty(exports, "angularHtmlFallbackMiddleware", { enumerable: true, get: function () { return html_fallback_middleware_1.angularHtmlFallbackMiddleware; } });
|
|
15
|
+
var index_html_middleware_1 = require("./index-html-middleware");
|
|
16
|
+
Object.defineProperty(exports, "createAngularIndexHtmlMiddleware", { enumerable: true, get: function () { return index_html_middleware_1.createAngularIndexHtmlMiddleware; } });
|
|
17
|
+
var ssr_middleware_1 = require("./ssr-middleware");
|
|
18
|
+
Object.defineProperty(exports, "createAngularSSRMiddleware", { enumerable: true, get: function () { return ssr_middleware_1.createAngularSSRMiddleware; } });
|
|
@@ -0,0 +1,12 @@
|
|
|
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, ViteDevServer } from 'vite';
|
|
9
|
+
export declare function createAngularSSRMiddleware(server: ViteDevServer, outputFiles: Map<string, {
|
|
10
|
+
contents: Uint8Array;
|
|
11
|
+
servable: boolean;
|
|
12
|
+
}>, indexHtmlTransformer?: (content: string) => Promise<string>): Connect.NextHandleFunction;
|
|
@@ -0,0 +1,57 @@
|
|
|
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.createAngularSSRMiddleware = createAngularSSRMiddleware;
|
|
11
|
+
const render_page_1 = require("../../../utils/server-rendering/render-page");
|
|
12
|
+
const utils_1 = require("../utils");
|
|
13
|
+
function createAngularSSRMiddleware(server, outputFiles, indexHtmlTransformer) {
|
|
14
|
+
return function (req, res, next) {
|
|
15
|
+
const url = req.originalUrl;
|
|
16
|
+
if (!req.url ||
|
|
17
|
+
// Skip if path is not defined.
|
|
18
|
+
!url ||
|
|
19
|
+
// Skip if path is like a file.
|
|
20
|
+
// NOTE: We use a mime type lookup to mitigate against matching requests like: /browse/pl.0ef59752c0cd457dbf1391f08cbd936f
|
|
21
|
+
(0, utils_1.lookupMimeTypeFromRequest)(url)) {
|
|
22
|
+
next();
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const rawHtml = outputFiles.get('/index.server.html')?.contents;
|
|
26
|
+
if (!rawHtml) {
|
|
27
|
+
next();
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
server
|
|
31
|
+
.transformIndexHtml(req.url, Buffer.from(rawHtml).toString('utf-8'))
|
|
32
|
+
.then(async (processedHtml) => {
|
|
33
|
+
const resolvedUrls = server.resolvedUrls;
|
|
34
|
+
const baseUrl = resolvedUrls?.local[0] ?? resolvedUrls?.network[0];
|
|
35
|
+
if (indexHtmlTransformer) {
|
|
36
|
+
processedHtml = await indexHtmlTransformer(processedHtml);
|
|
37
|
+
}
|
|
38
|
+
const { content: ssrContent } = await (0, render_page_1.renderPage)({
|
|
39
|
+
document: processedHtml,
|
|
40
|
+
route: new URL(req.originalUrl ?? '/', baseUrl).toString(),
|
|
41
|
+
serverContext: 'ssr',
|
|
42
|
+
loadBundle: (uri) =>
|
|
43
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
44
|
+
server.ssrLoadModule(uri.slice(1)),
|
|
45
|
+
// Files here are only needed for critical CSS inlining.
|
|
46
|
+
outputFiles: {},
|
|
47
|
+
// TODO: add support for critical css inlining.
|
|
48
|
+
inlineCriticalCss: false,
|
|
49
|
+
});
|
|
50
|
+
res.setHeader('Content-Type', 'text/html');
|
|
51
|
+
res.setHeader('Cache-Control', 'no-cache');
|
|
52
|
+
(0, utils_1.appendServerConfiguredHeaders)(server, res);
|
|
53
|
+
res.end(ssrContent);
|
|
54
|
+
})
|
|
55
|
+
.catch((error) => next(error));
|
|
56
|
+
};
|
|
57
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
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 { IncomingMessage, ServerResponse } from 'node:http';
|
|
9
|
+
import type { ViteDevServer } from 'vite';
|
|
10
|
+
export type AngularMemoryOutputFiles = Map<string, {
|
|
11
|
+
contents: Uint8Array;
|
|
12
|
+
servable: boolean;
|
|
13
|
+
}>;
|
|
14
|
+
export declare function pathnameWithoutBasePath(url: string, basePath: string): string;
|
|
15
|
+
export declare function lookupMimeTypeFromRequest(url: string): string | undefined;
|
|
16
|
+
export declare function appendServerConfiguredHeaders(server: ViteDevServer, res: ServerResponse<IncomingMessage>): void;
|
|
@@ -0,0 +1,40 @@
|
|
|
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.pathnameWithoutBasePath = pathnameWithoutBasePath;
|
|
11
|
+
exports.lookupMimeTypeFromRequest = lookupMimeTypeFromRequest;
|
|
12
|
+
exports.appendServerConfiguredHeaders = appendServerConfiguredHeaders;
|
|
13
|
+
const mrmime_1 = require("mrmime");
|
|
14
|
+
const node_path_1 = require("node:path");
|
|
15
|
+
function pathnameWithoutBasePath(url, basePath) {
|
|
16
|
+
const parsedUrl = new URL(url, 'http://localhost');
|
|
17
|
+
const pathname = decodeURIComponent(parsedUrl.pathname);
|
|
18
|
+
// slice(basePath.length - 1) to retain the trailing slash
|
|
19
|
+
return basePath !== '/' && pathname.startsWith(basePath)
|
|
20
|
+
? pathname.slice(basePath.length - 1)
|
|
21
|
+
: pathname;
|
|
22
|
+
}
|
|
23
|
+
function lookupMimeTypeFromRequest(url) {
|
|
24
|
+
const extension = (0, node_path_1.extname)(url.split('?')[0]);
|
|
25
|
+
if (extension === '.ico') {
|
|
26
|
+
return 'image/x-icon';
|
|
27
|
+
}
|
|
28
|
+
return extension && (0, mrmime_1.lookup)(extension);
|
|
29
|
+
}
|
|
30
|
+
function appendServerConfiguredHeaders(server, res) {
|
|
31
|
+
const headers = server.config.server.headers;
|
|
32
|
+
if (!headers) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
for (const [name, value] of Object.entries(headers)) {
|
|
36
|
+
if (value !== undefined) {
|
|
37
|
+
res.setHeader(name, value);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -7,7 +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.useJSONBuildLogs = exports.useTypeChecking = exports.shouldWatchRoot = exports.debugPerformance = exports.useParallelTs = exports.maxWorkers = exports.allowMinify = exports.shouldBeautify = exports.allowMangle = void 0;
|
|
10
|
+
exports.shouldOptimizeChunks = exports.useJSONBuildLogs = exports.useTypeChecking = exports.shouldWatchRoot = exports.debugPerformance = exports.useParallelTs = exports.maxWorkers = exports.allowMinify = exports.shouldBeautify = exports.allowMangle = void 0;
|
|
11
11
|
const node_os_1 = require("node:os");
|
|
12
12
|
function isDisabled(variable) {
|
|
13
13
|
return variable === '0' || variable.toLowerCase() === 'false';
|
|
@@ -69,7 +69,7 @@ exports.allowMinify = debugOptimize.minify;
|
|
|
69
69
|
const maxWorkersVariable = process.env['NG_BUILD_MAX_WORKERS'];
|
|
70
70
|
exports.maxWorkers = isPresent(maxWorkersVariable)
|
|
71
71
|
? +maxWorkersVariable
|
|
72
|
-
: Math.min(4, (0, node_os_1.availableParallelism)());
|
|
72
|
+
: Math.min(4, Math.max((0, node_os_1.availableParallelism)() - 1, 1));
|
|
73
73
|
const parallelTsVariable = process.env['NG_BUILD_PARALLEL_TS'];
|
|
74
74
|
exports.useParallelTs = !isPresent(parallelTsVariable) || !isDisabled(parallelTsVariable);
|
|
75
75
|
const debugPerfVariable = process.env['NG_BUILD_DEBUG_PERF'];
|
|
@@ -80,3 +80,5 @@ const typeCheckingVariable = process.env['NG_BUILD_TYPE_CHECK'];
|
|
|
80
80
|
exports.useTypeChecking = !isPresent(typeCheckingVariable) || !isDisabled(typeCheckingVariable);
|
|
81
81
|
const buildLogsJsonVariable = process.env['NG_BUILD_LOGS_JSON'];
|
|
82
82
|
exports.useJSONBuildLogs = isPresent(buildLogsJsonVariable) && isEnabled(buildLogsJsonVariable);
|
|
83
|
+
const optimizeChunksVariable = process.env['NG_BUILD_OPTIMIZE_CHUNKS'];
|
|
84
|
+
exports.shouldOptimizeChunks = isPresent(optimizeChunksVariable) && isEnabled(optimizeChunksVariable);
|
|
@@ -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 = '18.1.0
|
|
13
|
+
const VERSION = '18.1.0';
|
|
14
14
|
function hasCacheMetadata(value) {
|
|
15
15
|
return (!!value &&
|
|
16
16
|
typeof value === 'object' &&
|