UNPKG

1.99 kBJavaScriptView Raw
1function removeJsExt(asset) {
2 return asset.replace(/\.js$/, '')
3}
4
5module.exports = class ZenJsPlugin {
6 constructor() {
7 this.entryPointFiles = []
8 }
9
10 genZenJs(compiler) {
11 // 在 emit 阶段生成无 js 后缀脚本,以确保被正确压缩
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}