@angular-devkit/build-angular 17.0.0 → 17.0.1

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 CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "@angular-devkit/build-angular",
3
- "version": "17.0.0",
3
+ "version": "17.0.1",
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.1700.0",
11
- "@angular-devkit/build-webpack": "0.1700.0",
12
- "@angular-devkit/core": "17.0.0",
10
+ "@angular-devkit/architect": "0.1700.1",
11
+ "@angular-devkit/build-webpack": "0.1700.1",
12
+ "@angular-devkit/core": "17.0.1",
13
13
  "@babel/core": "7.23.2",
14
14
  "@babel/generator": "7.23.0",
15
15
  "@babel/helper-annotate-as-pure": "7.22.5",
@@ -20,7 +20,7 @@
20
20
  "@babel/preset-env": "7.23.2",
21
21
  "@babel/runtime": "7.23.2",
22
22
  "@discoveryjs/json-ext": "0.5.7",
23
- "@ngtools/webpack": "17.0.0",
23
+ "@ngtools/webpack": "17.0.1",
24
24
  "@vitejs/plugin-basic-ssl": "1.0.1",
25
25
  "ansi-colors": "4.1.3",
26
26
  "autoprefixer": "10.4.16",
@@ -34,32 +34,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
34
34
  };
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.runEsBuildBuildAction = void 0;
37
- const promises_1 = __importDefault(require("node:fs/promises"));
38
37
  const node_path_1 = __importDefault(require("node:path"));
39
38
  const sass_language_1 = require("../../tools/esbuild/stylesheets/sass-language");
40
39
  const utils_1 = require("../../tools/esbuild/utils");
40
+ const delete_output_dir_1 = require("../../utils/delete-output-dir");
41
41
  const environment_options_1 = require("../../utils/environment-options");
42
- const error_1 = require("../../utils/error");
43
42
  async function* runEsBuildBuildAction(action, options) {
44
43
  const { writeToFileSystemFilter, writeToFileSystem = true, watch, poll, logger, deleteOutputPath, cacheOptions, outputPath, verbose, projectRoot, workspaceRoot, progress, } = options;
45
- if (writeToFileSystem) {
46
- // Clean output path if enabled
47
- if (deleteOutputPath) {
48
- if (outputPath === workspaceRoot) {
49
- logger.error('Output path MUST not be workspace root directory!');
50
- return;
51
- }
52
- await promises_1.default.rm(outputPath, { force: true, recursive: true, maxRetries: 3 });
53
- }
54
- // Create output directory if needed
55
- try {
56
- await promises_1.default.mkdir(outputPath, { recursive: true });
57
- }
58
- catch (e) {
59
- (0, error_1.assertIsError)(e);
60
- logger.error('Unable to create output directory: ' + e.message);
61
- return;
62
- }
44
+ if (deleteOutputPath && writeToFileSystem) {
45
+ await (0, delete_output_dir_1.deleteOutputDir)(workspaceRoot, outputPath);
63
46
  }
64
47
  const withProgress = progress ? utils_1.withSpinner : utils_1.withNoProgress;
65
48
  // Initial build
@@ -135,7 +118,7 @@ async function* runEsBuildBuildAction(action, options) {
135
118
  return;
136
119
  }
137
120
  // Wait for changes and rebuild as needed
138
- let previousWatchFiles = new Set(result.watchFiles);
121
+ const currentWatchFiles = new Set(result.watchFiles);
139
122
  try {
140
123
  for await (const changes of watcher) {
141
124
  if (options.signal?.aborted) {
@@ -146,12 +129,22 @@ async function* runEsBuildBuildAction(action, options) {
146
129
  }
147
130
  result = await withProgress('Changes detected. Rebuilding...', () => action(result.createRebuildState(changes)));
148
131
  // Update watched locations provided by the new build result.
149
- // Add any new locations
150
- watcher.add(result.watchFiles.filter((watchFile) => !previousWatchFiles.has(watchFile)));
151
- const newWatchFiles = new Set(result.watchFiles);
152
- // Remove any old locations
153
- watcher.remove([...previousWatchFiles].filter((watchFile) => !newWatchFiles.has(watchFile)));
154
- previousWatchFiles = newWatchFiles;
132
+ // Keep watching all previous files if there are any errors; otherwise consider all
133
+ // files stale until confirmed present in the new result's watch files.
134
+ const staleWatchFiles = result.errors.length > 0 ? undefined : new Set(currentWatchFiles);
135
+ for (const watchFile of result.watchFiles) {
136
+ if (!currentWatchFiles.has(watchFile)) {
137
+ // Add new watch location
138
+ watcher.add(watchFile);
139
+ currentWatchFiles.add(watchFile);
140
+ }
141
+ // Present so remove from stale locations
142
+ staleWatchFiles?.delete(watchFile);
143
+ }
144
+ // Remove any stale locations if the build was successful
145
+ if (staleWatchFiles?.size) {
146
+ watcher.remove([...staleWatchFiles]);
147
+ }
155
148
  if (writeToFileSystem) {
156
149
  // Write output files
157
150
  const filesToWrite = writeToFileSystemFilter
@@ -11,6 +11,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
11
11
  };
12
12
  Object.defineProperty(exports, "__esModule", { value: true });
13
13
  exports.normalizeOptions = void 0;
14
+ const promises_1 = require("node:fs/promises");
14
15
  const node_module_1 = require("node:module");
15
16
  const node_path_1 = __importDefault(require("node:path"));
16
17
  const helpers_1 = require("../../tools/webpack/utils/helpers");
@@ -67,8 +68,15 @@ async function normalizeOptions(context, projectName, options, plugins) {
67
68
  let fileReplacements;
68
69
  if (options.fileReplacements) {
69
70
  for (const replacement of options.fileReplacements) {
71
+ const fileReplaceWith = node_path_1.default.join(workspaceRoot, replacement.with);
72
+ try {
73
+ await (0, promises_1.access)(fileReplaceWith, promises_1.constants.F_OK);
74
+ }
75
+ catch {
76
+ throw new Error(`The ${fileReplaceWith} path in file replacements does not exist.`);
77
+ }
70
78
  fileReplacements ??= {};
71
- fileReplacements[node_path_1.default.join(workspaceRoot, replacement.replace)] = node_path_1.default.join(workspaceRoot, replacement.with);
79
+ fileReplacements[node_path_1.default.join(workspaceRoot, replacement.replace)] = fileReplaceWith;
72
80
  }
73
81
  }
74
82
  const globalStyles = [];
@@ -74,7 +74,7 @@ async function initialize(options, context, webpackConfigurationTransform) {
74
74
  transformedConfig = await webpackConfigurationTransform(config);
75
75
  }
76
76
  if (options.deleteOutputPath) {
77
- (0, utils_1.deleteOutputDir)(context.workspaceRoot, originalOutputPath);
77
+ await (0, utils_1.deleteOutputDir)(context.workspaceRoot, originalOutputPath);
78
78
  }
79
79
  return { config: transformedConfig || config, projectRoot, projectSourceRoot, i18n };
80
80
  }
@@ -16,6 +16,7 @@ const node_fs_1 = require("node:fs");
16
16
  const promises_1 = __importDefault(require("node:fs/promises"));
17
17
  const node_path_1 = __importDefault(require("node:path"));
18
18
  const utils_1 = require("../../tools/esbuild/utils");
19
+ const utils_2 = require("../../utils");
19
20
  const application_1 = require("../application");
20
21
  const builder_status_warnings_1 = require("./builder-status-warnings");
21
22
  /**
@@ -29,7 +30,11 @@ async function* buildEsbuildBrowser(userOptions, context, infrastructureSettings
29
30
  // Inform user of status of builder and options
30
31
  (0, builder_status_warnings_1.logBuilderStatusWarnings)(userOptions, context);
31
32
  const normalizedOptions = normalizeOptions(userOptions);
32
- const fullOutputPath = node_path_1.default.join(context.workspaceRoot, normalizedOptions.outputPath);
33
+ const { deleteOutputPath, outputPath } = normalizedOptions;
34
+ const fullOutputPath = node_path_1.default.join(context.workspaceRoot, outputPath);
35
+ if (deleteOutputPath && infrastructureSettings?.write !== false) {
36
+ await (0, utils_2.deleteOutputDir)(context.workspaceRoot, outputPath);
37
+ }
33
38
  for await (const result of (0, application_1.buildApplicationInternal)(normalizedOptions, context, {
34
39
  write: false,
35
40
  }, plugins)) {
@@ -11,4 +11,4 @@ import { DevServerBuilderOutput } from './webpack-server';
11
11
  export { DevServerBuilderOptions, DevServerBuilderOutput, execute as executeDevServerBuilder };
12
12
  declare const _default: import("../../../../architect/src/internal").Builder<DevServerBuilderOptions & import("../../../../core/src").JsonObject>;
13
13
  export default _default;
14
- export { execute as serveWebpackBrowser };
14
+ export { execute as executeDevServer };
@@ -7,9 +7,9 @@
7
7
  * found in the LICENSE file at https://angular.io/license
8
8
  */
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
- exports.serveWebpackBrowser = exports.executeDevServerBuilder = void 0;
10
+ exports.executeDevServer = exports.executeDevServerBuilder = void 0;
11
11
  const architect_1 = require("@angular-devkit/architect");
12
12
  const builder_1 = require("./builder");
13
13
  Object.defineProperty(exports, "executeDevServerBuilder", { enumerable: true, get: function () { return builder_1.execute; } });
14
- Object.defineProperty(exports, "serveWebpackBrowser", { enumerable: true, get: function () { return builder_1.execute; } });
14
+ Object.defineProperty(exports, "executeDevServer", { enumerable: true, get: function () { return builder_1.execute; } });
15
15
  exports.default = (0, architect_1.createBuilder)(builder_1.execute);
@@ -60,11 +60,12 @@ async function* serveWithVite(serverOptions, builderName, context, transformers,
60
60
  poll: serverOptions.poll,
61
61
  verbose: serverOptions.verbose,
62
62
  }, builderName));
63
- if (browserOptions.prerender) {
63
+ if (browserOptions.prerender || browserOptions.ssr) {
64
64
  // Disable prerendering if enabled and force SSR.
65
65
  // This is so instead of prerendering all the routes for every change, the page is "prerendered" when it is requested.
66
- browserOptions.ssr = true;
67
66
  browserOptions.prerender = false;
67
+ // Avoid bundling and processing the ssr entry-point as this is not used by the dev-server.
68
+ browserOptions.ssr = true;
68
69
  // https://nodejs.org/api/process.html#processsetsourcemapsenabledval
69
70
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
70
71
  process.setSourceMapsEnabled(true);
@@ -90,7 +91,7 @@ async function* serveWithVite(serverOptions, builderName, context, transformers,
90
91
  // Always enable JIT linking to support applications built with and without AOT.
91
92
  // In a development environment the additional scope information does not
92
93
  // have a negative effect unlike production where final output size is relevant.
93
- { sourcemap: true, jit: true }, 1, true);
94
+ { sourcemap: true, jit: true, thirdPartySourcemaps: true }, 1, true);
94
95
  // Extract output index from options
95
96
  // TODO: Provide this info from the build results
96
97
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -107,6 +108,13 @@ async function* serveWithVite(serverOptions, builderName, context, transformers,
107
108
  implicitServer: [],
108
109
  explicit: [],
109
110
  };
111
+ // Add cleanup logic via a builder teardown.
112
+ let deferred;
113
+ context.addTeardown(async () => {
114
+ await server?.close();
115
+ await prebundleTransformer.close();
116
+ deferred?.();
117
+ });
110
118
  const build = builderName === '@angular-devkit/build-angular:application'
111
119
  ? application_1.buildApplicationInternal
112
120
  : browser_esbuild_1.buildEsbuildBrowser;
@@ -206,13 +214,6 @@ async function* serveWithVite(serverOptions, builderName, context, transformers,
206
214
  baseUrl: serverUrl?.href,
207
215
  };
208
216
  }
209
- // Add cleanup logic via a builder teardown
210
- let deferred;
211
- context.addTeardown(async () => {
212
- await server?.close();
213
- await prebundleTransformer.close();
214
- deferred?.();
215
- });
216
217
  await new Promise((resolve) => (deferred = resolve));
217
218
  }
218
219
  exports.serveWithVite = serveWithVite;
@@ -421,19 +422,15 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
421
422
  const originalssrTransform = server.ssrTransform;
422
423
  server.ssrTransform = async (code, map, url, originalCode) => {
423
424
  const result = await originalssrTransform(code, null, url, originalCode);
424
- if (!result) {
425
- return null;
426
- }
427
- let transformedCode = result.code;
428
- if (result.map && map) {
429
- transformedCode +=
430
- `\n//# sourceMappingURL=` +
431
- `data:application/json;base64,${Buffer.from(JSON.stringify((0, remapping_1.default)([result.map, map], () => null))).toString('base64')}`;
425
+ if (!result || !result.map || !map) {
426
+ return result;
432
427
  }
428
+ const remappedMap = (0, remapping_1.default)([result.map, map], () => null);
429
+ // Set the sourcemap root to the workspace root. This is needed since we set a virtual path as root.
430
+ remappedMap.sourceRoot = serverOptions.workspaceRoot + '/';
433
431
  return {
434
432
  ...result,
435
- map: null,
436
- code: transformedCode,
433
+ map: remappedMap,
437
434
  };
438
435
  };
439
436
  // Assets and resources get handled first
@@ -150,7 +150,7 @@ async function initialize(options, context, webpackConfigurationTransform) {
150
150
  return [getPlatformServerExportsConfig(wco), (0, configs_1.getCommonConfig)(wco), (0, configs_1.getStylesConfig)(wco)];
151
151
  });
152
152
  if (options.deleteOutputPath) {
153
- (0, utils_1.deleteOutputDir)(context.workspaceRoot, originalOutputPath);
153
+ await (0, utils_1.deleteOutputDir)(context.workspaceRoot, originalOutputPath);
154
154
  }
155
155
  const transformedConfig = (await webpackConfigurationTransform?.(config)) ?? config;
156
156
  return { config: transformedConfig, i18n, projectRoot, projectSourceRoot };
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @license
3
+ * Copyright Google LLC All Rights Reserved.
4
+ *
5
+ * Use of this source code is governed by an MIT-style license that can be
6
+ * found in the LICENSE file at https://angular.io/license
7
+ */
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ /**
3
+ * @license
4
+ * Copyright Google LLC All Rights Reserved.
5
+ *
6
+ * Use of this source code is governed by an MIT-style license that can be
7
+ * found in the LICENSE file at https://angular.io/license
8
+ */
9
+ // import { AngularCompilation, createAngularCompilation } from './compilation';
10
+ // import { ComponentStylesheetBundler } from './component-stylesheets';
11
+ // export interface InvalidationResult {
12
+ // code: boolean;
13
+ // styles: string[];
14
+ // }
15
+ // export class ApplicationAngularCompiler {
16
+ // #compilation: AngularCompilation | undefined;
17
+ // #stylesheetBundler: ComponentStylesheetBundler;
18
+ // readonly #emitFileCache = new Map<string, string>();
19
+ // constructor(options: { persistentCachePath?: string; jitMode?: boolean, incremental?: boolean }) {
20
+ // const {
21
+ // jitMode = false,
22
+ // incremental = false,
23
+ // persistentCachePath,
24
+ // } = options;
25
+ // this.#stylesheetBundler = new ComponentStylesheetBundler({}, incremental);
26
+ // }
27
+ // get isJit(): boolean {
28
+ // return false;
29
+ // }
30
+ // get usesAllowJs(): boolean {
31
+ // return false;
32
+ // }
33
+ // async initialize() {
34
+ // }
35
+ // invalidate(files: Iterable<string>): InvalidationResult {
36
+ // return {
37
+ // code: true,
38
+ // styles: [],
39
+ // };
40
+ // }
41
+ // }
@@ -35,6 +35,9 @@ class ParallelCompilation extends angular_compilation_1.AngularCompilation {
35
35
  minThreads: 1,
36
36
  maxThreads: 1,
37
37
  idleTimeout: Infinity,
38
+ // Web containers do not support transferable objects with receiveOnMessagePort which
39
+ // is used when the Atomics based wait loop is enable.
40
+ useAtomics: !process.versions.webcontainer,
38
41
  filename: localRequire.resolve('./parallel-worker'),
39
42
  });
40
43
  }
@@ -7,8 +7,8 @@
7
7
  */
8
8
  export declare class SharedTSCompilationState {
9
9
  #private;
10
- get waitUntilReady(): Promise<void>;
11
- markAsReady(): void;
10
+ get waitUntilReady(): Promise<boolean>;
11
+ markAsReady(hasErrors: boolean): void;
12
12
  markAsInProgress(): void;
13
13
  dispose(): void;
14
14
  }
@@ -12,17 +12,19 @@ class SharedTSCompilationState {
12
12
  #pendingCompilation = true;
13
13
  #resolveCompilationReady;
14
14
  #compilationReadyPromise;
15
+ #hasErrors = true;
15
16
  get waitUntilReady() {
16
17
  if (!this.#pendingCompilation) {
17
- return Promise.resolve();
18
+ return Promise.resolve(this.#hasErrors);
18
19
  }
19
20
  this.#compilationReadyPromise ??= new Promise((resolve) => {
20
21
  this.#resolveCompilationReady = resolve;
21
22
  });
22
23
  return this.#compilationReadyPromise;
23
24
  }
24
- markAsReady() {
25
- this.#resolveCompilationReady?.();
25
+ markAsReady(hasErrors) {
26
+ this.#hasErrors = hasErrors;
27
+ this.#resolveCompilationReady?.(hasErrors);
26
28
  this.#compilationReadyPromise = undefined;
27
29
  this.#pendingCompilation = false;
28
30
  }
@@ -30,7 +32,7 @@ class SharedTSCompilationState {
30
32
  this.#pendingCompilation = true;
31
33
  }
32
34
  dispose() {
33
- this.markAsReady();
35
+ this.markAsReady(true);
34
36
  globalSharedCompilationState = undefined;
35
37
  }
36
38
  }
@@ -202,8 +202,7 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
202
202
  return result;
203
203
  }
204
204
  if (compilation instanceof compilation_1.NoopCompilation) {
205
- await sharedTSCompilationState.waitUntilReady;
206
- hasCompilationErrors = false;
205
+ hasCompilationErrors = await sharedTSCompilationState.waitUntilReady;
207
206
  return result;
208
207
  }
209
208
  const diagnostics = await compilation.diagnoseFiles();
@@ -250,7 +249,7 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
250
249
  hasCompilationErrors = !!result.errors?.length;
251
250
  // Reset the setup warnings so that they are only shown during the first build.
252
251
  setupWarnings = undefined;
253
- sharedTSCompilationState.markAsReady();
252
+ sharedTSCompilationState.markAsReady(hasCompilationErrors);
254
253
  return result;
255
254
  });
256
255
  build.onLoad({ filter: /\.[cm]?[jt]sx?$/ }, async (args) => {
@@ -314,7 +313,7 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
314
313
  }
315
314
  build.onEnd((result) => {
316
315
  // Ensure other compilations are unblocked if the main compilation throws during start
317
- sharedTSCompilationState?.markAsReady();
316
+ sharedTSCompilationState?.markAsReady(hasCompilationErrors);
318
317
  for (const { outputFiles, metafile } of additionalResults.values()) {
319
318
  // Add any additional output files to the main output files
320
319
  if (outputFiles?.length) {
@@ -194,7 +194,6 @@ function createServerPolyfillBundleOptions(options, target, sourceFileCache) {
194
194
  if (!polyfillBundleOptions) {
195
195
  return;
196
196
  }
197
- const { workspaceRoot } = options;
198
197
  const buildOptions = {
199
198
  ...polyfillBundleOptions,
200
199
  platform: 'node',
@@ -218,8 +217,6 @@ function createServerPolyfillBundleOptions(options, target, sourceFileCache) {
218
217
  'polyfills.server': namespace,
219
218
  },
220
219
  };
221
- buildOptions.plugins ??= [];
222
- buildOptions.plugins.push((0, rxjs_esm_resolution_plugin_1.createRxjsEsmResolutionPlugin)());
223
220
  return () => buildOptions;
224
221
  }
225
222
  exports.createServerPolyfillBundleOptions = createServerPolyfillBundleOptions;
@@ -161,22 +161,26 @@ class BundlerContext {
161
161
  throw failure;
162
162
  }
163
163
  }
164
+ finally {
165
+ if (this.incremental) {
166
+ // When incremental always add any files from the load result cache
167
+ if (this.#loadCache) {
168
+ this.#loadCache.watchFiles
169
+ .filter((file) => !isInternalAngularFile(file))
170
+ // watch files are fully resolved paths
171
+ .forEach((file) => this.watchFiles.add(file));
172
+ }
173
+ }
174
+ }
164
175
  // Update files that should be watched.
165
176
  // While this should technically not be linked to incremental mode, incremental is only
166
177
  // currently enabled with watch mode where watch files are needed.
167
178
  if (this.incremental) {
168
179
  // Add input files except virtual angular files which do not exist on disk
169
180
  Object.keys(result.metafile.inputs)
170
- .filter((input) => !input.startsWith('angular:'))
181
+ .filter((input) => !isInternalAngularFile(input))
171
182
  // input file paths are always relative to the workspace root
172
183
  .forEach((input) => this.watchFiles.add((0, node_path_1.join)(this.workspaceRoot, input)));
173
- // Also add any files from the load result cache
174
- if (this.#loadCache) {
175
- this.#loadCache.watchFiles
176
- .filter((file) => !file.startsWith('angular:'))
177
- // watch files are fully resolved paths
178
- .forEach((file) => this.watchFiles.add(file));
179
- }
180
184
  }
181
185
  // Return if the build encountered any errors
182
186
  if (result.errors.length) {
@@ -271,12 +275,12 @@ class BundlerContext {
271
275
  #addErrorsToWatch(result) {
272
276
  for (const error of result.errors) {
273
277
  let file = error.location?.file;
274
- if (file) {
278
+ if (file && !isInternalAngularFile(file)) {
275
279
  this.watchFiles.add((0, node_path_1.join)(this.workspaceRoot, file));
276
280
  }
277
281
  for (const note of error.notes) {
278
282
  file = note.location?.file;
279
- if (file) {
283
+ if (file && !isInternalAngularFile(file)) {
280
284
  this.watchFiles.add((0, node_path_1.join)(this.workspaceRoot, file));
281
285
  }
282
286
  }
@@ -324,3 +328,6 @@ class BundlerContext {
324
328
  }
325
329
  }
326
330
  exports.BundlerContext = BundlerContext;
331
+ function isInternalAngularFile(file) {
332
+ return file.startsWith('angular:');
333
+ }
@@ -53,7 +53,7 @@ export declare class ExecutionResult {
53
53
  success: boolean;
54
54
  outputFiles: BuildOutputFile[];
55
55
  assetFiles: BuildOutputAsset[];
56
- errors: (PartialMessage | Message)[];
56
+ errors: (Message | PartialMessage)[];
57
57
  externalMetadata: ExternalResultMetadata | undefined;
58
58
  };
59
59
  get watchFiles(): string[];
@@ -18,8 +18,8 @@ function createCachedLoad(cache, callback) {
18
18
  let result = cache.get(loadCacheKey);
19
19
  if (result === undefined) {
20
20
  result = await callback(args);
21
- // Do not cache null or undefined or results with errors
22
- if (result && result.errors === undefined) {
21
+ // Do not cache null or undefined
22
+ if (result) {
23
23
  await cache.put(loadCacheKey, result);
24
24
  }
25
25
  }
@@ -107,6 +107,7 @@ async function compileString(data, filename, options, resolver, unsafeInlineJava
107
107
  }
108
108
  catch (error) {
109
109
  if (isLessException(error)) {
110
+ const location = convertExceptionLocation(error);
110
111
  // Retry with a warning for less files requiring the deprecated inline JavaScript option
111
112
  if (error.message.includes('Inline JavaScript is not enabled.')) {
112
113
  const withJsResult = await compileString(data, filename, options, resolver,
@@ -114,7 +115,7 @@ async function compileString(data, filename, options, resolver, unsafeInlineJava
114
115
  withJsResult.warnings = [
115
116
  {
116
117
  text: 'Deprecated inline execution of JavaScript has been enabled ("javascriptEnabled")',
117
- location: convertExceptionLocation(error),
118
+ location,
118
119
  notes: [
119
120
  {
120
121
  location: null,
@@ -133,10 +134,11 @@ async function compileString(data, filename, options, resolver, unsafeInlineJava
133
134
  errors: [
134
135
  {
135
136
  text: error.message,
136
- location: convertExceptionLocation(error),
137
+ location,
137
138
  },
138
139
  ],
139
140
  loader: 'css',
141
+ watchFiles: location.file ? [filename, location.file] : [filename],
140
142
  };
141
143
  }
142
144
  throw error;
@@ -170,7 +170,7 @@ async function compileString(data, filePath, syntax, options, resolveUrl) {
170
170
  }
171
171
  catch (error) {
172
172
  if (isSassException(error)) {
173
- const file = error.span.url ? (0, node_url_1.fileURLToPath)(error.span.url) : undefined;
173
+ const fileWithError = error.span.url ? (0, node_url_1.fileURLToPath)(error.span.url) : undefined;
174
174
  return {
175
175
  loader: 'css',
176
176
  errors: [
@@ -179,7 +179,7 @@ async function compileString(data, filePath, syntax, options, resolveUrl) {
179
179
  },
180
180
  ],
181
181
  warnings,
182
- watchFiles: file ? [file] : undefined,
182
+ watchFiles: fileWithError ? [filePath, fileWithError] : [filePath],
183
183
  };
184
184
  }
185
185
  throw error;
@@ -8,4 +8,4 @@
8
8
  /**
9
9
  * Delete an output directory, but error out if it's the root of the project.
10
10
  */
11
- export declare function deleteOutputDir(root: string, outputPath: string): void;
11
+ export declare function deleteOutputDir(root: string, outputPath: string): Promise<void>;
@@ -6,41 +6,32 @@
6
6
  * Use of this source code is governed by an MIT-style license that can be
7
7
  * found in the LICENSE file at https://angular.io/license
8
8
  */
9
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- var desc = Object.getOwnPropertyDescriptor(m, k);
12
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
13
- desc = { enumerable: true, get: function() { return m[k]; } };
14
- }
15
- Object.defineProperty(o, k2, desc);
16
- }) : (function(o, m, k, k2) {
17
- if (k2 === undefined) k2 = k;
18
- o[k2] = m[k];
19
- }));
20
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
21
- Object.defineProperty(o, "default", { enumerable: true, value: v });
22
- }) : function(o, v) {
23
- o["default"] = v;
24
- });
25
- var __importStar = (this && this.__importStar) || function (mod) {
26
- if (mod && mod.__esModule) return mod;
27
- var result = {};
28
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
29
- __setModuleDefault(result, mod);
30
- return result;
31
- };
32
9
  Object.defineProperty(exports, "__esModule", { value: true });
33
10
  exports.deleteOutputDir = void 0;
34
- const fs = __importStar(require("fs"));
35
- const path_1 = require("path");
11
+ const promises_1 = require("node:fs/promises");
12
+ const node_path_1 = require("node:path");
36
13
  /**
37
14
  * Delete an output directory, but error out if it's the root of the project.
38
15
  */
39
- function deleteOutputDir(root, outputPath) {
40
- const resolvedOutputPath = (0, path_1.resolve)(root, outputPath);
16
+ async function deleteOutputDir(root, outputPath) {
17
+ const resolvedOutputPath = (0, node_path_1.resolve)(root, outputPath);
41
18
  if (resolvedOutputPath === root) {
42
19
  throw new Error('Output path MUST not be project root directory!');
43
20
  }
44
- fs.rmSync(resolvedOutputPath, { force: true, recursive: true, maxRetries: 3 });
21
+ // Avoid removing the actual directory to avoid errors in cases where the output
22
+ // directory is mounted or symlinked. Instead the contents are removed.
23
+ let entries;
24
+ try {
25
+ entries = await (0, promises_1.readdir)(resolvedOutputPath);
26
+ }
27
+ catch (error) {
28
+ if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {
29
+ return;
30
+ }
31
+ throw error;
32
+ }
33
+ for (const entry of entries) {
34
+ await (0, promises_1.rm)((0, node_path_1.join)(resolvedOutputPath, entry), { force: true, recursive: true, maxRetries: 3 });
35
+ }
45
36
  }
46
37
  exports.deleteOutputDir = deleteOutputDir;
@@ -68,11 +68,8 @@ exports.allowMinify = debugOptimize.minify;
68
68
  */
69
69
  const maxWorkersVariable = process.env['NG_BUILD_MAX_WORKERS'];
70
70
  exports.maxWorkers = isPresent(maxWorkersVariable) ? +maxWorkersVariable : 4;
71
- // Default to enabled unless inside a Web Container which currently fails when transferring MessagePort objects
72
71
  const parallelTsVariable = process.env['NG_BUILD_PARALLEL_TS'];
73
- exports.useParallelTs = isPresent(parallelTsVariable)
74
- ? !isDisabled(parallelTsVariable)
75
- : !process.versions.webcontainer;
72
+ exports.useParallelTs = !isPresent(parallelTsVariable) || !isDisabled(parallelTsVariable);
76
73
  const legacySassVariable = process.env['NG_BUILD_LEGACY_SASS'];
77
74
  exports.useLegacySass = (() => {
78
75
  if (!isPresent(legacySassVariable)) {
@@ -74,9 +74,15 @@ export async function* extractRoutes(bootstrapAppFnOrModule, document) {
74
74
  await whenStable(applicationRef);
75
75
  const injector = applicationRef.injector;
76
76
  const router = injector.get(Router);
77
- const compiler = injector.get(Compiler);
78
- // Extract all the routes from the config.
79
- yield* getRoutesFromRouterConfig(router.config, compiler, injector);
77
+ if (router.config.length === 0) {
78
+ // In case there are no routes available
79
+ yield { route: '', success: true, redirect: false };
80
+ }
81
+ else {
82
+ const compiler = injector.get(Compiler);
83
+ // Extract all the routes from the config.
84
+ yield* getRoutesFromRouterConfig(router.config, compiler, injector);
85
+ }
80
86
  }
81
87
  finally {
82
88
  platformRef.destroy();