持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第30天,点击查看活动详情
前言
上一篇文章讲了如何写一个webpack的loader,这篇文章讲一下如何写一个wepback插件。
因为我们项目经常要更新,但是我们客户他们经常都忘记刷新页面,导致有些问题我已经修改了,并更新到线上了,但是由于他们忘记刷新,导致他们访问的还是旧内容。
为了避免这种情况,写一个webpack插件,实现判断页面是否需要刷新。
webpack插件
webpack插件可以理解为在打包过程中,会执行不同的hook钩子,你可以在你需要的hook钩子写上你的逻辑。
我讲下我这个webpack插件的实现逻辑:
第一种实现:
每次打包都读取package.json的version字段,然后给它加一,然后生成一个文件version.txt,里面就是加一后的版本。然后也要更新package.json的version字段,下次打包在这个基础上加一
每次聚焦页面都请求这个txt文件,和上次的package.json的version对比,如果一样就证明没有更新,如果不一样就代表有更新,提示要刷新页面。
还有第二种实现:
因为第一种方式打包都要更新package.json的version字段,然后我的打包是gitlab ci/cd 自动化打包,无法做到自动提交package.json文件到gitlab。
所以我采用时间戳的方式。
每次打包生成新的时间戳,存到version.txt文件中。然后把这个新的时间戳存到js文件里。
每次聚焦页面,就取version.txt的时间戳和js文件的时间戳对比,如果不一致,则代码有更新,需要刷新,否则就是没有更新。
webpack插件编写
需要一个类(你也可以提供一个函数)
内部要有个apply方法,参数是compiler对象。它包括了当前的wepack的配置的信息,包活hook的钩子,outputPath,options等等
例子:
const fs = require('fs')
class version {
apply (compiler) {
compiler.hooks.done.tap('version', () => {
const output = compiler.outputPath
console.log('outeput', output)
fs.writeFileSync(output + '/version.txt', +new Date())
})
}
}
module.exports = version
上面的就是使用了done这个hook钩子,会在打包后执行。
使用格式compiler.hooks.hooksName.tap(pluginName, () => {})
hooksName也就是hook的名字,pluginName就是wepback插件的名称,自定义。
webpack的hook有很多hook,还有beforeRun,在打包之前执行,适合设置多入口打包等等。
可以去compiler 钩子 查看所有的钩子合集。
一般是使用tap方法,但是如果内部是异步的,可以使用tapAsync和tapPromise。
注意, 以前语法是使用compiler.plugin(hookName, (compilation) => {}),现在已经废弃了。
compiler.hooks.beforeRun.tap('version', (compilation) => {
console.log('compilation', compilation.hooks)
})
另外hook钩子回调函数的参数会有个compilation对象,它和compiler对象类似,也是有很多hook钩子,地址。
compiler对象会贯穿整个打包周期,只要没有重新build,compiler对象都是同一个。
而compilation对象是针对当前编译的对象,比如webpack --watch,只要监听文件变化,hook钩子会重新执行,compilation对象就会重新生成。
插件的注册使用
在weback.config.js里面
const Version = require('./plugins/version')
module.exports = {
entry: './main.js',
plugins: [
new Version()
]
}
在vue.config.js里面
module.exports = {
chainWebpack: config => {
config.plugin('version').use(require('../plugins/version'))
}
}