原文地址
编写 loader 和 plugins
github
一、loader
1.loader 介绍
loader 是什么
loader 作用
- loader 的执行是有顺序的,
支持链式的调用
。loader的执行顺序是从下到上,从右到左。比如处理样式类的文件,use:['style-loader', 'css-loader']
。css-loader
处理后的文件返回给style-loader
。 - 一个 Loader 的职责是单一的,只需要完成一种转换。
- Webpack 会默认缓存所有 Loader 的处理结果,对没有修改的 loader 不会重新加载,关闭webpack 的默认缓存结果需要添加
this.cacheable(false);
常见的loader
- 样式类的 loader:
css-loader, style-loader, less-loader, postcss-loader(添加-webkit)
等 - 文件类的 loader:
url-loader, file-loader, raw-loader
等。 - 编译类的 loader:
babel-loader, ts-loader
等 - 校验测试类 loader:
eslint-loader, jslint-loader
等
4. loader 的三种使用方式
在
webpack.config.js
中配置module.exports = { module:{ rules:[{ test:/\.css$/, use:['css-loader'], // use:{loader:'css-loader',options:{}} } ] } }
通过命令行的参数方式
webpack --module-bind 'css=css-loader'
通过内联使用
import txt from 'css-loader!./file.css';
2. 编写一个 loader
// 在 ./loader/replaceLoader.js 创建一个替换字符串的 loader
module.exports = function(source) {
return source.replace('a', 'b')
}
// 在webpack.config.js 使用 自己写的loader
module.exports = {
module:{
rules:[{
test:"/\.js$/",
use:[{
loader: path.resolve(__dirname, './loader/replaceLoader.js')
options:{
name: '林一一'
}
}
]
}]
}
}
// 或者使用 replaceLoader
module.exports={
resolveLoader:['node_modules', './loader']
module:{
rules:[{
test:"/\.js$/",
use:['resolveLoader']
}]
}
}
loader 还可以接收
options
传入的参数,详情查看 loader API,也可以使用官方提供的loader-util
接收参数const loaderUtil = require('loader-utils') module.exports = function(source) { console.log(this.query.name) // 林一一 const options = loaderUtil.getOptions(this) return source.replace('a', 'b') }
异步:loader 是一个函数自然有同步和异步的区分。使用异步的loader需要添加
this.async()
申明异步操作const loaderUtils = require('loader-utils') module.exports = function(source) { const options = loaderUtils.getOptions(this) const callback = this.async() setTimeout(()=>{ console.log(options.name) let res = source.replace('a', options.name) callback(null, res, sourceMaps, ast) }, 4000) }
- 默认情况下 webpack 给 loader 传递的字符串编码是
utf-8
,如果需要处理二进制的文件需要添加exports.raw = true
。 - 上面提到过 webpack 会默认将
loader
的加载结果缓存如果需要关闭webpack
的缓存结果需要添加this.cacheable(false);
。 Npm link
专门用于开发和调试本地 Npm 模块,在没有发布到 npm 上面也可以在调式本地的loader
。具体需要在package.json
中配置本地loader
,在根目录下执行npm link loader-name
就可以在node_modules
中使用本地的loader
了。同时也可以采用上面的resolveLoader
实现导入loader
的方式
总结编写 loader 的思路
二、webpack 的构建流程
初始化参数
。从配置文件和shell
语句中合并的参数开始编译
。将上一步得到的参数初始化成complier对象
,加载所有的导入插件,执行对象的 run 方法开始执行编译;确定入口
。从配置的entry
入口找出所有的入口文件。编译模块
。根据入口文件的依赖,调用所有配置的loader
进行转换。完成模块编译并输出
。根据入口文件之间的依赖关系,形成一个个代码块chunk
。输出完成
。将形成的代码块chunk
输出到文件系统。
三、plugin
1 plugin 介绍
plugin 是什么
plugin 作用
常见的 plugin
html-webpack-plugin
会在打包后自动生成一个html
文件,并且会将打包后的 js 文件引入到html
文件内。optimize-css-assets-webpack-plugin
对CSS 代码进行压缩。mini-css-extract-plugin
。将写入style
标签内的 css 抽离成一个 用link
导入 生成的 CSS 文件webpack-parallel-uglify-plugin
。开启多进程执行代码压缩,提高打包的速度。clean-webpack-plugin
。每次打包前都将旧生成的文件删除。serviceworker-webpack-plugin
。为网页应用增加离线缓存功能。
plugin 的使用方式
const ServiceworkerWebpackPlugin = require('serviceworker-webpack-plugin')
module.exports = {
plugins:[
new ServiceworkerWebpackPlugin(),
]
}
2 编写一个 plugin
class MyPlugin {
constructor(params){
console.log(params)
}
// webpack 初始化参数后会调用这个引用函数,闯入初始化的 complier对象。
apply(complier){
// 绑定钩子事件
// complier.hooks.emit.tapAsync()
compiler.plugin('emit', compilation => {
console.log('MyPlugin')
))
}
}
module.export = MyPlugin