这是我参与「第五届青训营 」伴学笔记创作活动的第 7 天
理解Loader
问题:Webpack只认JS
为处理非标准JS 资源,设计出资源翻译模块
↓
loader
↓
用于将资源翻译为标准JS
使用Loader
- 按照Loader
npm add -D css-loader style-loader less-loader
- 添加module处理CSS文件
module.exports = {
modules: {
rules: [
{
test: /\.less$/i,
use: [
"style-loader",
"css-loader",
"less-loader",
],
},
],
},
},
认识Loader: 链式调用
从前面的示例里面可以得到,我们用到了三个loader,分别是style-loader、css-loader、less-loader。
三个loader的职责
- css-loader:将css包装成类型module.exports = "${css}" 的内容,包装后的内容符合JS的语法。
- style-loader:将css模块包进require语句,并在运行时调用rejectStyle等函数将内容注入到页面的style标签。
- less-loader:实现less->css的转换
认识Loader: 其他特性
特点
- 链式执行
- 支持异步执行
- 分normal、pitch两种模式
注:不是重点,不重要。pitch阶段,如果任何一个loader的pitch阶段有返回值的话,就会停止执行后面的阶段。通过这一特性,经常用来做一些catch,catch loader就是根据这一特性写的。
编写Loader
src/index.js
console.log('hello xiaochengzi');
loaders/loader.js书写loader代码
module.exports = function(source) {
// 这里不能用箭头函数
// source 为 loader 的输入
// 可能是文件内容,也可能是上一个 loader 处理的结果
return source.replace('xiaochengzi', this.query.name);
}
在webpack.config.js中做 loader 的使用配置
const path = require('path');
module.exports = {
mode: 'development',
entry: {
main: './src/index.js'
},
module: {
rules: [{
test: /.js/,
use: [
{
loader: path.resolve(__dirname, './loaders/loader.js'),
options: {
name: 'world' // 传递给loader的参数
}
}
] // 使用自己写的loader模块
}]
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dist')
}
}
常见Loader
掌握这些常用的 Loader 的功能、配置方法。
理解插件
插件是什么?
为什么设计插件?
原因
- 如果不用插件,当新人参加到项目中来,需要了解现有的整个流程细节,时间成本成本高,产出低;
- 如果不用插件,功能迭代成本高,牵一发而动全身;
- 如果不用插件,对于开源项目,功能僵化,缺乏成长性。
心智成本高 => 可维护性低 => 生命力弱
作用
提高应用、工具的扩展性
插件架构精髓
对扩展开发,对修改封闭
理解插件
插件安装、使用步骤(以 Webpack Dashboard 为例)
- 安装插件
npm i -D webpack-dashboard
- webpack-config.js配置项
- 引入插件
const DashboardPlugin = require('webpack-dashboard/plugin')
- 创建插件实例
module.exports = {
// ...
plugins: [new DashboardPlugin()],
// ...
};
写插件
// 一个 JavaScript 类
class MyWebpackPlugin {
// 在插件函数的 prototype 上定义一个 `apply` 方法,以 compiler 为参数。
apply(compiler) {
// 指定一个挂载到 webpack 自身的事件钩子。
compiler.hooks.thisCompilation.tap(
'MyWebpackPlugin',
(compilation, callback) => {
}
);
}
}
注:tap是同步方法,tapAsnyc 和 tapPromise 是异步方法。
插件围绕‘钩子’展开 thisCompilation就是一个钩子,相当于一个事件 钩子的核心信息
- 时机
什么时候触发的事件。
实例中,当有一个compilation对象传入时,事件被触发。
- 上下文
通过Tapable提供的回调机制,以参数方式传递上下文信息。
- 交互
在上下文参数对象中附带了很多存在side effect 的交互接口,插件可以通过这些接口改变。
关键的钩子
时机:compiler.hooks.compilation
参数:compilation等
交互:dependencyFactories.set