forked from angular/angular-cli
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathutils.ts
104 lines (92 loc) · 3.49 KB
/
utils.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
import { existsSync } from 'node:fs';
import * as path from 'node:path';
import { URL, pathToFileURL } from 'node:url';
import { Compilation, Configuration } from 'webpack';
export interface EmittedFiles {
id?: string;
name?: string;
file: string;
initial: boolean;
asset?: boolean;
extension: string;
}
export function getEmittedFiles(compilation: Compilation): EmittedFiles[] {
const files: EmittedFiles[] = [];
const chunkFileNames = new Set<string>();
// adds all chunks to the list of emitted files such as lazy loaded modules
for (const chunk of compilation.chunks) {
for (const file of chunk.files) {
if (chunkFileNames.has(file)) {
continue;
}
chunkFileNames.add(file);
files.push({
id: chunk.id?.toString(),
name: chunk.name ?? undefined,
file,
extension: path.extname(file),
initial: chunk.isOnlyInitial(),
});
}
}
// add all other files
for (const file of Object.keys(compilation.assets)) {
// Chunk files have already been added to the files list above
if (chunkFileNames.has(file)) {
continue;
}
files.push({ file, extension: path.extname(file), initial: false, asset: true });
}
return files;
}
/**
* This uses a dynamic import to load a module which may be ESM.
* CommonJS code can load ESM code via a dynamic import. Unfortunately, TypeScript
* will currently, unconditionally downlevel dynamic import into a require call.
* require calls cannot load ESM code and will result in a runtime error. To workaround
* this, a Function constructor is used to prevent TypeScript from changing the dynamic import.
* Once TypeScript provides support for keeping the dynamic import this workaround can
* be dropped.
*
* @param modulePath The path of the module to load.
* @returns A Promise that resolves to the dynamically imported module.
*/
function loadEsmModule<T>(modulePath: string | URL): Promise<T> {
return new Function('modulePath', `return import(modulePath);`)(modulePath) as Promise<T>;
}
export async function getWebpackConfig(configPath: string): Promise<Configuration> {
if (!existsSync(configPath)) {
throw new Error(`Webpack configuration file ${configPath} does not exist.`);
}
switch (path.extname(configPath)) {
case '.mjs':
// Load the ESM configuration file using the TypeScript dynamic import workaround.
// Once TypeScript provides support for keeping the dynamic import this workaround can be
// changed to a direct dynamic import.
return (await loadEsmModule<{ default: Configuration }>(pathToFileURL(configPath))).default;
case '.cjs':
return require(configPath);
default:
// The file could be either CommonJS or ESM.
// CommonJS is tried first then ESM if loading fails.
try {
return require(configPath);
} catch (e) {
if ((e as NodeJS.ErrnoException).code === 'ERR_REQUIRE_ESM') {
// Load the ESM configuration file using the TypeScript dynamic import workaround.
// Once TypeScript provides support for keeping the dynamic import this workaround can be
// changed to a direct dynamic import.
return (await loadEsmModule<{ default: Configuration }>(pathToFileURL(configPath)))
.default;
}
throw e;
}
}
}