@angular-devkit/build-angular 17.0.0-rc.3 → 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.
@@ -6,16 +6,24 @@
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 __importDefault = (this && this.__importDefault) || function (mod) {
10
+ return (mod && mod.__esModule) ? mod : { "default": mod };
11
+ };
9
12
  Object.defineProperty(exports, "__esModule", { value: true });
10
13
  exports.load = exports.resolve = exports.initialize = void 0;
14
+ const node_assert_1 = __importDefault(require("node:assert"));
15
+ const node_crypto_1 = require("node:crypto");
11
16
  const node_path_1 = require("node:path");
12
17
  const node_url_1 = require("node:url");
13
18
  const url_1 = require("url");
14
19
  const javascript_transformer_1 = require("../../../tools/esbuild/javascript-transformer");
15
20
  const node_18_utils_1 = require("./node-18-utils");
16
- const TRANSFORMED_FILES = {};
17
- const CHUNKS_REGEXP = /file:\/\/\/(main\.server|chunk-\w+)\.mjs/;
18
- let workspaceRootFile;
21
+ /**
22
+ * Node.js ESM loader to redirect imports to in memory files.
23
+ * @see: https://nodejs.org/api/esm.html#loaders for more information about loaders.
24
+ */
25
+ const MEMORY_URL_SCHEME = 'memory://';
26
+ let memoryVirtualRootUrl;
19
27
  let outputFiles;
20
28
  const javascriptTransformer = new javascript_transformer_1.JavaScriptTransformer(
21
29
  // Always enable JIT linking to support applications built with and without AOT.
@@ -24,45 +32,89 @@ const javascriptTransformer = new javascript_transformer_1.JavaScriptTransformer
24
32
  { sourcemap: true, jit: true }, 1);
25
33
  (0, node_18_utils_1.callInitializeIfNeeded)(initialize);
26
34
  function initialize(data) {
27
- workspaceRootFile = (0, node_url_1.pathToFileURL)((0, node_path_1.join)(data.workspaceRoot, 'index.mjs')).href;
35
+ // This path does not actually exist but is used to overlay the in memory files with the
36
+ // actual filesystem for resolution purposes.
37
+ // A custom URL schema (such as `memory://`) cannot be used for the resolve output because
38
+ // the in-memory files may use `import.meta.url` in ways that assume a file URL.
39
+ // `createRequire` is one example of this usage.
40
+ memoryVirtualRootUrl = (0, node_url_1.pathToFileURL)((0, node_path_1.join)(data.workspaceRoot, `.angular/prerender-root/${(0, node_crypto_1.randomUUID)()}/`)).href;
28
41
  outputFiles = data.outputFiles;
29
42
  }
30
43
  exports.initialize = initialize;
31
44
  function resolve(specifier, context, nextResolve) {
32
- if (!isFileProtocol(specifier)) {
33
- const normalizedSpecifier = specifier.replace(/^\.\//, '');
34
- if (normalizedSpecifier in outputFiles) {
45
+ // In-memory files loaded from external code will contain a memory scheme
46
+ if (specifier.startsWith(MEMORY_URL_SCHEME)) {
47
+ let memoryUrl;
48
+ try {
49
+ memoryUrl = new URL(specifier);
50
+ }
51
+ catch {
52
+ node_assert_1.default.fail('External code attempted to use malformed memory scheme: ' + specifier);
53
+ }
54
+ // Resolve with a URL based from the virtual filesystem root
55
+ return {
56
+ format: 'module',
57
+ shortCircuit: true,
58
+ url: new URL(memoryUrl.pathname.slice(1), memoryVirtualRootUrl).href,
59
+ };
60
+ }
61
+ // Use next/default resolve if the parent is not from the virtual root
62
+ if (!context.parentURL?.startsWith(memoryVirtualRootUrl)) {
63
+ return nextResolve(specifier, context);
64
+ }
65
+ // Check for `./` and `../` relative specifiers
66
+ const isRelative = specifier[0] === '.' &&
67
+ (specifier[1] === '/' || (specifier[1] === '.' && specifier[2] === '/'));
68
+ // Relative specifiers from memory file should be based from the parent memory location
69
+ if (isRelative) {
70
+ let specifierUrl;
71
+ try {
72
+ specifierUrl = new URL(specifier, context.parentURL);
73
+ }
74
+ catch { }
75
+ if (specifierUrl?.pathname &&
76
+ Object.hasOwn(outputFiles, specifierUrl.href.slice(memoryVirtualRootUrl.length))) {
35
77
  return {
36
78
  format: 'module',
37
79
  shortCircuit: true,
38
- // File URLs need to absolute. In Windows these also need to include the drive.
39
- // The `/` will be resolved to the drive letter.
40
- url: (0, node_url_1.pathToFileURL)('/' + normalizedSpecifier).href,
80
+ url: specifierUrl.href,
41
81
  };
42
82
  }
83
+ node_assert_1.default.fail(`In-memory ESM relative file should always exist: '${context.parentURL}' --> '${specifier}'`);
43
84
  }
85
+ // Update the parent URL to allow for module resolution for the workspace.
86
+ // This handles bare specifiers (npm packages) and absolute paths.
44
87
  // Defer to the next hook in the chain, which would be the
45
88
  // Node.js default resolve if this is the last user-specified loader.
46
- return nextResolve(specifier, isBundleEntryPointOrChunk(context) ? { ...context, parentURL: workspaceRootFile } : context);
89
+ return nextResolve(specifier, {
90
+ ...context,
91
+ parentURL: new URL('index.js', memoryVirtualRootUrl).href,
92
+ });
47
93
  }
48
94
  exports.resolve = resolve;
49
95
  async function load(url, context, nextLoad) {
50
96
  const { format } = context;
51
- // CommonJs modules require no transformations and are not in memory.
52
- if (format !== 'commonjs' && isFileProtocol(url)) {
97
+ // Load the file from memory if the URL is based in the virtual root
98
+ if (url.startsWith(memoryVirtualRootUrl)) {
99
+ const source = outputFiles[url.slice(memoryVirtualRootUrl.length)];
100
+ (0, node_assert_1.default)(source !== undefined, 'Resolved in-memory ESM file should always exist: ' + url);
101
+ // In-memory files have already been transformer during bundling and can be returned directly
102
+ return {
103
+ format,
104
+ shortCircuit: true,
105
+ source,
106
+ };
107
+ }
108
+ // Only module files potentially require transformation. Angular libraries that would
109
+ // need linking are ESM only.
110
+ if (format === 'module' && isFileProtocol(url)) {
53
111
  const filePath = (0, url_1.fileURLToPath)(url);
54
- // Remove '/' or drive letter for Windows that was added in the above 'resolve'.
55
- let source = outputFiles[(0, node_path_1.relative)('/', filePath)] ?? TRANSFORMED_FILES[filePath];
56
- if (source === undefined) {
57
- source = TRANSFORMED_FILES[filePath] = Buffer.from(await javascriptTransformer.transformFile(filePath)).toString('utf-8');
58
- }
59
- if (source !== undefined) {
60
- return {
61
- format,
62
- shortCircuit: true,
63
- source,
64
- };
65
- }
112
+ const source = await javascriptTransformer.transformFile(filePath);
113
+ return {
114
+ format,
115
+ shortCircuit: true,
116
+ source,
117
+ };
66
118
  }
67
119
  // Let Node.js handle all other URLs.
68
120
  return nextLoad(url);
@@ -74,9 +126,6 @@ function isFileProtocol(url) {
74
126
  function handleProcessExit() {
75
127
  void javascriptTransformer.close();
76
128
  }
77
- function isBundleEntryPointOrChunk(context) {
78
- return !!context.parentURL && CHUNKS_REGEXP.test(context.parentURL);
79
- }
80
129
  process.once('exit', handleProcessExit);
81
130
  process.once('SIGINT', handleProcessExit);
82
131
  process.once('uncaughtException', handleProcessExit);
@@ -8,6 +8,7 @@
8
8
  */
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
10
  const node_worker_threads_1 = require("node:worker_threads");
11
+ const load_esm_1 = require("../load-esm");
11
12
  const fetch_patch_1 = require("./fetch-patch");
12
13
  const render_page_1 = require("./render-page");
13
14
  /**
@@ -15,12 +16,13 @@ const render_page_1 = require("./render-page");
15
16
  */
16
17
  const { outputFiles, document, inlineCriticalCss } = node_worker_threads_1.workerData;
17
18
  /** Renders an application based on a provided options. */
18
- async function render(options) {
19
+ function render(options) {
19
20
  return (0, render_page_1.renderPage)({
20
21
  ...options,
21
22
  outputFiles,
22
23
  document,
23
24
  inlineCriticalCss,
25
+ loadBundle: async (path) => await (0, load_esm_1.loadEsmModule)(new URL(path, 'memory://')),
24
26
  });
25
27
  }
26
28
  function initialize() {
@@ -16,8 +16,8 @@ const fetch_patch_1 = require("./fetch-patch");
16
16
  const { document, verbose } = node_worker_threads_1.workerData;
17
17
  /** Renders an application based on a provided options. */
18
18
  async function extractRoutes() {
19
- const { extractRoutes } = await (0, load_esm_1.loadEsmModule)('./render-utils.server.mjs');
20
- const { default: bootstrapAppFnOrModule } = await (0, load_esm_1.loadEsmModule)('./main.server.mjs');
19
+ const { extractRoutes } = await (0, load_esm_1.loadEsmModule)(new URL('./render-utils.server.mjs', 'memory://'));
20
+ const { default: bootstrapAppFnOrModule } = await (0, load_esm_1.loadEsmModule)(new URL('./main.server.mjs', 'memory://'));
21
21
  const skippedRedirects = [];
22
22
  const skippedOthers = [];
23
23
  const routes = [];