webpack loader 介绍及使用
webpack 只能处理 js 模块,其他文件如.css、.ts 它无法处理,所以需要 loader 来处理 js 外的文件使其转化为 js 模块,loader 的加载顺序是从右到左,从下到上。
比如下面对于.scss 文件的转化分别经历了 sass-loader、css-loader、style-loader,几个 loader 各司其职,缺一不可。除了下面配置的方式,也可通过import "style-loader!css-loader!sass-loader!./index.scss";
来使用 loader 转化该 scss 文件。
module: {
rules: [{
test: /\.scss$/,
use: [{
loader: "style-loader" // 将 JS 字符串生成为 style 节点
}, {
loader: "css-loader" // 将 CSS 转化成 CommonJS 模块
}, {
loader: "sass-loader" // 将 Sass 编译成 CSS
}]
}]
}
常用 loader:
- url-loader/file-loader:将资源 copy 到 dist 中相应位置并重命名,url-loader 可配置小于多少 limit 时转化为 dataurl,如果大于 limit 默认走 file-loader,所以如果没有特殊需求单用 url-loader 即可;
- babel-loader:es 新标准转 es5;
- ts-loader:ts 转 js;
- postcss-loader:可对 css 处理,如自动加浏览器兼容性前缀等,一般在 sass-loader 上层,css-loader 下层。
自定义 loader
开发各类小程序时(微信/百度/头条等),基本都会对小程序的包大小限制在几兆左右,此时项目中就不能放太多的图片,否则很容易就会超过限制。所以很多时候我们会把小程序中用到的图片放到 oss 上面,程序直接引用 oss 的地址。
开发的时候得先把需要的图片事先上传到 oss 上面,然后获取到 oss 地址再放到 src 中,会显得格外繁琐。
此时我们需要自定义一个处理图片的 loader,主要是获取到图片的内容并上传到 oss,然后获取到 oss 地址并包装成 commonjs 模块返回;
我们的小程序是基于 uniapp 的,uniapp 除了可以使用hbuilderx
开发之外,还可以通过老朋友vue-cli
来开发,也就意味着可以自定义 loader 了。要修改vue-cli
的配置,需要新建一个vue.config.js
文件:
module.exports = {
chainWebpack: (config) => {
// 获取到images的配置规则,怎么知道处理图片的rule名称是images而不是img或者image呢,vue-cli下执行vue inspect > output.js可以看到所有的规则名及具体配置
const imagesRule = config.module.rule('images');
// 清楚改rule下所有的loader
imagesRule.uses.clear();
// 使用自定义的loader
imagesRule.use('./img-upload-loader.js').loader('./img-upload-loader.js').end();
}
};
主要做了 2 个操作:
- 清除图片处理的所有 loaders,其实就是
url-loader
和file-loader
这两兄弟; - 配置我们自定义的 loader。
这里img-upload-loader
就是负责上传图片的 loader 了,看下实现代码:
module.exports = function (source) {
const callback = this.async();
upload(source, () => {
callback(null, `module.exports = '${url}'`);
})
};
function upload(source, cb) {
// 此处模拟上传操作
req.upload('https://xxx', source).then((url) => {
cb(url);
})
};
通过异步 loader 实现上传,上传成功后导出地址;
打包时会把小程序中 image 组件的 rc 转为线上地址,比如:
<image :src="require('@/assets/images/logo.png')" />
将转为:
<image src="https://xxx.com/logo.png" />
这里需要注意的是 src 的地址必须是通过 require 引入的,否则不生效,因为 uniapp 默认不会把 image 中的 src 当作模块处理,这里和开发 h5 时有差别。