前面我們編寫了一個Loader ,這裏我們試下編寫一個簡單的plugin。
那麼Loader 與 Plugin,他們有什麼區別呢。
我們在源代碼中引入js 或其他格式文件時,我們可以通過Loader 去處理這些文件,也就是Loader 幫助我們處理模塊。而Plugin 是在我們打包的時候,在某些特定時刻上插件會被調用。比如說,當打包結束希望自動生成html 文件,這時可以使用htmlWebpackPlugin 插件;再比如,在打包之前,希望把dist 目錄清空,那我們可以使用cleanWebpackPlugin...
下面我們來編寫一個簡單的webpack plugin。
對於webpack 插件來說,他的核心機制事件驅動的模式或者說發佈訂閱設計模式。代碼的執行是通過事件來驅動的。
那我們也是新建一個項目 plugin ,然後npm init -y 來初始化。
然後我們在項目根目錄下新建目錄src, src 下新建文件index.js , 輸入一個console語句
console.log('hello')
然後,我們在項目中安裝webpack, webpack-cli
npm install webpack webpack-cli --save-dev
然後,我們配置一下webpack.config.js 如下。
const path = require('path')
module.exports = {
mode: 'development',
entry: {
main: './src/index.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js'
}
}
然後配置一下package.json 的script 如下。
"scripts": {
"build": "webpack"
},
然後,先打包一下,看看是否配全了。
接下來,我們將做一件事,當打包結束的時候,在dist 目錄下生成一個版權文件,裏面保存版權信息。
那麼,我們在項目跟目錄下創建目錄 plugins,裏面新建一個文件copyright-webpack-plugin.js
然後,插件是一個 class (Loader 是一個函數,雖然本質上class 是函數的語法糖,但class 上還是有些不同的內部功能)。當調用插件的時候,會執行這個類的apply 方法,apply 方法會接收一個參數 compiler ,它是一個webpack 的實例。下面,我們把大致的格式寫好了。
class CopyrightWebpackPlugin {
constructor () {
}
apply (compiler) {
}
}
module.exports = CopyrightWebpackPlugin
然後,在webpack.config.js 中去把插件引入並配置上,如下。
const path = require('path')
const CopyRightWebpackPlugin = require('./plugins/copyright-webpack-plugin')
module.exports = {
mode: 'development',
entry: {
main: './src/index.js'
},
plugins: [
new CopyRightWebpackPlugin()
],
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js'
}
}
當然,如果想往插件中傳入參數,在使用new 調用插件的時候,傳入(通過對象)即可,在插件的constructor 中正常接收即可。
回到我們的問題,希望在打包結束時,在dist 下生成一個文件,那麼我們就要使用到插件中的appply 函數。apply 接收的compiler 是一個webpack 的實例,我們先翻翻官網 webpack documentation > API > compiler hooks
我們可以找到emit 的hook (注意他是 AsyncSeriesHook 即異步的鉤子)
這就是我們要的鉤子,如下
class CopyrightWebpackPlugin {
apply (compiler) {
compiler.hooks.emit.tapAsync('CopyrightWebpackPlugin', (compilation, cb) => {
console.log(123)
cb()
})
}
}
module.exports = CopyrightWebpackPlugin
下面,我們要在打包結束時生成一個文件,在compilation 中存放了這次打包的所有內容,我們查看一下compilation.assets 如下。
class CopyrightWebpackPlugin {
apply (compiler) {
compiler.hooks.emit.tapAsync('CopyrightWebpackPlugin', (compilation, cb) => {
console.log(compilation.assets)
cb()
})
}
}
module.exports = CopyrightWebpackPlugin
下面,我們更改下代碼
class CopyrightWebpackPlugin {
apply (compiler) {
compiler.hooks.emit.tapAsync('CopyrightWebpackPlugin', (compilation, cb) => {
compilation.assets['copyright.txt'] = {
source: function () {
return 'copyright by y'
},
size: function () {
return 14
}
}
cb()
})
}
}
module.exports = CopyrightWebpackPlugin
然後打包,就會發現,打包結束後多了一個我們要的文件。
上面emit hooks 是異步的,如果我們想用的hooks 是同步的話,應該向下面這樣使用。比如compile hook。如下。
class CopyrightWebpackPlugin {
apply (compiler) {
compiler.hooks.compile.tap('CopyrightWebpackPlugin', (compilation) => {
console.log('compile')
})
compiler.hooks.emit.tapAsync('CopyrightWebpackPlugin', (compilation, cb) => {
compilation.assets['copyright.txt'] = {
source: function () {
return 'copyright by y'
},
size: function () {
return 14
}
}
cb()
})
}
}
module.exports = CopyrightWebpackPlugin
如果我們想要debug 我們的插件的話,可以使用node 運行webpack ,如下。
先在package.json 中配置script 如下。(__inspect 表示node 運行時進入調試模式,__inspect_brk 表示在執行時在第一行打斷點)
"scripts": {
"debug": "node --inspect --inspect-brk node_modules/webpack/bin/webpack.js",
"build": "webpack"
},
然後我們運行命令 npm run debug ,即可看到
然後,我們可以打開chrome 瀏覽器。控制檯上會有這個綠色六邊形,點開。就會自動跳轉到調試的頁面。
Done.