一、概念
帮助webpack将不同类型的文件转换为webpack可识别的模块。
二、Loader执行顺序
分类
- pre:前置loader
- normal:普通loader
- inline:内联loader
- post:后置loader
执行顺序
- 4类loader的执行顺序为per>normal>inline>post
- 相同优先级的loader执行顺序为:从右到左,从下到上。
例如:
// 此时loader执行顺序:loader3 - loader2 - loader1
module: {rules: [{test: /\.js$/,loader: "loader1",},{test: /\.js$/,loader: "loader2",},{test: /\.js$/,loader: "loader3",},],
},
// 此时loader执行顺序:loader1 - loader2 - loader3
module: {rules: [{enforce: "pre",test: /\.js$/,loader: "loader1",},{// 没有enforce就是normaltest: /\.js$/,loader: "loader2",},{enforce: "post",test: /\.js$/,loader: "loader3",},],
},
使用Loader 的方式
- 配置方式:在 webpack.config.js 文件中指定 loader。(pre、normal、post loader)
- 内联方式:在每个 import 语句中显式指定 loader。(inline loader)
inline Loader
用法:import Styles from ‘style-loader!css-loader?modules!./styles.css’;
含义:使用 css-loader 和 style-loader 处理 styles.css 文件通过 ! 将资源中的 loader 分开
inline loader 可以通过添加不同前缀,跳过其他类型 loader。! 跳过 normal loader。
import Styles from '!style-loader!css-loader?modules!./styles.css';
-! 跳过 pre 和 normal loader。
import Styles from '-!style-loader!css-loader?modules!./styles.css';
!! 跳过 pre、 normal 和 post loader。
import Styles from '!!style-loader!css-loader?modules!./styles.css';
三、开发一个Loader
最简单的Loader
//loader/loader1.js
module.exports = function (content){console.log(content)return content;
}
他接受要处理的源码作为参数,输出转换后的js代码
Loader接受的参数
- content 源文件的内容
- map sourceMap数据
- meta 数据可以是任何内容
Loader分类
- 同步Loader
module.exports = function (content ,map ,meta) {/* 第一个参数:err代表是否有错误第二个参数:content处理后的内容第三个参数:sorce-map继续传递sourcemap 第四个参数:meta给下一个loader传递参数*///相比于普通return方式这种写法可以传递更多参数,不中断loader执行。//return content this.callback(null,content,map,meta)
}
- 异步Loader
由于同步计算过于耗时,在 Node.js 这样的单线程环境下进行此操作并不是好的方案,我们建议尽可能地使你的 loader 异步化。但如果计算量很小,同步 loader 也是可以的。
module.exports = function (content, map, meta) {const callback = this.async();// 进行异步操作setTimeout(() => {callback(null, result, map, meta);}, 1000);
};
- Raw Loader
默认情况下,资源文件会被转化为 UTF-8 字符串,然后传给 loader。通过设置 raw 为 true,loader 可以接收原始的 Buffer
module.exports = function (content) {// content是一个Buffer数据return content;
};
module.exports.raw = true; // 开启 Raw Loader
- Pitching Loader
webpack 会先从左到右执行 loader 链中的每个 loader 上的 pitch 方法(如果有),然后再从右到左执行 loader 链中的每个 loader 上的普通 loader 方法。在这个过程中如果任何 pitch 有返回值,则 loader 链被阻断。webpack 会跳过后面所有的的 pitch 和 loader,直接进入上一个 loader 。
module.exports = function (content) {return content;
};
module.exports.pitch = function (remainingRequest, precedingRequest, data) {console.log("do somethings");
};
手写banner-loader
作用:给代码添加文本注释包括作者、日期
//loader/banner-loader.js
const schema = require("./schema.json");
module.exports = function (content,map,meta){//获取Loader的options,同时对options做校验//schema 是options的校验规则。const options = this.getOptions(schema);const date = (new Date()).toLocaleString()const prefix = `/* Author ${options.author}Date ${date}*/`return `${prefix} \n ${content}`
}
下面是schema.json文件
{"type":"object","porperties":{"author":{"type":"string"}},"addtionalProperties":false
}
在webpack.config.js中配置
//...省略module: {rules: [{test:/\.js$/,loader:'./loader/banner-loader',options:{author:'老王'}}]},
在dist压缩文件main.js中
/***/ "./src/main.js":
/*!*********************!*\!*** ./src/main.js ***!\*********************/
/***/ (() => {eval("\n /* \n Author 老王\n Date 2024/1/13 14:32:11\n */\n \n console.log('hello main')\n\n//# sourceURL=webpack:///./src/main.js?");/***/ })/******/ });
/************************************************************************/