loader
webpack loader: loader本质上是一个函数,它的作用是将某个源码字符串转换成另一个源码字符串返回。
loader函数将在模块解析的过程中被调用,以得到最终的源码。按照loader配置的书写顺序, 多个loader从后往前依次调用, 后面一个loader的输出结果传入前一个loader继续处理.
2020-01-13-09-35-44.png代码示例
var loaderUtils = require('loader-utils');
module.exports = function (sourceCode) {
var options = loaderUtils.getOptions(this);
var reg = new RegExp(options.changeVar, "g");
return sourceCode.replace(reg, "var");
}
在配置文件中的options处书写的额外参数, 可以在loader函数内的this中读取到, webpack在this对象内放了很多东西. 使用load-utils
包可以帮助我们解析this对象的内容.
plugin
loader的功能定位是转换代码,而一些其他的操作难以使用loader完成,比如:
- 当webpack生成文件时,顺便多生成一个说明描述文件
- 当webpack编译启动时,控制台输出一句话表示webpack启动了
- 当xxxx时,xxxx
这种类似的功能需要把功能嵌入到webpack的编译流程中,而这种事情的实现是依托于plugin的. webpack在编译的过程中有许多事件, 我们通过监听这些事件能够参与到编译过程的各个阶段, 并且有机会在这些阶段来实现我们的功能.
plugin的本质是一个带有apply方法的对象, 习惯上我们会将该对象写成构造函数的模式.
apply方法有一个参数compiler, compiler对象是在初始化阶段创建的, 整个webpack打包过程中只有一个compiler对象, 后续完成打包工作的是compiler对象内部创建的compilation(每一次具体的打包过程都会有新的compilation对象). apply方法会在创建好compiler对象后调用, 并向方法传入compiler.
代码示例
module.exports = class MyPlugin {
constructor(filename = 'filelist.txt') {
this.filename = filename;
}
apply(compiler) {
// 在这里注册事件, 类似于window.onload
compiler.hooks.emit.tap("MyPlugin-emit", function(compilation) {
// 事件处理函数
var fileList = [];
for (const key in compilation.assets) {
var content = `[${key}] 大小: ${compilation.assets[key].size()}b`;
fileList.push(content);
}
var str = fileList.join("\n\n");
compilation.assets[this.filename] = {
source() {
return str;
},
size() {
return str.length;
}
};
});
}
}
常用扩展
- css-loader: 将css代码转换为js代码, 将css中的其他依赖作为require导入, 以便webpack分析依赖
- style-loader: 将css-loader转换后的代码进一步处理, 将样式加到页面的style元素中
- MiniCssExtractPlugin: 将css文件单独抽离到输出目录(跟js打包方式一样, 一个chunk合并成一个css)
- 它包含有一个plugin和一个loader
- 在loader配置处以
MiniCssExtractPlugin.loader
的方式, 替换到原先的style-loader
- clean-webpack-plugin: 清除输出目录
- html-webpack-plugin: 自动生成页面
- copy-webpack-plugin: 复制静态资源(html中直接引用静态资源, 希望把静态资源复制到输出目录)
- webpack-dev-server: 开发服务器(既不是plugin, 也不是loader), 运行webpack-dev-server后, 做了以下操作
- 内部执行webpack命令, 传递命令参数
- 开启watch
- 注册hooks, 向webpack中注册钩子函数, 主要功能有: 将资源列表保存, 禁止webpack输出文件
- 用express开启一个服务器, 监听某端口
- file-loader: 将导入的文件, 导出为一个有效url地址, 并将文件输出到输出目录
- url-loader: 将依赖的文件转换为: 导出一个base64格式的字符串, 不生成文件到输出目录
- url-loader可以配置如果文件超过了设定的大小, 则不生成base64编码, 而是交给file-loader处理
- url-loader内部使用了file-loader, 它的配置项有些自身不用, 是传递给file-loader用的
webpack内置插件
所有的webpack内置插件都作为webpack的静态属性存在
const webpack = require("webpack");
new webpack.插件名(options);
- DefinePlugin: 定义一些全局的常量
- BannerPlugin: 为每个chunk生成的文件头部添加注释, 一般用于添加作者, 公司, 版权信息等
- ProvidePlugin: 自动加载模块, 而不必导出import或require
解决路径问题
在某些情况下, 例如将图片用file-loader输出到dist/img目录下, js文件输出到dist/scripts目录下, 页面文件输出到dist/html目录下, 此时js对图片的引用会产生问题.
这种问题发生的根本原因是: 模块中的路径来自于某个loader或plugin, 当产生路径时, loader或plugin只有相对于dist目录的路径, 并不知道该路径将在哪个资源中使用, 从而无法确定最终的正确路径.
面对这种情况, 需要依靠webpack的配置publicPath解决.
注意: publicPath
通常在output配置项中, 本身没有任何作用, 但是某些loader和plugin会读取这个publicPath, 并且它们导出的地址前面, 拼接上这个配置. 通常output里配置为publicPath: "/"
这样, 文件的地址就变成了绝对路径.
一般, 会用到publicPath的loader和plugin, 本身也会支持在自己的配置项中再单独配置publicPath项.
网友评论