forked from icelam/html-inline-script-webpack-plugin
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathHtmlInlineScriptPlugin.ts
More file actions
84 lines (68 loc) · 2.33 KB
/
HtmlInlineScriptPlugin.ts
File metadata and controls
84 lines (68 loc) · 2.33 KB
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
import { Compilation } from 'webpack';
import type { Compiler, WebpackPluginInstance } from 'webpack';
import htmlWebpackPlugin from 'html-webpack-plugin';
import type { HtmlTagObject } from 'html-webpack-plugin';
import { PLUGIN_PREFIX } from './constants';
class HtmlInlineScriptPlugin implements WebpackPluginInstance {
tests: RegExp[];
constructor(tests?: RegExp[]) {
this.tests = tests || [/.+[.]js$/];
}
isFileNeedsToBeInlined(
assetName: string
): boolean {
return this.tests.some((test) => assetName.match(test));
}
processScriptTag(
publicPath: string,
assets: Compilation['assets'],
tag: HtmlTagObject
): HtmlTagObject {
if (tag.tagName !== 'script' || !tag.attributes?.src) {
return tag;
}
const scriptName = (tag.attributes.src as string).replace(publicPath, '');
if (!this.isFileNeedsToBeInlined(scriptName)) {
return tag;
}
const asset = assets[scriptName];
if (!asset) {
return tag;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { src, ...attributesWithoutSrc } = tag.attributes;
return {
tagName: 'script',
innerHTML: asset.source() as string,
voidTag: false,
attributes: attributesWithoutSrc,
meta: { plugin: 'html-inline-script-webpack-plugin' }
};
}
apply(compiler: Compiler): void {
let publicPath = compiler.options?.output?.publicPath as string || '';
if (publicPath && !publicPath.endsWith('/')) {
publicPath += '/';
}
compiler.hooks.compilation.tap(`${PLUGIN_PREFIX}_compilation`, (compilation) => {
const hooks = htmlWebpackPlugin.getHooks(compilation);
hooks.alterAssetTags.tap(`${PLUGIN_PREFIX}_alterAssetTags`, (data) => {
data.assetTags.scripts = data.assetTags.scripts.map(
(tag: HtmlTagObject) => this.processScriptTag(publicPath, compilation.assets, tag)
);
return data;
});
compilation.hooks.processAssets.tap({
name: `${PLUGIN_PREFIX}_PROCESS_ASSETS_STAGE_SUMMARIZE`,
stage: Compilation.PROCESS_ASSETS_STAGE_SUMMARIZE
}, (assets) => {
Object.keys(assets).forEach((assetName) => {
if (this.isFileNeedsToBeInlined(assetName)) {
delete assets[assetName];
}
});
});
});
}
}
export default HtmlInlineScriptPlugin;