@angular-devkit/build-angular 17.2.0-next.0 → 17.2.0-rc.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.
Files changed (50) hide show
  1. package/package.json +24 -25
  2. package/src/builders/application/build-action.d.ts +1 -0
  3. package/src/builders/application/build-action.js +18 -18
  4. package/src/builders/application/execute-build.js +8 -15
  5. package/src/builders/application/index.js +20 -3
  6. package/src/builders/application/options.d.ts +13 -2
  7. package/src/builders/application/options.js +16 -3
  8. package/src/builders/application/schema.d.ts +13 -0
  9. package/src/builders/application/schema.json +12 -0
  10. package/src/builders/application/setup-bundling.js +2 -2
  11. package/src/builders/browser/index.js +3 -2
  12. package/src/builders/dev-server/builder.js +13 -2
  13. package/src/builders/dev-server/options.d.ts +1 -0
  14. package/src/builders/dev-server/options.js +3 -1
  15. package/src/builders/dev-server/schema.d.ts +19 -0
  16. package/src/builders/dev-server/schema.json +18 -0
  17. package/src/builders/dev-server/vite-server.js +6 -6
  18. package/src/builders/extract-i18n/application-extraction.js +3 -1
  19. package/src/builders/server/index.js +3 -2
  20. package/src/tools/babel/plugins/elide-angular-metadata.d.ts +1 -1
  21. package/src/tools/babel/plugins/elide-angular-metadata.js +38 -30
  22. package/src/tools/babel/plugins/pure-toplevel-functions.d.ts +1 -1
  23. package/src/tools/babel/plugins/pure-toplevel-functions.js +3 -4
  24. package/src/tools/esbuild/angular/compiler-plugin.js +1 -1
  25. package/src/tools/esbuild/application-code-bundle.js +7 -4
  26. package/src/tools/esbuild/budget-stats.js +5 -0
  27. package/src/tools/esbuild/bundler-context.d.ts +1 -0
  28. package/src/tools/esbuild/bundler-context.js +19 -5
  29. package/src/tools/esbuild/bundler-execution-result.d.ts +2 -0
  30. package/src/tools/esbuild/bundler-execution-result.js +6 -0
  31. package/src/tools/esbuild/compiler-plugin-options.js +2 -1
  32. package/src/tools/esbuild/external-packages-plugin.d.ts +3 -1
  33. package/src/tools/esbuild/external-packages-plugin.js +9 -5
  34. package/src/tools/esbuild/global-scripts.js +3 -4
  35. package/src/tools/esbuild/global-styles.js +2 -1
  36. package/src/tools/esbuild/index-html-generator.js +4 -2
  37. package/src/tools/esbuild/stylesheets/bundle-options.d.ts +2 -0
  38. package/src/tools/esbuild/stylesheets/bundle-options.js +1 -0
  39. package/src/tools/esbuild/stylesheets/stylesheet-plugin-factory.d.ts +7 -0
  40. package/src/tools/esbuild/stylesheets/stylesheet-plugin-factory.js +24 -8
  41. package/src/tools/esbuild/utils.d.ts +5 -8
  42. package/src/tools/esbuild/utils.js +64 -31
  43. package/src/tools/vite/angular-memory-plugin.js +13 -0
  44. package/src/tools/webpack/utils/stats.d.ts +1 -0
  45. package/src/tools/webpack/utils/stats.js +101 -49
  46. package/src/utils/environment-options.d.ts +1 -0
  47. package/src/utils/environment-options.js +3 -1
  48. package/src/utils/load-proxy-config.js +3 -3
  49. package/src/utils/postcss-configuration.d.ts +11 -0
  50. package/src/utils/postcss-configuration.js +77 -0
package/package.json CHANGED
@@ -1,26 +1,26 @@
1
1
  {
2
2
  "name": "@angular-devkit/build-angular",
3
- "version": "17.2.0-next.0",
3
+ "version": "17.2.0-rc.0",
4
4
  "description": "Angular Webpack Build Facade",
5
5
  "main": "src/index.js",
6
6
  "typings": "src/index.d.ts",
7
7
  "builders": "builders.json",
8
8
  "dependencies": {
9
9
  "@ampproject/remapping": "2.2.1",
10
- "@angular-devkit/architect": "0.1702.0-next.0",
11
- "@angular-devkit/build-webpack": "0.1702.0-next.0",
12
- "@angular-devkit/core": "17.2.0-next.0",
13
- "@babel/core": "7.23.7",
10
+ "@angular-devkit/architect": "0.1702.0-rc.0",
11
+ "@angular-devkit/build-webpack": "0.1702.0-rc.0",
12
+ "@angular-devkit/core": "17.2.0-rc.0",
13
+ "@babel/core": "7.23.9",
14
14
  "@babel/generator": "7.23.6",
15
15
  "@babel/helper-annotate-as-pure": "7.22.5",
16
16
  "@babel/helper-split-export-declaration": "7.22.6",
17
- "@babel/plugin-transform-async-generator-functions": "7.23.7",
17
+ "@babel/plugin-transform-async-generator-functions": "7.23.9",
18
18
  "@babel/plugin-transform-async-to-generator": "7.23.3",
19
- "@babel/plugin-transform-runtime": "7.23.7",
20
- "@babel/preset-env": "7.23.8",
21
- "@babel/runtime": "7.23.8",
19
+ "@babel/plugin-transform-runtime": "7.23.9",
20
+ "@babel/preset-env": "7.23.9",
21
+ "@babel/runtime": "7.23.9",
22
22
  "@discoveryjs/json-ext": "0.5.7",
23
- "@ngtools/webpack": "17.2.0-next.0",
23
+ "@ngtools/webpack": "17.2.0-rc.0",
24
24
  "@vitejs/plugin-basic-ssl": "1.1.0",
25
25
  "ansi-colors": "4.1.3",
26
26
  "autoprefixer": "10.4.17",
@@ -29,50 +29,49 @@
29
29
  "browserslist": "^4.21.5",
30
30
  "copy-webpack-plugin": "12.0.2",
31
31
  "critters": "0.0.20",
32
- "css-loader": "6.9.1",
33
- "esbuild-wasm": "0.19.12",
32
+ "css-loader": "6.10.0",
33
+ "esbuild-wasm": "0.20.0",
34
34
  "fast-glob": "3.3.2",
35
35
  "https-proxy-agent": "7.0.2",
36
36
  "http-proxy-middleware": "2.0.6",
37
- "inquirer": "9.2.12",
37
+ "inquirer": "9.2.14",
38
38
  "jsonc-parser": "3.2.1",
39
39
  "karma-source-map-support": "1.4.0",
40
40
  "less": "4.2.0",
41
41
  "less-loader": "11.1.0",
42
42
  "license-webpack-plugin": "4.0.2",
43
43
  "loader-utils": "3.2.1",
44
- "magic-string": "0.30.5",
45
- "mini-css-extract-plugin": "2.7.7",
44
+ "magic-string": "0.30.7",
45
+ "mini-css-extract-plugin": "2.8.0",
46
46
  "mrmime": "2.0.0",
47
47
  "open": "8.4.2",
48
48
  "ora": "5.4.1",
49
49
  "parse5-html-rewriting-stream": "7.0.0",
50
- "picomatch": "3.0.1",
51
- "piscina": "4.3.0",
52
- "postcss": "8.4.33",
53
- "postcss-loader": "8.0.0",
50
+ "picomatch": "4.0.1",
51
+ "piscina": "4.3.1",
52
+ "postcss": "8.4.35",
53
+ "postcss-loader": "8.1.0",
54
54
  "resolve-url-loader": "5.0.0",
55
55
  "rxjs": "7.8.1",
56
56
  "sass": "1.70.0",
57
- "sass-loader": "14.0.0",
58
- "semver": "7.5.4",
57
+ "sass-loader": "14.1.0",
58
+ "semver": "7.6.0",
59
59
  "source-map-loader": "5.0.0",
60
60
  "source-map-support": "0.5.21",
61
61
  "terser": "5.27.0",
62
- "text-table": "0.2.0",
63
62
  "tree-kill": "1.2.2",
64
63
  "tslib": "2.6.2",
65
- "undici": "6.4.0",
64
+ "undici": "6.6.2",
66
65
  "vite": "5.0.12",
67
66
  "watchpack": "2.4.0",
68
- "webpack": "5.89.0",
67
+ "webpack": "5.90.1",
69
68
  "webpack-dev-middleware": "6.1.1",
70
69
  "webpack-dev-server": "4.15.1",
71
70
  "webpack-merge": "5.10.0",
72
71
  "webpack-subresource-integrity": "5.1.0"
73
72
  },
74
73
  "optionalDependencies": {
75
- "esbuild": "0.19.12"
74
+ "esbuild": "0.20.0"
76
75
  },
77
76
  "peerDependencies": {
78
77
  "@angular/compiler-cli": "^17.0.0 || ^17.2.0-next.0",
@@ -26,4 +26,5 @@ export declare function runEsBuildBuildAction(action: (rebuildState?: RebuildSta
26
26
  poll?: number;
27
27
  signal?: AbortSignal;
28
28
  preserveSymlinks?: boolean;
29
+ clearScreen?: boolean;
29
30
  }): AsyncIterable<(ExecutionResult['outputWithFiles'] | ExecutionResult['output']) & BuilderOutput>;
@@ -40,8 +40,21 @@ const sass_language_1 = require("../../tools/esbuild/stylesheets/sass-language")
40
40
  const utils_1 = require("../../tools/esbuild/utils");
41
41
  const delete_output_dir_1 = require("../../utils/delete-output-dir");
42
42
  const environment_options_1 = require("../../utils/environment-options");
43
+ // Watch workspace for package manager changes
44
+ const packageWatchFiles = [
45
+ // manifest can affect module resolution
46
+ 'package.json',
47
+ // npm lock file
48
+ 'package-lock.json',
49
+ // pnpm lock file
50
+ 'pnpm-lock.yaml',
51
+ // yarn lock file including Yarn PnP manifest files (https://yarnpkg.com/advanced/pnp-spec/)
52
+ 'yarn.lock',
53
+ '.pnp.cjs',
54
+ '.pnp.data.json',
55
+ ];
43
56
  async function* runEsBuildBuildAction(action, options) {
44
- const { writeToFileSystemFilter, writeToFileSystem, watch, poll, logger, deleteOutputPath, cacheOptions, outputOptions, verbose, projectRoot, workspaceRoot, progress, preserveSymlinks, } = options;
57
+ const { writeToFileSystemFilter, writeToFileSystem, watch, poll, clearScreen, logger, deleteOutputPath, cacheOptions, outputOptions, verbose, projectRoot, workspaceRoot, progress, preserveSymlinks, } = options;
45
58
  if (deleteOutputPath && writeToFileSystem) {
46
59
  await (0, delete_output_dir_1.deleteOutputDir)(workspaceRoot, outputOptions.base, [
47
60
  outputOptions.browser,
@@ -54,8 +67,6 @@ async function* runEsBuildBuildAction(action, options) {
54
67
  try {
55
68
  // Perform the build action
56
69
  result = await withProgress('Building...', () => action());
57
- // Log all diagnostic (error/warning) messages from the build
58
- await (0, utils_1.logMessages)(logger, result);
59
70
  }
60
71
  finally {
61
72
  // Ensure Sass workers are shutdown if not watching
@@ -95,19 +106,6 @@ async function* runEsBuildBuildAction(action, options) {
95
106
  if (environment_options_1.shouldWatchRoot) {
96
107
  watcher.add(projectRoot);
97
108
  }
98
- // Watch workspace for package manager changes
99
- const packageWatchFiles = [
100
- // manifest can affect module resolution
101
- 'package.json',
102
- // npm lock file
103
- 'package-lock.json',
104
- // pnpm lock file
105
- 'pnpm-lock.yaml',
106
- // yarn lock file including Yarn PnP manifest files (https://yarnpkg.com/advanced/pnp-spec/)
107
- 'yarn.lock',
108
- '.pnp.cjs',
109
- '.pnp.data.json',
110
- ];
111
109
  watcher.add(packageWatchFiles
112
110
  .map((file) => node_path_1.default.join(workspaceRoot, file))
113
111
  .filter((file) => (0, node_fs_1.existsSync)(file)));
@@ -138,12 +136,14 @@ async function* runEsBuildBuildAction(action, options) {
138
136
  if (options.signal?.aborted) {
139
137
  break;
140
138
  }
139
+ if (clearScreen) {
140
+ // eslint-disable-next-line no-console
141
+ console.clear();
142
+ }
141
143
  if (verbose) {
142
144
  logger.info(changes.toDebugString());
143
145
  }
144
146
  result = await withProgress('Changes detected. Rebuilding...', () => action(result.createRebuildState(changes)));
145
- // Log all diagnostic (error/warning) messages from the rebuild
146
- await (0, utils_1.logMessages)(logger, result);
147
147
  // Update watched locations provided by the new build result.
148
148
  // Keep watching all previous files if there are any errors; otherwise consider all
149
149
  // files stale until confirmed present in the new result's watch files.
@@ -16,14 +16,13 @@ const commonjs_checker_1 = require("../../tools/esbuild/commonjs-checker");
16
16
  const license_extractor_1 = require("../../tools/esbuild/license-extractor");
17
17
  const utils_1 = require("../../tools/esbuild/utils");
18
18
  const bundle_calculator_1 = require("../../utils/bundle-calculator");
19
- const color_1 = require("../../utils/color");
20
19
  const copy_assets_1 = require("../../utils/copy-assets");
21
20
  const supported_browsers_1 = require("../../utils/supported-browsers");
22
21
  const execute_post_bundle_1 = require("./execute-post-bundle");
23
22
  const i18n_1 = require("./i18n");
24
23
  const setup_bundling_1 = require("./setup-bundling");
25
24
  async function executeBuild(options, context, rebuildState) {
26
- const { projectRoot, workspaceRoot, i18nOptions, optimizationOptions, assets, cacheOptions, prerenderOptions, } = options;
25
+ const { projectRoot, workspaceRoot, i18nOptions, optimizationOptions, assets, cacheOptions, prerenderOptions, ssrOptions, verbose, colors, jsonLogs, } = options;
27
26
  // TODO: Consider integrating into watch mode. Would require full rebuild on target changes.
28
27
  const browsers = (0, supported_browsers_1.getSupportedBrowsers)(projectRoot, context.logger);
29
28
  // Load active translations if inlining
@@ -96,12 +95,11 @@ async function executeBuild(options, context, rebuildState) {
96
95
  executionResult.addOutputFile('3rdpartylicenses.txt', await (0, license_extractor_1.extractLicenses)(metafile, workspaceRoot), bundler_context_1.BuildOutputFileType.Root);
97
96
  }
98
97
  // Perform i18n translation inlining if enabled
99
- let prerenderedRoutes;
100
98
  if (i18nOptions.shouldInline) {
101
99
  const result = await (0, i18n_1.inlineI18n)(options, executionResult, initialFiles);
102
100
  executionResult.addErrors(result.errors);
103
101
  executionResult.addWarnings(result.warnings);
104
- prerenderedRoutes = result.prerenderedRoutes;
102
+ executionResult.addPrerenderedRoutes(result.prerenderedRoutes);
105
103
  }
106
104
  else {
107
105
  const result = await (0, execute_post_bundle_1.executePostBundleSteps)(options, executionResult.outputFiles, executionResult.assetFiles, initialFiles,
@@ -109,26 +107,21 @@ async function executeBuild(options, context, rebuildState) {
109
107
  i18nOptions.hasDefinedSourceLocale ? i18nOptions.sourceLocale : undefined);
110
108
  executionResult.addErrors(result.errors);
111
109
  executionResult.addWarnings(result.warnings);
112
- prerenderedRoutes = result.prerenderedRoutes;
110
+ executionResult.addPrerenderedRoutes(result.prerenderedRoutes);
113
111
  executionResult.outputFiles.push(...result.additionalOutputFiles);
114
112
  executionResult.assetFiles.push(...result.additionalAssets);
115
113
  }
116
114
  if (prerenderOptions) {
117
- executionResult.addOutputFile('prerendered-routes.json', JSON.stringify({ routes: prerenderedRoutes.sort((a, b) => a.localeCompare(b)) }, null, 2), bundler_context_1.BuildOutputFileType.Root);
118
- let prerenderMsg = `Prerendered ${prerenderedRoutes.length} static route`;
119
- if (prerenderedRoutes.length > 1) {
120
- prerenderMsg += 's.';
121
- }
122
- else {
123
- prerenderMsg += '.';
124
- }
125
- context.logger.info(color_1.colors.magenta(prerenderMsg) + '\n');
115
+ const prerenderedRoutes = executionResult.prerenderedRoutes;
116
+ executionResult.addOutputFile('prerendered-routes.json', JSON.stringify({ routes: prerenderedRoutes }, null, 2), bundler_context_1.BuildOutputFileType.Root);
126
117
  }
127
- (0, utils_1.logBuildStats)(context.logger, metafile, initialFiles, budgetFailures, changedFiles, estimatedTransferSizes);
128
118
  // Write metafile if stats option is enabled
129
119
  if (options.stats) {
130
120
  executionResult.addOutputFile('stats.json', JSON.stringify(metafile, null, 2), bundler_context_1.BuildOutputFileType.Root);
131
121
  }
122
+ if (!jsonLogs) {
123
+ context.logger.info((0, utils_1.logBuildStats)(metafile, initialFiles, budgetFailures, colors, changedFiles, estimatedTransferSizes, !!ssrOptions, verbose));
124
+ }
132
125
  return executionResult;
133
126
  }
134
127
  exports.executeBuild = executeBuild;
@@ -10,6 +10,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
10
10
  exports.buildApplication = exports.buildApplicationInternal = void 0;
11
11
  const architect_1 = require("@angular-devkit/architect");
12
12
  const bundler_context_1 = require("../../tools/esbuild/bundler-context");
13
+ const utils_1 = require("../../tools/esbuild/utils");
14
+ const color_1 = require("../../utils/color");
13
15
  const purge_cache_1 = require("../../utils/purge-cache");
14
16
  const version_1 = require("../../utils/version");
15
17
  const build_action_1 = require("./build-action");
@@ -57,11 +59,25 @@ context, infrastructureSettings, extensions) {
57
59
  context.addTeardown(() => controller.abort('builder-teardown'));
58
60
  }
59
61
  yield* (0, build_action_1.runEsBuildBuildAction)(async (rebuildState) => {
62
+ const { prerenderOptions, outputOptions, jsonLogs } = normalizedOptions;
60
63
  const startTime = process.hrtime.bigint();
61
64
  const result = await (0, execute_build_1.executeBuild)(normalizedOptions, context, rebuildState);
62
- const buildTime = Number(process.hrtime.bigint() - startTime) / 10 ** 9;
63
- const status = result.errors.length > 0 ? 'failed' : 'complete';
64
- logger.info(`Application bundle generation ${status}. [${buildTime.toFixed(3)} seconds]`);
65
+ if (!jsonLogs) {
66
+ if (prerenderOptions) {
67
+ const prerenderedRoutesLength = result.prerenderedRoutes.length;
68
+ let prerenderMsg = `Prerendered ${prerenderedRoutesLength} static route`;
69
+ prerenderMsg += prerenderedRoutesLength !== 1 ? 's.' : '.';
70
+ logger.info(color_1.colors.magenta(prerenderMsg));
71
+ }
72
+ const buildTime = Number(process.hrtime.bigint() - startTime) / 10 ** 9;
73
+ const hasError = result.errors.length > 0;
74
+ if (writeToFileSystem && !hasError) {
75
+ logger.info(`Output location: ${outputOptions.base}\n`);
76
+ }
77
+ logger.info(`Application bundle generation ${hasError ? 'failed' : 'complete'}. [${buildTime.toFixed(3)} seconds]`);
78
+ }
79
+ // Log all diagnostic (error/warning) messages
80
+ await (0, utils_1.logMessages)(logger, result, normalizedOptions);
65
81
  return result;
66
82
  }, {
67
83
  watch: normalizedOptions.watch,
@@ -74,6 +90,7 @@ context, infrastructureSettings, extensions) {
74
90
  projectRoot: normalizedOptions.projectRoot,
75
91
  workspaceRoot: normalizedOptions.workspaceRoot,
76
92
  progress: normalizedOptions.progress,
93
+ clearScreen: normalizedOptions.clearScreen,
77
94
  writeToFileSystem,
78
95
  // For app-shell and SSG server files are not required by users.
79
96
  // Omit these when SSR is not enabled.
@@ -31,7 +31,9 @@ interface InternalOptions {
31
31
  * Indicates whether all node packages should be marked as external.
32
32
  * Currently used by the dev-server to support prebundling.
33
33
  */
34
- externalPackages?: boolean;
34
+ externalPackages?: boolean | {
35
+ exclude: string[];
36
+ };
35
37
  /**
36
38
  * Forces the output from the localize post-processing to not create nested directories per locale output.
37
39
  * This is only used by the development server which currently only supports a single locale per build.
@@ -72,7 +74,9 @@ export declare function normalizeOptions(context: BuilderContext, projectName: s
72
74
  polyfills: string[] | undefined;
73
75
  poll: number | undefined;
74
76
  progress: boolean;
75
- externalPackages: boolean | undefined;
77
+ externalPackages: boolean | {
78
+ exclude: string[];
79
+ } | undefined;
76
80
  preserveSymlinks: boolean;
77
81
  stylePreprocessorOptions: import("./schema").StylePreprocessorOptions | undefined;
78
82
  subresourceIntegrity: boolean | undefined;
@@ -127,6 +131,7 @@ export declare function normalizeOptions(context: BuilderContext, projectName: s
127
131
  file: string;
128
132
  package: string;
129
133
  } | undefined;
134
+ postcssConfiguration: import("../../utils/postcss-configuration").PostcssConfiguration | undefined;
130
135
  i18nOptions: I18nOptions & {
131
136
  duplicateTranslationBehavior?: I18NTranslation | undefined;
132
137
  missingTranslationBehavior?: I18NTranslation | undefined;
@@ -136,5 +141,11 @@ export declare function normalizeOptions(context: BuilderContext, projectName: s
136
141
  publicPath: string | undefined;
137
142
  plugins: Plugin[] | undefined;
138
143
  loaderExtensions: Record<string, "binary" | "file" | "text"> | undefined;
144
+ jsonLogs: boolean;
145
+ colors: boolean;
146
+ clearScreen: boolean | undefined;
147
+ define: {
148
+ [key: string]: string;
149
+ } | undefined;
139
150
  }>;
140
151
  export {};
@@ -17,9 +17,12 @@ const node_module_1 = require("node:module");
17
17
  const node_path_1 = __importDefault(require("node:path"));
18
18
  const helpers_1 = require("../../tools/webpack/utils/helpers");
19
19
  const utils_1 = require("../../utils");
20
+ const color_1 = require("../../utils/color");
21
+ const environment_options_1 = require("../../utils/environment-options");
20
22
  const i18n_options_1 = require("../../utils/i18n-options");
21
23
  const normalize_cache_1 = require("../../utils/normalize-cache");
22
24
  const package_chunk_sort_1 = require("../../utils/package-chunk-sort");
25
+ const postcss_configuration_1 = require("../../utils/postcss-configuration");
23
26
  const tailwind_1 = require("../../utils/tailwind");
24
27
  const webpack_browser_config_1 = require("../../utils/webpack-browser-config");
25
28
  const schema_1 = require("./schema");
@@ -70,7 +73,7 @@ async function normalizeOptions(context, projectName, options, extensions) {
70
73
  server: 'server',
71
74
  media: 'media',
72
75
  ...(typeof outputPath === 'string' ? undefined : outputPath),
73
- base: normalizeDirectoryPath(node_path_1.default.join(workspaceRoot, typeof outputPath === 'string' ? outputPath : outputPath.base)),
76
+ base: normalizeDirectoryPath(node_path_1.default.resolve(workspaceRoot, typeof outputPath === 'string' ? outputPath : outputPath.base)),
74
77
  };
75
78
  const outputNames = {
76
79
  bundles: options.outputHashing === schema_1.OutputHashing.All || options.outputHashing === schema_1.OutputHashing.Bundles
@@ -108,6 +111,11 @@ async function normalizeOptions(context, projectName, options, extensions) {
108
111
  loaderExtensions[extension] = value;
109
112
  }
110
113
  }
114
+ const postcssConfiguration = await (0, postcss_configuration_1.loadPostcssConfiguration)(workspaceRoot, projectRoot);
115
+ // Skip tailwind configuration if postcss is customized
116
+ const tailwindConfiguration = postcssConfiguration
117
+ ? undefined
118
+ : await getTailwindConfig(workspaceRoot, projectRoot, context);
111
119
  const globalStyles = [];
112
120
  if (options.styles?.length) {
113
121
  const { entryPoints: stylesheetEntrypoints, noInjectNames } = (0, helpers_1.normalizeGlobalStyles)(options.styles || []);
@@ -170,7 +178,7 @@ async function normalizeOptions(context, projectName, options, extensions) {
170
178
  };
171
179
  }
172
180
  // Initial options to keep
173
- const { allowedCommonJsDependencies, aot, baseHref, crossOrigin, externalDependencies, extractLicenses, inlineStyleLanguage = 'css', outExtension, serviceWorker, poll, polyfills, statsJson, stylePreprocessorOptions, subresourceIntegrity, verbose, watch, progress = true, externalPackages, deleteOutputPath, namedChunks, budgets, deployUrl, } = options;
181
+ const { allowedCommonJsDependencies, aot, baseHref, crossOrigin, externalDependencies, extractLicenses, inlineStyleLanguage = 'css', outExtension, serviceWorker, poll, polyfills, statsJson, stylePreprocessorOptions, subresourceIntegrity, verbose, watch, progress = true, externalPackages, deleteOutputPath, namedChunks, budgets, deployUrl, clearScreen, define, } = options;
174
182
  // Return all the normalized options
175
183
  return {
176
184
  advancedOptimizations: !!aot && optimizationOptions.scripts,
@@ -212,13 +220,18 @@ async function normalizeOptions(context, projectName, options, extensions) {
212
220
  globalScripts,
213
221
  serviceWorker: typeof serviceWorker === 'string' ? node_path_1.default.join(workspaceRoot, serviceWorker) : undefined,
214
222
  indexHtmlOptions,
215
- tailwindConfiguration: await getTailwindConfig(workspaceRoot, projectRoot, context),
223
+ tailwindConfiguration,
224
+ postcssConfiguration,
216
225
  i18nOptions,
217
226
  namedChunks,
218
227
  budgets: budgets?.length ? budgets : undefined,
219
228
  publicPath: deployUrl ? deployUrl : undefined,
220
229
  plugins: extensions?.codePlugins?.length ? extensions?.codePlugins : undefined,
221
230
  loaderExtensions,
231
+ jsonLogs: environment_options_1.useJSONBuildLogs,
232
+ colors: color_1.colors.enabled,
233
+ clearScreen,
234
+ define,
222
235
  };
223
236
  }
224
237
  exports.normalizeOptions = normalizeOptions;
@@ -33,10 +33,23 @@ export interface Schema {
33
33
  * set.
34
34
  */
35
35
  budgets?: Budget[];
36
+ /**
37
+ * Automatically clear the terminal screen during rebuilds.
38
+ */
39
+ clearScreen?: boolean;
36
40
  /**
37
41
  * Define the crossorigin attribute setting of elements that provide CORS support.
38
42
  */
39
43
  crossOrigin?: CrossOrigin;
44
+ /**
45
+ * Defines global identifiers that will be replaced with a specified constant value when
46
+ * found in any JavaScript or TypeScript code including libraries. The value will be used
47
+ * directly. String values must be put in quotes. Identifiers within Angular metadata such
48
+ * as Component Decorators will not be replaced.
49
+ */
50
+ define?: {
51
+ [key: string]: string;
52
+ };
40
53
  /**
41
54
  * Delete the output path before building.
42
55
  */
@@ -133,6 +133,11 @@
133
133
  },
134
134
  "default": []
135
135
  },
136
+ "clearScreen": {
137
+ "type": "boolean",
138
+ "default": false,
139
+ "description": "Automatically clear the terminal screen during rebuilds."
140
+ },
136
141
  "optimization": {
137
142
  "description": "Enables optimization of the build output. Including minification of scripts and styles, tree-shaking, dead-code elimination, inlining of critical CSS and fonts inlining. For more information, see https://angular.io/guide/workspace-config#optimization-configuration.",
138
143
  "default": true,
@@ -211,6 +216,13 @@
211
216
  "^\\.\\S+$": { "enum": ["text", "binary", "file", "empty"] }
212
217
  }
213
218
  },
219
+ "define": {
220
+ "description": "Defines global identifiers that will be replaced with a specified constant value when found in any JavaScript or TypeScript code including libraries. The value will be used directly. String values must be put in quotes. Identifiers within Angular metadata such as Component Decorators will not be replaced.",
221
+ "type": "object",
222
+ "additionalProperties": {
223
+ "type": "string"
224
+ }
225
+ },
214
226
  "fileReplacements": {
215
227
  "description": "Replace compilation source files with other compilation source files in the build.",
216
228
  "type": "array",
@@ -59,11 +59,11 @@ function setupBundlerContexts(options, browsers, codeBundleCache) {
59
59
  // Disable external deps for server bundles.
60
60
  // This is because it breaks Vite 'optimizeDeps' for SSR.
61
61
  externalPackages: false,
62
- }, nodeTargets, codeBundleCache), () => false));
62
+ }, nodeTargets, codeBundleCache)));
63
63
  // Server polyfills code
64
64
  const serverPolyfillBundleOptions = (0, application_code_bundle_1.createServerPolyfillBundleOptions)(options, nodeTargets, codeBundleCache);
65
65
  if (serverPolyfillBundleOptions) {
66
- bundlerContexts.push(new bundler_context_1.BundlerContext(workspaceRoot, !!options.watch, serverPolyfillBundleOptions, () => false));
66
+ bundlerContexts.push(new bundler_context_1.BundlerContext(workspaceRoot, !!options.watch, serverPolyfillBundleOptions));
67
67
  }
68
68
  }
69
69
  return bundlerContexts;
@@ -120,8 +120,9 @@ function buildWebpackBrowser(options, context, transforms = {}) {
120
120
  webpackFactory: require('webpack'),
121
121
  logging: transforms.logging ||
122
122
  ((stats, config) => {
123
- if (options.verbose) {
124
- context.logger.info(stats.toString(config.stats));
123
+ if (options.verbose && config.stats !== false) {
124
+ const statsOptions = config.stats === true ? undefined : config.stats;
125
+ context.logger.info(stats.toString(statsOptions));
125
126
  }
126
127
  }),
127
128
  }).pipe((0, rxjs_1.concatMap)(
@@ -63,8 +63,16 @@ function execute(options, context, transforms = {}, extensions) {
63
63
  if (transforms?.logging || transforms?.webpackConfiguration) {
64
64
  throw new Error('The `application` and `browser-esbuild` builders do not support Webpack transforms.');
65
65
  }
66
+ // Warn if the initial options provided by the user enable prebundling but caching is disabled
67
+ if (options.prebundle && !normalizedOptions.cacheOptions.enabled) {
68
+ context.logger.warn(`Prebundling has been configured but will not be used because caching has been disabled.`);
69
+ }
66
70
  return (0, rxjs_1.defer)(() => Promise.resolve().then(() => __importStar(require('./vite-server')))).pipe((0, rxjs_1.switchMap)(({ serveWithVite }) => serveWithVite(normalizedOptions, builderName, context, transforms, extensions)));
67
71
  }
72
+ // Warn if the initial options provided by the user enable prebundling with Webpack-based builders
73
+ if (options.prebundle) {
74
+ context.logger.warn(`Prebundling has been configured but will not be used because it is not supported by the "${builderName}" builder.`);
75
+ }
68
76
  if (extensions?.buildPlugins?.length) {
69
77
  throw new Error('Only the `application` and `browser-esbuild` builders support plugins.');
70
78
  }
@@ -80,7 +88,10 @@ async function initialize(initialOptions, projectName, context, builderSelector
80
88
  // Purge old build disk cache.
81
89
  await (0, purge_cache_1.purgeStaleBuildCache)(context);
82
90
  const normalizedOptions = await (0, options_1.normalizeOptions)(context, projectName, initialOptions);
83
- const builderName = await context.getBuilderNameForTarget(normalizedOptions.buildTarget);
91
+ const builderName = builderSelector({
92
+ builderName: await context.getBuilderNameForTarget(normalizedOptions.buildTarget),
93
+ forceEsbuild: !!normalizedOptions.forceEsbuild,
94
+ }, context.logger);
84
95
  if (!normalizedOptions.disableHostCheck &&
85
96
  !/^127\.\d+\.\d+\.\d+/g.test(normalizedOptions.host) &&
86
97
  normalizedOptions.host !== 'localhost') {
@@ -100,7 +111,7 @@ case.
100
111
  }
101
112
  normalizedOptions.port = await (0, check_port_1.checkPort)(normalizedOptions.port, normalizedOptions.host);
102
113
  return {
103
- builderName: builderSelector({ builderName, forceEsbuild: !!normalizedOptions.forceEsbuild }, context.logger),
114
+ builderName,
104
115
  normalizedOptions,
105
116
  };
106
117
  }
@@ -43,4 +43,5 @@ export declare function normalizeOptions(context: BuilderContext, projectName: s
43
43
  sslCert: string | undefined;
44
44
  sslKey: string | undefined;
45
45
  forceEsbuild: boolean | undefined;
46
+ prebundle: import("./schema").PrebundleUnion;
46
47
  }>;
@@ -33,7 +33,7 @@ async function normalizeOptions(context, projectName, options) {
33
33
  const buildTargetSpecifier = options.buildTarget ?? options.browserTarget ?? `::development`;
34
34
  const buildTarget = (0, architect_1.targetFromTargetString)(buildTargetSpecifier, projectName, 'build');
35
35
  // Initial options to keep
36
- const { host, port, poll, open, verbose, watch, allowedHosts, disableHostCheck, liveReload, hmr, headers, proxyConfig, servePath, publicHost, ssl, sslCert, sslKey, forceEsbuild, } = options;
36
+ const { host, port, poll, open, verbose, watch, allowedHosts, disableHostCheck, liveReload, hmr, headers, proxyConfig, servePath, publicHost, ssl, sslCert, sslKey, forceEsbuild, prebundle, } = options;
37
37
  // Return all the normalized options
38
38
  return {
39
39
  buildTarget,
@@ -58,6 +58,8 @@ async function normalizeOptions(context, projectName, options) {
58
58
  sslCert,
59
59
  sslKey,
60
60
  forceEsbuild,
61
+ // Prebundling defaults to true but requires caching to function
62
+ prebundle: cacheOptions.enabled && (prebundle ?? true),
61
63
  };
62
64
  }
63
65
  exports.normalizeOptions = normalizeOptions;
@@ -58,6 +58,12 @@ export interface Schema {
58
58
  * Port to listen on.
59
59
  */
60
60
  port?: number;
61
+ /**
62
+ * Enable and control the Vite-based development server's prebundling capabilities. To
63
+ * enable prebundling, the Angular CLI cache must also be enabled. This option has no effect
64
+ * when using the 'browser' or other Webpack-based builders.
65
+ */
66
+ prebundle?: PrebundleUnion;
61
67
  /**
62
68
  * Proxy configuration file. For more information, see
63
69
  * https://angular.io/guide/build#proxying-to-a-backend-server.
@@ -94,3 +100,16 @@ export interface Schema {
94
100
  */
95
101
  watch?: boolean;
96
102
  }
103
+ /**
104
+ * Enable and control the Vite-based development server's prebundling capabilities. To
105
+ * enable prebundling, the Angular CLI cache must also be enabled. This option has no effect
106
+ * when using the 'browser' or other Webpack-based builders.
107
+ */
108
+ export type PrebundleUnion = boolean | PrebundleClass;
109
+ export interface PrebundleClass {
110
+ /**
111
+ * List of package imports that should not be prebundled by the development server. The
112
+ * packages will be bundled into the application code itself.
113
+ */
114
+ exclude: string[];
115
+ }
@@ -106,6 +106,24 @@
106
106
  "type": "boolean",
107
107
  "description": "Force the development server to use the 'browser-esbuild' builder when building. This is a developer preview option for the esbuild-based build system.",
108
108
  "default": false
109
+ },
110
+ "prebundle": {
111
+ "description": "Enable and control the Vite-based development server's prebundling capabilities. To enable prebundling, the Angular CLI cache must also be enabled. This option has no effect when using the 'browser' or other Webpack-based builders.",
112
+ "oneOf": [
113
+ { "type": "boolean" },
114
+ {
115
+ "type": "object",
116
+ "properties": {
117
+ "exclude": {
118
+ "description": "List of package imports that should not be prebundled by the development server. The packages will be bundled into the application code itself.",
119
+ "type": "array",
120
+ "items": { "type": "string" }
121
+ }
122
+ },
123
+ "additionalProperties": false,
124
+ "required": ["exclude"]
125
+ }
126
+ ]
109
127
  }
110
128
  },
111
129
  "additionalProperties": false,
@@ -66,16 +66,15 @@ async function* serveWithVite(serverOptions, builderName, context, transformers,
66
66
  // Avoid bundling and processing the ssr entry-point as this is not used by the dev-server.
67
67
  browserOptions.ssr = true;
68
68
  // https://nodejs.org/api/process.html#processsetsourcemapsenabledval
69
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
70
69
  process.setSourceMapsEnabled(true);
71
70
  }
72
71
  // Set all packages as external to support Vite's prebundle caching
73
- browserOptions.externalPackages = serverOptions.cacheOptions.enabled;
72
+ browserOptions.externalPackages = serverOptions.prebundle;
74
73
  const baseHref = browserOptions.baseHref;
75
74
  if (serverOptions.servePath === undefined && baseHref !== undefined) {
76
75
  // Remove trailing slash
77
76
  serverOptions.servePath =
78
- baseHref[baseHref.length - 1] === '/' ? baseHref.slice(0, -1) : baseHref;
77
+ baseHref !== './' && baseHref[baseHref.length - 1] === '/' ? baseHref.slice(0, -1) : baseHref;
79
78
  }
80
79
  // The development server currently only supports a single locale when localizing.
81
80
  // This matches the behavior of the Webpack-based development server but could be expanded in the future.
@@ -341,7 +340,8 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
341
340
  publicDir: false,
342
341
  esbuild: false,
343
342
  mode: 'development',
344
- appType: 'mpa',
343
+ // We use custom as we do not rely on Vite's htmlFallbackMiddleware and indexHtmlMiddleware.
344
+ appType: 'custom',
345
345
  css: {
346
346
  devSourcemap: true,
347
347
  },
@@ -392,7 +392,7 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
392
392
  * - Breaks RxJs (Unless it is added as external). See: https://github.com/angular/angular-cli/issues/26235
393
393
  */
394
394
  // Only enable with caching since it causes prebundle dependencies to be cached
395
- disabled: true, // !serverOptions.cacheOptions.enabled,
395
+ disabled: true, // serverOptions.prebundle === false,
396
396
  // Exclude any explicitly defined dependencies (currently build defined externals and node.js built-ins)
397
397
  exclude: serverExplicitExternal,
398
398
  // Include all implict dependencies from the external packages internal option
@@ -422,7 +422,7 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
422
422
  // Browser only optimizeDeps. (This does not run for SSR dependencies).
423
423
  optimizeDeps: getDepOptimizationConfig({
424
424
  // Only enable with caching since it causes prebundle dependencies to be cached
425
- disabled: !serverOptions.cacheOptions.enabled,
425
+ disabled: serverOptions.prebundle === false,
426
426
  // Exclude any explicitly defined dependencies (currently build defined externals)
427
427
  exclude: externalMetadata.explicit,
428
428
  // Include all implict dependencies from the external packages internal option