@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.
Files changed (46) hide show
  1. package/package.json +9 -8
  2. package/src/builders/app-shell/render-worker.d.ts +1 -1
  3. package/src/builders/app-shell/render-worker.js +16 -9
  4. package/src/builders/application/build-action.js +5 -2
  5. package/src/builders/application/execute-build.js +49 -30
  6. package/src/builders/dev-server/builder.d.ts +12 -1
  7. package/src/builders/dev-server/builder.js +13 -4
  8. package/src/builders/dev-server/vite-server.d.ts +9 -6
  9. package/src/builders/dev-server/vite-server.js +167 -63
  10. package/src/builders/extract-i18n/application-extraction.js +1 -0
  11. package/src/builders/prerender/routes-extractor-worker.js +1 -1
  12. package/src/builders/ssr-dev-server/index.d.ts +1 -1
  13. package/src/index.d.ts +1 -0
  14. package/src/index.js +3 -1
  15. package/src/tools/babel/plugins/elide-angular-metadata.js +14 -2
  16. package/src/tools/esbuild/angular/compiler-plugin.js +104 -57
  17. package/src/tools/esbuild/application-code-bundle.d.ts +3 -2
  18. package/src/tools/esbuild/application-code-bundle.js +7 -19
  19. package/src/tools/esbuild/bundler-context.d.ts +4 -1
  20. package/src/tools/esbuild/bundler-context.js +13 -8
  21. package/src/tools/esbuild/bundler-execution-result.d.ts +16 -14
  22. package/src/tools/esbuild/bundler-execution-result.js +18 -3
  23. package/src/tools/esbuild/commonjs-checker.js +12 -7
  24. package/src/tools/esbuild/global-scripts.d.ts +1 -1
  25. package/src/tools/esbuild/global-scripts.js +2 -1
  26. package/src/tools/esbuild/javascript-transformer.d.ts +2 -1
  27. package/src/tools/esbuild/javascript-transformer.js +44 -20
  28. package/src/tools/esbuild/utils.d.ts +1 -1
  29. package/src/tools/esbuild/utils.js +18 -4
  30. package/src/utils/bundle-calculator.js +1 -1
  31. package/src/utils/environment-options.d.ts +1 -0
  32. package/src/utils/environment-options.js +7 -2
  33. package/src/utils/load-esm.js +6 -1
  34. package/src/utils/routes-extractor/extractor.d.ts +1 -1
  35. package/src/utils/routes-extractor/extractor.js +2 -2
  36. package/src/utils/server-rendering/esm-in-memory-loader/loader-hooks.d.ts +0 -4
  37. package/src/utils/server-rendering/esm-in-memory-loader/loader-hooks.js +78 -28
  38. package/src/utils/server-rendering/fetch-patch.d.ts +8 -0
  39. package/src/utils/server-rendering/fetch-patch.js +66 -0
  40. package/src/utils/server-rendering/prerender.js +25 -30
  41. package/src/utils/server-rendering/render-worker.d.ts +4 -2
  42. package/src/utils/server-rendering/render-worker.js +10 -4
  43. package/src/utils/server-rendering/routes-extractor-worker.d.ts +5 -3
  44. package/src/utils/server-rendering/routes-extractor-worker.js +12 -6
  45. package/src/utils/server-rendering/prerender-server.d.ts +0 -21
  46. 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 = __importDefault(require("node:path"));
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
- async function* serveWithVite(serverOptions, builderName, context, plugins) {
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 listeningAddress;
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
- implicit: [],
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
- }, plugins)) {
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
- if (result.externalMetadata.explicit) {
153
- externalMetadata.explicit.push(...result.externalMetadata.explicit);
154
- }
155
- if (result.externalMetadata.implicit) {
156
- externalMetadata.implicit.push(...result.externalMetadata.implicit);
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.default.join(context.workspaceRoot, root);
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
- listeningAddress = server.httpServer?.address();
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 { success: true, port: listeningAddress?.port };
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((f) => {
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.default.join(serverOptions.cacheOptions.path, 'vite'),
289
- root: serverOptions.workspaceRoot,
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
- // Exclude any provided dependencies (currently build defined externals)
319
- external: externalMetadata.implicit,
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 = normalizePath(node_path_1.default.join(node_path_1.default.dirname(importerFile), 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 codeContents = outputFiles.get(file)?.contents;
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(file + '.map')?.contents;
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.default.extname(pathname);
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 (!url || url.endsWith('.html')) {
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: (path) =>
506
+ loadBundle: (uri) =>
438
507
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
439
- server.ssrLoadModule(path.slice(1)),
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.implicit,
500
- // Skip automatic file-based entry point discovery
501
- entries: [],
502
- // Add an esbuild plugin to run the Angular linker on dependencies
503
- esbuildOptions: {
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);