webpack做的事情,仅仅是分析出各种模块的依赖关系,然后形成资源列表,最终打包生成到指定的文件中。 更多的功能需要借助webpack loaders和webpack plugins完成。
webpack loader: loader本质上是一个函数,它的作用是将某个源码字符串转换成另一个源码字符串返回。
loader函数的将在模块解析的过程中被调用,以得到最终的源码。
全流程:
chunk中解析模块的流程:
chunk中解析模块的更详细流程:
处理loaders流程:
loader配置:
完整配置
module.exports = {
module: { //针对模块的配置,目前版本只有两个配置,rules、noParse
rules: [ //模块匹配规则,可以存在多个规则
{ //每个规则是一个对象
test: /\.js$/, //匹配的模块正则
use: [ //匹配到后应用的规则模块
{ //其中一个规则
loader: "模块路径", //loader模块的路径,该字符串会被放置到require中
options: { //向对应loader传递的额外参数
}
}
]
}
]
}
}
简化配置
module.exports = {
module: { //针对模块的配置,目前版本只有两个配置,rules、noParse
rules: [ //模块匹配规则,可以存在多个规则
{ //每个规则是一个对象
test: /\.js$/, //匹配的模块正则
use: ["模块路径1", "模块路径2"]//loader模块的路径,该字符串会被放置到require中
}
]
}
}
配置案例
- 下面的loader1 - 3都是自己编写的loader
module.exports = {
mode: "development",
module: {
rules: [
{
test: /index\.js$/, //正则表达式,匹配模块的路径
use: ["./loaders/loader1", "./loaders/loader2"] //匹配到了之后,使用哪些加载器
}, //规则1
{
test: /\.js$/, //正则表达式,匹配模块的路径
use: ["./loaders/loader3", "./loaders/loader4"] //匹配到了之后,使用哪些加载器
} //规则2
], //模块的匹配规则
}
}
- 自己编写的处理样式的loader
module.exports = {
mode: "development",
devtool: "source-map",
module: {
rules: [{
test: /\.css$/,
use: ["./loaders/style-loader"]
}]
}
}
module.exports = function (sourceCode) {
var code = `var style = document.createElement("style");
style.innerHTML = \`${sourceCode}\`;
document.head.appendChild(style);
module.exports = \`${sourceCode}\``;
return code;
}
- 自己编写的处理图片loader
module.exports = {
mode: "development",
devtool: "source-map",
module: {
rules: [
{
test: /\.(png)|(jpg)|(gif)$/, use: [{
loader: "./loaders/img-loader.js",
options: {
limit: 3000, //3000字节以上使用图片,3000字节以内使用base64
filename: "img-[contenthash:5].[ext]"
}
}]
}
]
}
}
var loaderUtil = require("loader-utils")
function loader(buffer) { //给的是buffer
console.log("文件数据大小:(字节)", buffer.byteLength);
var { limit = 1000, filename = "[contenthash].[ext]" } = loaderUtil.getOptions(this);
if (buffer.byteLength >= limit) {
var content = getFilePath.call(this, buffer, filename);
}
else{
var content = getBase64(buffer)
}
return `module.exports = \`${content}\``;
}
loader.raw = true; //该loader要处理的是原始数据
module.exports = loader;
function getBase64(buffer) {
return "data:image/png;base64," + buffer.toString("base64");
}
function getFilePath(buffer, name) {
var filename = loaderUtil.interpolateName(this, name, {
content: buffer
});
this.emitFile(filename, buffer);
return filename;
}