背景
之前在 webpack 打包 node 遇到的问题 这篇文章里头记录了遇到的问题,我总觉得这个问题很简单,认真研究了一下 webpack
之后,觉得自己尝试一下,自己实现一下 webpack-shebang-plugin
这个插件。
开始的时候我还想用 loader
去实现,但是在 production
环境下打包,会对代码进行压缩,删除我们添加的注释,所以以我短浅的目光看来,可能用 plugin
的方式来实现更好一点
代码实现
plugins/ShebangWepbackPlugin.js
const prefix = `#! /usr/bin/env node\n`
class ChebangWepbackPlugin {
/**
* 过滤出 js 后缀的文件
* 返回:js 文件资源列表
*/
getExtensionList(compliation) {
// 只对 js 文件进行操作
const extensions = ['js']
const assetList = Object.keys(compliation.assets).filter(
(assetPath) => {
const splitted = assetPath.split('.')
const extension = splitted[splitted.length - 1]
return extensions.includes(extension)
}
)
return assetList
}
/**
* 对资源列表中的每一个资源进行处理
*/
sourceHandler(compliation, assetList) {
assetList.forEach((asset) => {
const source = compliation.assets[asset].source()
const content = prefix + source
compliation.assets[asset] = {
source() {
return content
},
size() {
return content.length
},
}
})
}
apply(complier) {
complier.hooks.emit.tap('BannerWepbackPlugin', (compliation) => {
const assetList = this.getExtensionList(compliation)
this.sourceHandler(compliation, assetList)
})
}
}
module.exports = ChebangWepbackPlugin
我这里使用的钩子函数是
emit
,如果需要其他更多的钩子函数信息可以去 webpack 官网 API 文档 查看。里头会详情说明hooks
的作用和回调
compiler 和 compilation 的区别
我们从名字上去猜,都能大致猜到他们的区别。compiler
的中文翻译是:编译器,compilation
的中文翻译是:汇编物(翻译结果来自有道)。所以 compiler
他是一个工具嘛,贯穿整个生命周期,而且只有一个。compilation
是汇编物,简单点说就是打包出来的东西,这个 compilation
在不同的生命周期里头,会有不同的打包结果,所以在不同的 hooks
里头获取的 compilation
是可能不一样的。
更多应用场景
如果你的代码需要在文件上方加入一些自定义的注释方式也是可以用这样的方式来处理的,如果需要参数的话,可以在
constructor
里头传进去就可以啦
webpack 调试方法
如果你查阅过 webpack
的文档,你会发现文档里好像并没有说 compiler
和 compilation
里头有哪些属性,但是我们自己编写 plugin
的时候,是很需要查看里头的属性和方法的,有的小伙伴可能会选择 console.log
的方法,但是由于 compiler
里头的方法和属性实在太多了,而且在控制台查看不是很直观,给大家介绍一下我们调试时候的方法
- 在
package.json
配置一个script
{
"scripts": {
"debug": "node --inspect-brk ./node_modules/webpack-cli/bin/cli.js"
}
}
- 在需要的位置上打上断点
- 在浏览器打开任意的窗口,打开调试模式,会看到
node
的icon
,点击他就会打开调试窗口啦
- compiler 信息就能看到啦