Loader
因爲webpack
只識別js
文件,遇到非js
文件,需要利用loader
處理
我們開發常用的loader:諸如:babel-loader
url-loader
style-loader
css-loader
postcss-loader
等等
今天,我們手寫一個簡單的loader
,用來寫入我們要編譯的源代碼
開始的搭建項目步驟我們就不多說了,這裏我們用到webpack 4.X
版本,要搭配webpack-cli
來使用
npm init
npm i webpack webpack-cli -D
npm i cross-env -D — 配置跨平臺環境變量
package.json
{
"name": "webpack_test",
"version": "1.0.0",
"description": "webpack_test",
"main": "index.js",
"scripts": {
"start": "cross-env NODE_TYPE=development webpack --progress --colors --config webpack.config.js --mode=development",
"build": "cross-env NODE_TYPE=production webpack -p --progress --colors --config webpack.config.js --mode=production"
},
"keywords": [
"webpack"
],
"author": "[email protected]",
"license": "MIT",
"devDependencies": {
"cross-env": "^7.0.2",
"webpack": "^4.43.0",
"webpack-cli": "^3.3.12"
}
}
接下來,我們進入正題:
index.js
源代碼
export default function () {
console.log('init')
}
webpack.config.js
配置
const path = require('path')
module.exports = {
entry: path.resolve(__dirname, 'src/index.js'),
output: {
filename: "js/[name].[hash:8].js",
path:path.resolve(__dirname,'build'),
},
module: {
rules: [
{
test: /\.(js)$/,
use: {
loader: path.resolve(__dirname, './loader/write-stream-loader.js'),
options: {
name: ''
}
}
}
]
},
}
這裏,我們新建一個loader
文件夾,用來存放我們自定義loader
loader/write-stream-loader.js
const loaderUtils = require('loader-utils') // 引入loader提供的util工具插件
const fs = require('fs') // 引入fs文件系統
module.exports = function (source) {
console.log(source)
// 獲取options參數,object類型
let option = loaderUtils.getOptions(this)
console.log(option)
// 創建寫入流
let writeaStream = fs.createWriteStream('result.txt')
// 寫入源代碼
writeStream.write(source,'UTF-8')
// 標記結束
writeStream.end()
// 寫入完成回調
writeStream.on('finish', () => {
console.log()
console.log('寫入完成')
})
return source
}
接下來,我們執行webpack
編譯,執行npm run build
開始打包
…building for production
…
可以看到,源代碼
和options
參數打印出來了,並且寫入成功了
我們進入result.txt
文件中,可以看到源代碼
寫入成功了
至此,我們就完成了自定義loader
的編寫,這裏要注意,我們用到了webpack 4.X
版本
Plugins
webpack
中的plugins
也是webpack
的核心內容之一,作爲hook
函數,是爲了在編譯打包過程中發揮自身應有的作用
看過源碼同學大概有一個基本的認知,他是一個class
構造函數,通過原型的apply
方法執行。最後生成實例繼承Tapable
。其compiler
對象是plugins
的心臟,暴露其生命週期hook
函數
因爲我們想通過plugin
,在生成資源前導出一個說明文檔,所以我們這裏用到emit
生命週期函數
plugins/set-readme-webpack-plugin.js
class SetReadmeWebpackPlugin {
constructor(options) {
this.name = options.name || 'hello world'
}
apply(compiler) {
compiler.hooks.emit.tap('SetReadmeWebpackPlugin', compilation => {
compilation.assets['readme.txt'] = {
source: () => this.name,
size: () => 20
}
})
}
}
module.exports = SetReadmeWebpackPlugin
我們在webpack
中使用
webpack.config.js
const path = require('path')
const SetReadmeWebpackPlugin = require('./plugins/set-readme-webpack-plugin')
module.exports = {
entry: path.resolve(__dirname, 'src/index.js'),
output: {
filename: "js/[name].[hash:8].js",
path: path.resolve(__dirname, 'build'),
},
plugins: [
new SetReadmeWebpackPlugin({
name: 'readme'
})
]
}
接下來,我們執行npm run build
,我們通過控制檯可以看到options
輸出,並且創建了readme.txt
文檔
至此,我們完成了自定義plugins
的編寫