創(chuàng)建插件
webpack 插件由以下組成:
- 一個 JavaScript 命名函數(shù)。
- 在插件函數(shù)的 prototype 上定義一個 apply 方法。
- 指定一個綁定到 webpack 自身的事件鉤子宋欺。
- 處理 webpack 內(nèi)部實例的特定數(shù)據(jù)胸墙。
- 功能完成后調(diào)用 webpack 提供的回調(diào)寸痢。
// 一個 JavaScript 命名函數(shù)囊榜。
function MyWebpackPlugin() {
};
// 在插件函數(shù)的 prototype 上定義一個 `apply` 方法。
MyWebpackPlugin.prototype.apply = function(compiler) {
// 指定一個掛載到 webpack 自身的事件鉤子尼变。
compiler.plugin('webpacksEventHook', function(compilation /* 處理 webpack 內(nèi)部實例的特定數(shù)據(jù)利凑。*/, callback) {
console.log("This is an example plugin!!!");
// 功能完成后調(diào)用 webpack 提供的回調(diào)。
callback();
});
};
Compiler 和 Compilation
Compiler 和 Compilation 是插件開發(fā)中最重要的兩個資源
Compiler 對象代表了完整的 webpack 環(huán)境配置嫌术。這個對象在啟動 webpack 時被一次性建立哀澈,并配置好所有可操作的設(shè)置,包括 options度气,loader 和 plugin割按。當在 webpack 環(huán)境中應(yīng)用一個插件時,插件將收到此 compiler 對象的引用磷籍∈嗜伲可以使用它來訪問 webpack 的主環(huán)境。
compilation 對象代表了一次資源版本構(gòu)建院领。當運行 webpack 開發(fā)環(huán)境中間件時弛矛,每當檢測到一個文件變化,就會創(chuàng)建一個新的 compilation比然,從而生成一組新的編譯資源丈氓。一個 compilation 對象表現(xiàn)了當前的模塊資源、編譯生成資源、變化的文件万俗、以及被跟蹤依賴的狀態(tài)信息鱼鼓。compilation 對象也提供了很多關(guān)鍵時機的回調(diào),以供插件做自定義處理時選擇使用该编。
編寫一個基礎(chǔ)插件
- 插件是由「具有 apply 方法的 prototype 對象」所實例化出來的。這個 apply 方法在安裝插件時硕淑,會被 webpack compiler 調(diào)用一次课竣。apply 方法可以接收一個 webpack compiler 對象的引用,從而可以在回調(diào)函數(shù)中訪問到 compiler 對象.
module.exports = class MyPlugin {
constructor(options) {
this.options = options
}
apply(compiler) {
// 這里會打印在 調(diào)用此插件傳遞的參數(shù)
console.log('options', this.options)
}
}
- 安裝插件 在 webpack.config 配置 plugins
const path = require('path')
const MyPlugin = require('./plugins/plugin-demo')
module.exports = {
entry: './src/index.js',
output: {
path: path.join(__dirname, 'dist'),
filename: 'main.js'
},
mode: 'production',
plugins: [
new MyPlugin({
name: 'webpack'
})
]
}
編寫一個壓縮構(gòu)建資源為 zip 包的插件
- 安裝相關(guān)依賴
npm i jszip webpack-sources
- 代碼
const JSZip = require('jszip')
const path = require('path')
const RawSource = require('webpack-sources').RawSource
const zip = new JSZip
module.exports = class ZipPLugin {
constructor(options) {
this.options = options
}
apply(compiler) {
console.log('compiler', this.options)
compiler.hooks.emit.tapAsync('ZipPlugin', (compilation, callback) => {
// 創(chuàng)建一個目錄
const folder = zip.folder(this.options.filename)
for(let filename in compilation.assets) {
// 獲取 source 也就是文件的內(nèi)容
const source = compilation.assets[filename].source()
// 把內(nèi)容添加到文件中
folder.file(filename, source)
}
zip.generateAsync({
type: 'nodebuffer'
}).then((content) => {
// 獲取文件路徑地址
const outPutPath = path.join(compilation.options.output.path, this.options.filename + '.zip')
// 文件路徑的絕對定位改成相對定位置媳,
const outPutRelativePath = path.relative(
compilation.options.output.path,
outPutPath
)
compilation.assets[outPutRelativePath] = new RawSource(content)
callback()
})
})
}
}