-
Notifications
You must be signed in to change notification settings - Fork 12k
/
Copy pathstyles-webpack-plugin.ts
80 lines (68 loc) · 2.64 KB
/
styles-webpack-plugin.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
/**
* @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 assert from 'assert';
import type { Compilation, Compiler } from 'webpack';
import { assertIsError } from '../../../utils/error';
import { addError } from '../../../utils/webpack-diagnostics';
export interface StylesWebpackPluginOptions {
preserveSymlinks?: boolean;
root: string;
entryPoints: Record<string, string[]>;
}
/**
* The name of the plugin provided to Webpack when tapping Webpack compiler hooks.
*/
const PLUGIN_NAME = 'styles-webpack-plugin';
export class StylesWebpackPlugin {
private compilation: Compilation | undefined;
constructor(private readonly options: StylesWebpackPluginOptions) {}
apply(compiler: Compiler): void {
const { entryPoints, preserveSymlinks, root } = this.options;
const resolver = compiler.resolverFactory.get('global-styles', {
conditionNames: ['sass', 'less', 'style'],
mainFields: ['sass', 'less', 'style', 'main', '...'],
extensions: ['.scss', '.sass', '.less', '.css'],
restrictions: [/\.((le|sa|sc|c)ss)$/i],
preferRelative: true,
useSyncFileSystemCalls: true,
symlinks: !preserveSymlinks,
fileSystem: compiler.inputFileSystem ?? undefined,
});
const webpackOptions = compiler.options;
compiler.hooks.environment.tap(PLUGIN_NAME, () => {
const entry =
typeof webpackOptions.entry === 'function' ? webpackOptions.entry() : webpackOptions.entry;
webpackOptions.entry = async () => {
const entrypoints = await entry;
for (const [bundleName, paths] of Object.entries(entryPoints)) {
entrypoints[bundleName] ??= {};
const entryImport = (entrypoints[bundleName].import ??= []);
for (const path of paths) {
try {
const resolvedPath = resolver.resolveSync({}, root, path);
if (resolvedPath) {
entryImport.push(`${resolvedPath}?ngGlobalStyle`);
} else {
assert(this.compilation, 'Compilation cannot be undefined.');
addError(this.compilation, `Cannot resolve '${path}'.`);
}
} catch (error) {
assert(this.compilation, 'Compilation cannot be undefined.');
assertIsError(error);
addError(this.compilation, error.message);
}
}
}
return entrypoints;
};
});
compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation) => {
this.compilation = compilation;
});
}
}