1 | function removeJsExt(asset) {
|
2 | return asset.replace(/\.js$/, '')
|
3 | }
|
4 |
|
5 | module.exports = class ZenJsPlugin {
|
6 | constructor() {
|
7 | this.entryPointFiles = []
|
8 | }
|
9 |
|
10 | genZenJs(compiler) {
|
11 |
|
12 | compiler.plugin('emit', (compilation, callback) => {
|
13 | this.entryPointFiles.map(chunkFile => {
|
14 | const name = removeJsExt(chunkFile)
|
15 |
|
16 | compilation.assets[name] = compilation.assets[chunkFile]
|
17 | compilation.assets[name]._fileExt = 'js'
|
18 |
|
19 | return chunkFile
|
20 | })
|
21 |
|
22 | callback()
|
23 | })
|
24 | }
|
25 |
|
26 | collectEntryPointFiles(compilation) {
|
27 | const entryNames = Object.keys(compilation.entrypoints)
|
28 |
|
29 | this.entryPointFiles = entryNames.reduce((targets, entryName) => {
|
30 | const entryPointFiles = compilation.entrypoints[entryName].getFiles()
|
31 |
|
32 | return targets.concat(
|
33 | entryPointFiles.filter(chunkFile => chunkFile.endsWith('.js'))
|
34 | )
|
35 | }, [])
|
36 |
|
37 | return this.entryPointFiles
|
38 | }
|
39 |
|
40 | addScriptTypeAttr(compiler) {
|
41 | const { publicPath } = compiler.options.output
|
42 |
|
43 | compiler.plugin('compilation', compilation => {
|
44 | compilation.plugin(
|
45 | 'html-webpack-plugin-alter-asset-tags',
|
46 | (assetTags, callback) => {
|
47 | const entryPointFiles = this.collectEntryPointFiles(compilation)
|
48 | const isEntryScript = asset => {
|
49 | if (asset.tagName !== 'script') return false
|
50 |
|
51 | return entryPointFiles.find(
|
52 | f => publicPath + f === asset.attributes.src
|
53 | )
|
54 | }
|
55 |
|
56 | assetTags.head
|
57 | .concat(assetTags.body)
|
58 | .filter(isEntryScript)
|
59 | .forEach(script => {
|
60 | script.attributes = {
|
61 | type: 'text/javascript',
|
62 | src: removeJsExt(script.attributes.src)
|
63 | }
|
64 | })
|
65 |
|
66 | callback(null, assetTags)
|
67 | }
|
68 | )
|
69 | })
|
70 | }
|
71 |
|
72 | apply(compiler) {
|
73 | this.genZenJs(compiler)
|
74 | this.addScriptTypeAttr(compiler)
|
75 | }
|
76 | }
|