@angular-devkit/build-angular 17.0.0-rc.2 → 17.0.0-rc.4
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 +9 -8
- package/src/builders/app-shell/render-worker.d.ts +1 -1
- package/src/builders/app-shell/render-worker.js +16 -9
- package/src/builders/application/build-action.js +5 -2
- package/src/builders/application/execute-build.js +49 -30
- package/src/builders/dev-server/builder.d.ts +12 -1
- package/src/builders/dev-server/builder.js +13 -4
- package/src/builders/dev-server/vite-server.d.ts +9 -6
- package/src/builders/dev-server/vite-server.js +167 -63
- package/src/builders/extract-i18n/application-extraction.js +1 -0
- package/src/builders/prerender/routes-extractor-worker.js +1 -1
- package/src/builders/ssr-dev-server/index.d.ts +1 -1
- package/src/index.d.ts +1 -0
- package/src/index.js +3 -1
- package/src/tools/babel/plugins/elide-angular-metadata.js +14 -2
- package/src/tools/esbuild/angular/compiler-plugin.js +104 -57
- package/src/tools/esbuild/application-code-bundle.d.ts +3 -2
- package/src/tools/esbuild/application-code-bundle.js +7 -19
- package/src/tools/esbuild/bundler-context.d.ts +4 -1
- package/src/tools/esbuild/bundler-context.js +13 -8
- package/src/tools/esbuild/bundler-execution-result.d.ts +16 -14
- package/src/tools/esbuild/bundler-execution-result.js +18 -3
- package/src/tools/esbuild/commonjs-checker.js +12 -7
- package/src/tools/esbuild/global-scripts.d.ts +1 -1
- package/src/tools/esbuild/global-scripts.js +2 -1
- package/src/tools/esbuild/javascript-transformer.d.ts +2 -1
- package/src/tools/esbuild/javascript-transformer.js +44 -20
- package/src/tools/esbuild/utils.d.ts +1 -1
- package/src/tools/esbuild/utils.js +18 -4
- package/src/utils/bundle-calculator.js +1 -1
- package/src/utils/environment-options.d.ts +1 -0
- package/src/utils/environment-options.js +7 -2
- package/src/utils/load-esm.js +6 -1
- package/src/utils/routes-extractor/extractor.d.ts +1 -1
- package/src/utils/routes-extractor/extractor.js +2 -2
- package/src/utils/server-rendering/esm-in-memory-loader/loader-hooks.d.ts +0 -4
- package/src/utils/server-rendering/esm-in-memory-loader/loader-hooks.js +78 -28
- package/src/utils/server-rendering/fetch-patch.d.ts +8 -0
- package/src/utils/server-rendering/fetch-patch.js +66 -0
- package/src/utils/server-rendering/prerender.js +25 -30
- package/src/utils/server-rendering/render-worker.d.ts +4 -2
- package/src/utils/server-rendering/render-worker.js +10 -4
- package/src/utils/server-rendering/routes-extractor-worker.d.ts +5 -3
- package/src/utils/server-rendering/routes-extractor-worker.js +12 -6
- package/src/utils/server-rendering/prerender-server.d.ts +0 -21
- package/src/utils/server-rendering/prerender-server.js +0 -102
|
@@ -38,9 +38,10 @@ const remapping_1 = __importDefault(require("@ampproject/remapping"));
|
|
|
38
38
|
const mrmime_1 = require("mrmime");
|
|
39
39
|
const node_assert_1 = __importDefault(require("node:assert"));
|
|
40
40
|
const promises_1 = require("node:fs/promises");
|
|
41
|
-
const node_path_1 =
|
|
41
|
+
const node_path_1 = require("node:path");
|
|
42
42
|
const bundler_context_1 = require("../../tools/esbuild/bundler-context");
|
|
43
43
|
const javascript_transformer_1 = require("../../tools/esbuild/javascript-transformer");
|
|
44
|
+
const rxjs_esm_resolution_plugin_1 = require("../../tools/esbuild/rxjs-esm-resolution-plugin");
|
|
44
45
|
const utils_1 = require("../../tools/esbuild/utils");
|
|
45
46
|
const i18n_locale_plugin_1 = require("../../tools/vite/i18n-locale-plugin");
|
|
46
47
|
const render_page_1 = require("../../utils/server-rendering/render-page");
|
|
@@ -49,7 +50,8 @@ const webpack_browser_config_1 = require("../../utils/webpack-browser-config");
|
|
|
49
50
|
const application_1 = require("../application");
|
|
50
51
|
const browser_esbuild_1 = require("../browser-esbuild");
|
|
51
52
|
const load_proxy_config_1 = require("./load-proxy-config");
|
|
52
|
-
|
|
53
|
+
// eslint-disable-next-line max-lines-per-function
|
|
54
|
+
async function* serveWithVite(serverOptions, builderName, context, transformers, extensions) {
|
|
53
55
|
// Get the browser configuration from the target name.
|
|
54
56
|
const rawBrowserOptions = (await context.getTargetOptions(serverOptions.buildTarget));
|
|
55
57
|
const browserOptions = (await context.validateOptions({
|
|
@@ -88,7 +90,7 @@ async function* serveWithVite(serverOptions, builderName, context, plugins) {
|
|
|
88
90
|
// Always enable JIT linking to support applications built with and without AOT.
|
|
89
91
|
// In a development environment the additional scope information does not
|
|
90
92
|
// have a negative effect unlike production where final output size is relevant.
|
|
91
|
-
{ sourcemap: true, jit: true }, 1);
|
|
93
|
+
{ sourcemap: true, jit: true }, 1, true);
|
|
92
94
|
// Extract output index from options
|
|
93
95
|
// TODO: Provide this info from the build results
|
|
94
96
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -96,12 +98,13 @@ async function* serveWithVite(serverOptions, builderName, context, plugins) {
|
|
|
96
98
|
// dynamically import Vite for ESM compatibility
|
|
97
99
|
const { createServer, normalizePath } = await Promise.resolve().then(() => __importStar(require('vite')));
|
|
98
100
|
let server;
|
|
99
|
-
let
|
|
101
|
+
let serverUrl;
|
|
100
102
|
let hadError = false;
|
|
101
103
|
const generatedFiles = new Map();
|
|
102
104
|
const assetFiles = new Map();
|
|
103
105
|
const externalMetadata = {
|
|
104
|
-
|
|
106
|
+
implicitBrowser: [],
|
|
107
|
+
implicitServer: [],
|
|
105
108
|
explicit: [],
|
|
106
109
|
};
|
|
107
110
|
const build = builderName === '@angular-devkit/build-angular:application'
|
|
@@ -112,7 +115,7 @@ async function* serveWithVite(serverOptions, builderName, context, plugins) {
|
|
|
112
115
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
113
116
|
browserOptions, context, {
|
|
114
117
|
write: false,
|
|
115
|
-
},
|
|
118
|
+
}, extensions?.buildPlugins)) {
|
|
116
119
|
(0, node_assert_1.default)(result.outputFiles, 'Builder did not provide result files.');
|
|
117
120
|
// If build failed, nothing to serve
|
|
118
121
|
if (!result.success) {
|
|
@@ -146,18 +149,24 @@ async function* serveWithVite(serverOptions, builderName, context, plugins) {
|
|
|
146
149
|
assetFiles.set('/' + normalizePath(asset.destination), asset.source);
|
|
147
150
|
}
|
|
148
151
|
}
|
|
149
|
-
// To avoid disconnecting the array objects from the option, these arrays need to be mutated
|
|
150
|
-
// instead of replaced.
|
|
152
|
+
// To avoid disconnecting the array objects from the option, these arrays need to be mutated instead of replaced.
|
|
151
153
|
if (result.externalMetadata) {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
154
|
+
const { implicitBrowser, implicitServer, explicit } = result.externalMetadata;
|
|
155
|
+
// Empty Arrays to avoid growing unlimited with every re-build.
|
|
156
|
+
externalMetadata.explicit.length = 0;
|
|
157
|
+
externalMetadata.implicitServer.length = 0;
|
|
158
|
+
externalMetadata.implicitBrowser.length = 0;
|
|
159
|
+
externalMetadata.explicit.push(...explicit);
|
|
160
|
+
externalMetadata.implicitServer.push(...implicitServer);
|
|
161
|
+
externalMetadata.implicitBrowser.push(...implicitBrowser);
|
|
162
|
+
// The below needs to be sorted as Vite uses these options are part of the hashing invalidation algorithm.
|
|
163
|
+
// See: https://github.com/vitejs/vite/blob/0873bae0cfe0f0718ad2f5743dd34a17e4ab563d/packages/vite/src/node/optimizer/index.ts#L1203-L1239
|
|
164
|
+
externalMetadata.explicit.sort();
|
|
165
|
+
externalMetadata.implicitServer.sort();
|
|
166
|
+
externalMetadata.implicitBrowser.sort();
|
|
158
167
|
}
|
|
159
168
|
if (server) {
|
|
160
|
-
handleUpdate(generatedFiles, server, serverOptions, context.logger);
|
|
169
|
+
handleUpdate(normalizePath, generatedFiles, server, serverOptions, context.logger);
|
|
161
170
|
}
|
|
162
171
|
else {
|
|
163
172
|
const projectName = context.target?.project;
|
|
@@ -165,19 +174,37 @@ async function* serveWithVite(serverOptions, builderName, context, plugins) {
|
|
|
165
174
|
throw new Error('The builder requires a target.');
|
|
166
175
|
}
|
|
167
176
|
const { root = '' } = await context.getProjectMetadata(projectName);
|
|
168
|
-
const projectRoot = node_path_1.
|
|
177
|
+
const projectRoot = (0, node_path_1.join)(context.workspaceRoot, root);
|
|
169
178
|
const browsers = (0, supported_browsers_1.getSupportedBrowsers)(projectRoot, context.logger);
|
|
170
179
|
const target = (0, utils_1.transformSupportedBrowsersToTargets)(browsers);
|
|
171
180
|
// Setup server and start listening
|
|
172
|
-
const serverConfiguration = await setupServer(serverOptions, generatedFiles, assetFiles, browserOptions.preserveSymlinks, externalMetadata, !!browserOptions.ssr, prebundleTransformer, target);
|
|
181
|
+
const serverConfiguration = await setupServer(serverOptions, generatedFiles, assetFiles, browserOptions.preserveSymlinks, externalMetadata, !!browserOptions.ssr, prebundleTransformer, target, extensions?.middleware, transformers?.indexHtml);
|
|
173
182
|
server = await createServer(serverConfiguration);
|
|
174
183
|
await server.listen();
|
|
175
|
-
|
|
184
|
+
if (serverConfiguration.ssr?.optimizeDeps?.disabled === false) {
|
|
185
|
+
/**
|
|
186
|
+
* Vite will only start dependency optimization of SSR modules when the first request comes in.
|
|
187
|
+
* In some cases, this causes a long waiting time. To mitigate this, we call `ssrLoadModule` to
|
|
188
|
+
* initiate this process before the first request.
|
|
189
|
+
*
|
|
190
|
+
* NOTE: This will intentionally fail from the unknown module, but currently there is no other way
|
|
191
|
+
* to initiate the SSR dep optimizer.
|
|
192
|
+
*/
|
|
193
|
+
void server.ssrLoadModule('<deps-caller>').catch(() => { });
|
|
194
|
+
}
|
|
195
|
+
const urls = server.resolvedUrls;
|
|
196
|
+
if (urls && (urls.local.length || urls.network.length)) {
|
|
197
|
+
serverUrl = new URL(urls.local[0] ?? urls.network[0]);
|
|
198
|
+
}
|
|
176
199
|
// log connection information
|
|
177
200
|
server.printUrls();
|
|
178
201
|
}
|
|
179
202
|
// TODO: adjust output typings to reflect both development servers
|
|
180
|
-
yield {
|
|
203
|
+
yield {
|
|
204
|
+
success: true,
|
|
205
|
+
port: serverUrl?.port,
|
|
206
|
+
baseUrl: serverUrl?.href,
|
|
207
|
+
};
|
|
181
208
|
}
|
|
182
209
|
// Add cleanup logic via a builder teardown
|
|
183
210
|
let deferred;
|
|
@@ -189,13 +216,13 @@ async function* serveWithVite(serverOptions, builderName, context, plugins) {
|
|
|
189
216
|
await new Promise((resolve) => (deferred = resolve));
|
|
190
217
|
}
|
|
191
218
|
exports.serveWithVite = serveWithVite;
|
|
192
|
-
function handleUpdate(generatedFiles, server, serverOptions, logger) {
|
|
219
|
+
function handleUpdate(normalizePath, generatedFiles, server, serverOptions, logger) {
|
|
193
220
|
const updatedFiles = [];
|
|
194
221
|
// Invalidate any updated files
|
|
195
222
|
for (const [file, record] of generatedFiles) {
|
|
196
223
|
if (record.updated) {
|
|
197
224
|
updatedFiles.push(file);
|
|
198
|
-
const updatedModules = server.moduleGraph.getModulesByFile(file);
|
|
225
|
+
const updatedModules = server.moduleGraph.getModulesByFile(normalizePath((0, node_path_1.join)(server.config.root, file)));
|
|
199
226
|
updatedModules?.forEach((m) => server?.moduleGraph.invalidateModule(m));
|
|
200
227
|
}
|
|
201
228
|
}
|
|
@@ -207,8 +234,7 @@ function handleUpdate(generatedFiles, server, serverOptions, logger) {
|
|
|
207
234
|
const timestamp = Date.now();
|
|
208
235
|
server.ws.send({
|
|
209
236
|
type: 'update',
|
|
210
|
-
updates: updatedFiles.map((
|
|
211
|
-
const filePath = f.slice(1); // Remove leading slash.
|
|
237
|
+
updates: updatedFiles.map((filePath) => {
|
|
212
238
|
return {
|
|
213
239
|
type: 'css-update',
|
|
214
240
|
timestamp,
|
|
@@ -278,15 +304,21 @@ function analyzeResultFiles(normalizePath, htmlIndexPath, resultFiles, generated
|
|
|
278
304
|
}
|
|
279
305
|
}
|
|
280
306
|
// eslint-disable-next-line max-lines-per-function
|
|
281
|
-
async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks, externalMetadata, ssr, prebundleTransformer, target) {
|
|
307
|
+
async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks, externalMetadata, ssr, prebundleTransformer, target, extensionMiddleware, indexHtmlTransformer) {
|
|
282
308
|
const proxy = await (0, load_proxy_config_1.loadProxyConfiguration)(serverOptions.workspaceRoot, serverOptions.proxyConfig, true);
|
|
283
309
|
// dynamically import Vite for ESM compatibility
|
|
284
310
|
const { normalizePath } = await Promise.resolve().then(() => __importStar(require('vite')));
|
|
311
|
+
// Path will not exist on disk and only used to provide separate path for Vite requests
|
|
312
|
+
const virtualProjectRoot = normalizePath((0, node_path_1.join)(serverOptions.workspaceRoot, `.angular/vite-root`, serverOptions.buildTarget.project));
|
|
313
|
+
const serverExplicitExternal = [
|
|
314
|
+
...(await Promise.resolve().then(() => __importStar(require('node:module')))).builtinModules,
|
|
315
|
+
...externalMetadata.explicit,
|
|
316
|
+
];
|
|
285
317
|
const configuration = {
|
|
286
318
|
configFile: false,
|
|
287
319
|
envFile: false,
|
|
288
|
-
cacheDir: node_path_1.
|
|
289
|
-
root:
|
|
320
|
+
cacheDir: (0, node_path_1.join)(serverOptions.cacheOptions.path, 'vite'),
|
|
321
|
+
root: virtualProjectRoot,
|
|
290
322
|
publicDir: false,
|
|
291
323
|
esbuild: false,
|
|
292
324
|
mode: 'development',
|
|
@@ -315,8 +347,31 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
|
|
|
315
347
|
preTransformRequests: externalMetadata.explicit.length === 0,
|
|
316
348
|
},
|
|
317
349
|
ssr: {
|
|
318
|
-
//
|
|
319
|
-
|
|
350
|
+
// Note: `true` and `/.*/` have different sematics. When true, the `external` option is ignored.
|
|
351
|
+
noExternal: /.*/,
|
|
352
|
+
// Exclude any Node.js built in module and provided dependencies (currently build defined externals)
|
|
353
|
+
external: serverExplicitExternal,
|
|
354
|
+
optimizeDeps: getDepOptimizationConfig({
|
|
355
|
+
/**
|
|
356
|
+
* *********************************************
|
|
357
|
+
* NOTE: Temporary disable 'optimizeDeps' for SSR.
|
|
358
|
+
* *********************************************
|
|
359
|
+
*
|
|
360
|
+
* Currently this causes a number of issues.
|
|
361
|
+
* - Deps are re-optimized everytime the server is started.
|
|
362
|
+
* - Added deps after a rebuild are not optimized.
|
|
363
|
+
* - Breaks RxJs (Unless it is added as external). See: https://github.com/angular/angular-cli/issues/26235
|
|
364
|
+
*/
|
|
365
|
+
// Only enable with caching since it causes prebundle dependencies to be cached
|
|
366
|
+
disabled: true,
|
|
367
|
+
// Exclude any explicitly defined dependencies (currently build defined externals and node.js built-ins)
|
|
368
|
+
exclude: serverExplicitExternal,
|
|
369
|
+
// Include all implict dependencies from the external packages internal option
|
|
370
|
+
include: externalMetadata.implicitServer,
|
|
371
|
+
ssr: true,
|
|
372
|
+
prebundleTransformer,
|
|
373
|
+
target,
|
|
374
|
+
}),
|
|
320
375
|
},
|
|
321
376
|
plugins: [
|
|
322
377
|
(0, i18n_locale_plugin_1.createAngularLocaleDataPlugin)(),
|
|
@@ -331,24 +386,30 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
|
|
|
331
386
|
// `/@id/${source}` but is currently closer to a raw external than a resolved file path.
|
|
332
387
|
return source;
|
|
333
388
|
}
|
|
334
|
-
if (importer && source.startsWith(
|
|
389
|
+
if (importer && source[0] === '.' && importer.startsWith(virtualProjectRoot)) {
|
|
335
390
|
// Remove query if present
|
|
336
391
|
const [importerFile] = importer.split('?', 1);
|
|
337
|
-
source =
|
|
392
|
+
source =
|
|
393
|
+
'/' +
|
|
394
|
+
normalizePath((0, node_path_1.join)((0, node_path_1.dirname)((0, node_path_1.relative)(virtualProjectRoot, importerFile)), source));
|
|
338
395
|
}
|
|
339
396
|
const [file] = source.split('?', 1);
|
|
340
397
|
if (outputFiles.has(file)) {
|
|
341
|
-
return source;
|
|
398
|
+
return (0, node_path_1.join)(virtualProjectRoot, source);
|
|
342
399
|
}
|
|
343
400
|
},
|
|
344
401
|
load(id) {
|
|
345
402
|
const [file] = id.split('?', 1);
|
|
346
|
-
const
|
|
403
|
+
const relativeFile = '/' + normalizePath((0, node_path_1.relative)(virtualProjectRoot, file));
|
|
404
|
+
const codeContents = outputFiles.get(relativeFile)?.contents;
|
|
347
405
|
if (codeContents === undefined) {
|
|
406
|
+
if (relativeFile.endsWith('/node_modules/vite/dist/client/client.mjs')) {
|
|
407
|
+
return loadViteClientCode(file);
|
|
408
|
+
}
|
|
348
409
|
return;
|
|
349
410
|
}
|
|
350
411
|
const code = Buffer.from(codeContents).toString('utf-8');
|
|
351
|
-
const mapContents = outputFiles.get(
|
|
412
|
+
const mapContents = outputFiles.get(relativeFile + '.map')?.contents;
|
|
352
413
|
return {
|
|
353
414
|
// Remove source map URL comments from the code if a sourcemap is present.
|
|
354
415
|
// Vite will inline and add an additional sourcemap URL for the sourcemap.
|
|
@@ -383,7 +444,7 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
|
|
|
383
444
|
// Parse the incoming request.
|
|
384
445
|
// The base of the URL is unused but required to parse the URL.
|
|
385
446
|
const pathname = pathnameWithoutServePath(req.url, serverOptions);
|
|
386
|
-
const extension = node_path_1.
|
|
447
|
+
const extension = (0, node_path_1.extname)(pathname);
|
|
387
448
|
// Rewrite all build assets to a vite raw fs URL
|
|
388
449
|
const assetSourcePath = assets.get(pathname);
|
|
389
450
|
if (assetSourcePath !== undefined) {
|
|
@@ -413,12 +474,20 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
|
|
|
413
474
|
}
|
|
414
475
|
next();
|
|
415
476
|
});
|
|
477
|
+
if (extensionMiddleware?.length) {
|
|
478
|
+
extensionMiddleware.forEach((middleware) => server.middlewares.use(middleware));
|
|
479
|
+
}
|
|
416
480
|
// Returning a function, installs middleware after the main transform middleware but
|
|
417
481
|
// before the built-in HTML middleware
|
|
418
482
|
return () => {
|
|
419
483
|
function angularSSRMiddleware(req, res, next) {
|
|
420
484
|
const url = req.originalUrl;
|
|
421
|
-
if (
|
|
485
|
+
if (
|
|
486
|
+
// Skip if path is not defined.
|
|
487
|
+
!url ||
|
|
488
|
+
// Skip if path is like a file.
|
|
489
|
+
// NOTE: We use a regexp to mitigate against matching requests like: /browse/pl.0ef59752c0cd457dbf1391f08cbd936f
|
|
490
|
+
/^\.[a-z]{2,4}$/i.test((0, node_path_1.extname)(url.split('?')[0]))) {
|
|
422
491
|
next();
|
|
423
492
|
return;
|
|
424
493
|
}
|
|
@@ -434,15 +503,17 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
|
|
|
434
503
|
document: html,
|
|
435
504
|
route,
|
|
436
505
|
serverContext: 'ssr',
|
|
437
|
-
loadBundle: (
|
|
506
|
+
loadBundle: (uri) =>
|
|
438
507
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
439
|
-
server.ssrLoadModule(
|
|
508
|
+
server.ssrLoadModule(uri.slice(1)),
|
|
440
509
|
// Files here are only needed for critical CSS inlining.
|
|
441
510
|
outputFiles: {},
|
|
442
511
|
// TODO: add support for critical css inlining.
|
|
443
512
|
inlineCriticalCss: false,
|
|
444
513
|
});
|
|
445
|
-
return content
|
|
514
|
+
return indexHtmlTransformer && content
|
|
515
|
+
? await indexHtmlTransformer(content)
|
|
516
|
+
: content;
|
|
446
517
|
});
|
|
447
518
|
}
|
|
448
519
|
if (ssr) {
|
|
@@ -459,7 +530,7 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
|
|
|
459
530
|
if (pathname === '/' || pathname === `/index.html`) {
|
|
460
531
|
const rawHtml = outputFiles.get('/index.html')?.contents;
|
|
461
532
|
if (rawHtml) {
|
|
462
|
-
transformIndexHtmlAndAddHeaders(req.url, rawHtml, res, next);
|
|
533
|
+
transformIndexHtmlAndAddHeaders(req.url, rawHtml, res, next, indexHtmlTransformer);
|
|
463
534
|
return;
|
|
464
535
|
}
|
|
465
536
|
}
|
|
@@ -490,35 +561,18 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
|
|
|
490
561
|
},
|
|
491
562
|
},
|
|
492
563
|
],
|
|
493
|
-
optimizeDeps
|
|
564
|
+
// Browser only optimizeDeps. (This does not run for SSR dependencies).
|
|
565
|
+
optimizeDeps: getDepOptimizationConfig({
|
|
494
566
|
// Only enable with caching since it causes prebundle dependencies to be cached
|
|
495
567
|
disabled: !serverOptions.cacheOptions.enabled,
|
|
496
568
|
// Exclude any explicitly defined dependencies (currently build defined externals)
|
|
497
569
|
exclude: externalMetadata.explicit,
|
|
498
570
|
// Include all implict dependencies from the external packages internal option
|
|
499
|
-
include: externalMetadata.
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
// Set esbuild supported targets.
|
|
505
|
-
target,
|
|
506
|
-
supported: (0, utils_1.getFeatureSupport)(target),
|
|
507
|
-
plugins: [
|
|
508
|
-
{
|
|
509
|
-
name: 'angular-vite-optimize-deps',
|
|
510
|
-
setup(build) {
|
|
511
|
-
build.onLoad({ filter: /\.[cm]?js$/ }, async (args) => {
|
|
512
|
-
return {
|
|
513
|
-
contents: await prebundleTransformer.transformFile(args.path),
|
|
514
|
-
loader: 'js',
|
|
515
|
-
};
|
|
516
|
-
});
|
|
517
|
-
},
|
|
518
|
-
},
|
|
519
|
-
],
|
|
520
|
-
},
|
|
521
|
-
},
|
|
571
|
+
include: externalMetadata.implicitBrowser,
|
|
572
|
+
ssr: false,
|
|
573
|
+
prebundleTransformer,
|
|
574
|
+
target,
|
|
575
|
+
}),
|
|
522
576
|
};
|
|
523
577
|
if (serverOptions.ssl) {
|
|
524
578
|
if (serverOptions.sslCert && serverOptions.sslKey) {
|
|
@@ -538,6 +592,23 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
|
|
|
538
592
|
return configuration;
|
|
539
593
|
}
|
|
540
594
|
exports.setupServer = setupServer;
|
|
595
|
+
/**
|
|
596
|
+
* Reads the resolved Vite client code from disk and updates the content to remove
|
|
597
|
+
* an unactionable suggestion to update the Vite configuration file to disable the
|
|
598
|
+
* error overlay. The Vite configuration file is not present when used in the Angular
|
|
599
|
+
* CLI.
|
|
600
|
+
* @param file The absolute path to the Vite client code.
|
|
601
|
+
* @returns
|
|
602
|
+
*/
|
|
603
|
+
async function loadViteClientCode(file) {
|
|
604
|
+
const originalContents = await (0, promises_1.readFile)(file, 'utf-8');
|
|
605
|
+
let contents = originalContents.replace('You can also disable this overlay by setting', '');
|
|
606
|
+
contents = contents.replace(
|
|
607
|
+
// eslint-disable-next-line max-len
|
|
608
|
+
'<code part="config-option-name">server.hmr.overlay</code> to <code part="config-option-value">false</code> in <code part="config-file-name">vite.config.js.</code>', '');
|
|
609
|
+
(0, node_assert_1.default)(originalContents !== contents, 'Failed to update Vite client error overlay text.');
|
|
610
|
+
return contents;
|
|
611
|
+
}
|
|
541
612
|
function pathnameWithoutServePath(url, serverOptions) {
|
|
542
613
|
const parsedUrl = new URL(url, 'http://localhost');
|
|
543
614
|
let pathname = decodeURIComponent(parsedUrl.pathname);
|
|
@@ -549,3 +620,36 @@ function pathnameWithoutServePath(url, serverOptions) {
|
|
|
549
620
|
}
|
|
550
621
|
return pathname;
|
|
551
622
|
}
|
|
623
|
+
function getDepOptimizationConfig({ disabled, exclude, include, target, prebundleTransformer, ssr, }) {
|
|
624
|
+
const plugins = [
|
|
625
|
+
{
|
|
626
|
+
name: `angular-vite-optimize-deps${ssr ? '-ssr' : ''}`,
|
|
627
|
+
setup(build) {
|
|
628
|
+
build.onLoad({ filter: /\.[cm]?js$/ }, async (args) => {
|
|
629
|
+
return {
|
|
630
|
+
contents: await prebundleTransformer.transformFile(args.path),
|
|
631
|
+
loader: 'js',
|
|
632
|
+
};
|
|
633
|
+
});
|
|
634
|
+
},
|
|
635
|
+
},
|
|
636
|
+
];
|
|
637
|
+
if (ssr) {
|
|
638
|
+
plugins.unshift((0, rxjs_esm_resolution_plugin_1.createRxjsEsmResolutionPlugin)());
|
|
639
|
+
}
|
|
640
|
+
return {
|
|
641
|
+
// Only enable with caching since it causes prebundle dependencies to be cached
|
|
642
|
+
disabled,
|
|
643
|
+
// Exclude any explicitly defined dependencies (currently build defined externals)
|
|
644
|
+
exclude,
|
|
645
|
+
// Include all implict dependencies from the external packages internal option
|
|
646
|
+
include,
|
|
647
|
+
// Add an esbuild plugin to run the Angular linker on dependencies
|
|
648
|
+
esbuildOptions: {
|
|
649
|
+
// Set esbuild supported targets.
|
|
650
|
+
target,
|
|
651
|
+
supported: (0, utils_1.getFeatureSupport)(target),
|
|
652
|
+
plugins,
|
|
653
|
+
},
|
|
654
|
+
};
|
|
655
|
+
}
|
|
@@ -22,6 +22,7 @@ async function extractMessages(options, builderName, context, extractorConstruct
|
|
|
22
22
|
buildOptions.optimization = false;
|
|
23
23
|
buildOptions.sourceMap = { scripts: true, vendor: true };
|
|
24
24
|
buildOptions.localize = false;
|
|
25
|
+
buildOptions.budgets = undefined;
|
|
25
26
|
let build;
|
|
26
27
|
if (builderName === '@angular-devkit/build-angular:application') {
|
|
27
28
|
build = application_1.buildApplicationInternal;
|
|
@@ -45,7 +45,7 @@ async function extract() {
|
|
|
45
45
|
const bootstrapAppFnOrModule = bootstrapAppFn || AppServerModule;
|
|
46
46
|
(0, node_assert_1.default)(bootstrapAppFnOrModule, `Neither an AppServerModule nor a bootstrapping function was exported from: ${serverBundlePath}.`);
|
|
47
47
|
const routes = [];
|
|
48
|
-
for await (const { route, success } of extractRoutes(bootstrapAppFnOrModule, document
|
|
48
|
+
for await (const { route, success } of extractRoutes(bootstrapAppFnOrModule, document)) {
|
|
49
49
|
if (success) {
|
|
50
50
|
routes.push(route);
|
|
51
51
|
}
|
|
@@ -9,7 +9,7 @@ import { BuilderContext, BuilderOutput } from '@angular-devkit/architect';
|
|
|
9
9
|
import { json, logging } from '@angular-devkit/core';
|
|
10
10
|
import { Observable } from 'rxjs';
|
|
11
11
|
import { Schema } from './schema';
|
|
12
|
-
type SSRDevServerBuilderOptions = Schema & json.JsonObject;
|
|
12
|
+
export type SSRDevServerBuilderOptions = Schema & json.JsonObject;
|
|
13
13
|
export type SSRDevServerBuilderOutput = BuilderOutput & {
|
|
14
14
|
baseUrl?: string;
|
|
15
15
|
port?: string;
|
package/src/index.d.ts
CHANGED
|
@@ -14,4 +14,5 @@ export { execute as executeExtractI18nBuilder, ExtractI18nBuilderOptions, } from
|
|
|
14
14
|
export { execute as executeKarmaBuilder, KarmaBuilderOptions, KarmaConfigOptions, } from './builders/karma';
|
|
15
15
|
export { execute as executeProtractorBuilder, ProtractorBuilderOptions, } from './builders/protractor';
|
|
16
16
|
export { execute as executeServerBuilder, ServerBuilderOptions, ServerBuilderOutput, } from './builders/server';
|
|
17
|
+
export { execute as executeSSRDevServerBuilder, SSRDevServerBuilderOptions, SSRDevServerBuilderOutput, } from './builders/ssr-dev-server';
|
|
17
18
|
export { execute as executeNgPackagrBuilder, NgPackagrBuilderOptions } from './builders/ng-packagr';
|
package/src/index.js
CHANGED
|
@@ -21,7 +21,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
21
21
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
22
22
|
};
|
|
23
23
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
-
exports.executeNgPackagrBuilder = exports.executeServerBuilder = exports.executeProtractorBuilder = exports.executeKarmaBuilder = exports.executeExtractI18nBuilder = exports.executeDevServerBuilder = exports.buildApplication = exports.executeBrowserBuilder = exports.Type = exports.OutputHashing = exports.CrossOrigin = void 0;
|
|
24
|
+
exports.executeNgPackagrBuilder = exports.executeSSRDevServerBuilder = exports.executeServerBuilder = exports.executeProtractorBuilder = exports.executeKarmaBuilder = exports.executeExtractI18nBuilder = exports.executeDevServerBuilder = exports.buildApplication = exports.executeBrowserBuilder = exports.Type = exports.OutputHashing = exports.CrossOrigin = void 0;
|
|
25
25
|
__exportStar(require("./transforms"), exports);
|
|
26
26
|
var schema_1 = require("./builders/browser/schema");
|
|
27
27
|
Object.defineProperty(exports, "CrossOrigin", { enumerable: true, get: function () { return schema_1.CrossOrigin; } });
|
|
@@ -41,5 +41,7 @@ var protractor_1 = require("./builders/protractor");
|
|
|
41
41
|
Object.defineProperty(exports, "executeProtractorBuilder", { enumerable: true, get: function () { return protractor_1.execute; } });
|
|
42
42
|
var server_1 = require("./builders/server");
|
|
43
43
|
Object.defineProperty(exports, "executeServerBuilder", { enumerable: true, get: function () { return server_1.execute; } });
|
|
44
|
+
var ssr_dev_server_1 = require("./builders/ssr-dev-server");
|
|
45
|
+
Object.defineProperty(exports, "executeSSRDevServerBuilder", { enumerable: true, get: function () { return ssr_dev_server_1.execute; } });
|
|
44
46
|
var ng_packagr_1 = require("./builders/ng-packagr");
|
|
45
47
|
Object.defineProperty(exports, "executeNgPackagrBuilder", { enumerable: true, get: function () { return ng_packagr_1.execute; } });
|
|
@@ -17,6 +17,10 @@ const SET_CLASS_METADATA_NAME = 'ɵsetClassMetadata';
|
|
|
17
17
|
* Name of the asynchronous Angular class metadata function created by the Angular compiler.
|
|
18
18
|
*/
|
|
19
19
|
const SET_CLASS_METADATA_ASYNC_NAME = 'ɵsetClassMetadataAsync';
|
|
20
|
+
/**
|
|
21
|
+
* Name of the function that sets debug information on classes.
|
|
22
|
+
*/
|
|
23
|
+
const SET_CLASS_DEBUG_INFO_NAME = 'ɵsetClassDebugInfo';
|
|
20
24
|
/**
|
|
21
25
|
* Provides one or more keywords that if found within the content of a source file indicate
|
|
22
26
|
* that this plugin should be used with a source file.
|
|
@@ -24,7 +28,7 @@ const SET_CLASS_METADATA_ASYNC_NAME = 'ɵsetClassMetadataAsync';
|
|
|
24
28
|
* @returns An a string iterable containing one or more keywords.
|
|
25
29
|
*/
|
|
26
30
|
function getKeywords() {
|
|
27
|
-
return [SET_CLASS_METADATA_NAME, SET_CLASS_METADATA_ASYNC_NAME];
|
|
31
|
+
return [SET_CLASS_METADATA_NAME, SET_CLASS_METADATA_ASYNC_NAME, SET_CLASS_DEBUG_INFO_NAME];
|
|
28
32
|
}
|
|
29
33
|
exports.getKeywords = getKeywords;
|
|
30
34
|
/**
|
|
@@ -48,7 +52,8 @@ function default_1() {
|
|
|
48
52
|
}
|
|
49
53
|
if (calleeName !== undefined &&
|
|
50
54
|
(isRemoveClassMetadataCall(calleeName, callArguments) ||
|
|
51
|
-
isRemoveClassmetadataAsyncCall(calleeName, callArguments)
|
|
55
|
+
isRemoveClassmetadataAsyncCall(calleeName, callArguments) ||
|
|
56
|
+
isSetClassDebugInfoCall(calleeName, callArguments))) {
|
|
52
57
|
// The metadata function is always emitted inside a function expression
|
|
53
58
|
const parent = path.getFunctionParent();
|
|
54
59
|
if (parent && (parent.isFunctionExpression() || parent.isArrowFunctionExpression())) {
|
|
@@ -84,6 +89,13 @@ function isRemoveClassmetadataAsyncCall(name, args) {
|
|
|
84
89
|
isInlineFunction(args[1]) &&
|
|
85
90
|
isInlineFunction(args[2]));
|
|
86
91
|
}
|
|
92
|
+
/** Determines if a function call is a call to `setClassDebugInfo`. */
|
|
93
|
+
function isSetClassDebugInfoCall(name, args) {
|
|
94
|
+
return (name === SET_CLASS_DEBUG_INFO_NAME &&
|
|
95
|
+
args.length === 2 &&
|
|
96
|
+
core_1.types.isIdentifier(args[0]) &&
|
|
97
|
+
core_1.types.isObjectExpression(args[1]));
|
|
98
|
+
}
|
|
87
99
|
/** Determines if a node is an inline function expression. */
|
|
88
100
|
function isInlineFunction(node) {
|
|
89
101
|
return core_1.types.isFunctionExpression(node) || core_1.types.isArrowFunctionExpression(node);
|