因为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
版本
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
的编写