在web日常开发过程中,图像是最常见的装饰器,在webpack中,图像也被提升为一等公民,够像引用普通 JavaScript 模块一样通过 import/require
语句导入资源模块,这种开发模式允许我们将图像相关的处理合入统一的心智模型中,提升开发效率。
webpack4
中处理图片
在webpack4
中只能识别标准的JavaScript
对象,对于图像处理还需要借助loader
来实现,例如 file-loader
、url-loader
、raw-loader
等完成图像加载操作,实践中我们通常需要按资源类型选择适当加载器。
file-loader
::将图像引用转换为 url 语句并生成相应图片文件。url-loader
:有两种表现,对于小于阈值limit
的图像直接转化为 base64 编码;大于阈值的图像则调用file-loader
进行加载。raw-loader
:不做任何转译,只是简单将文件内容复制到产物中,适用于 SVG 场景。
配置起来如下:
module.exports = { // 省略其他配置 module: { rules: [ { test: /.(png|jpg|bmp)$/, use: [ // url-loader 内置了 file-loader,所以使用url-loader 就不需要使用 file-loader 了 // { // loader: "file-loader" // }, { loader: "url-loader", options: { limit: 1024 // 对于小于1kb的图像文件进行base64处理 } }] }, { test: /.svg$/, use: 'raw-loader' } ] } }
webpack5
中处理图片
而在webpack5
中,处理图片就不需要这样做了,因为上面这些loader
使用的太频繁了,于是webpack
将这些loader
内置了,并提供了type
属性来供用户使用,配置起来如下:
module.exports = { // 省略其他配置 module: { rules: [{ test: /.bmp$/, type: "asset/resource" }, { test: /.jpg$/, type: "asset/source" }, { test: /.png$/, type: "asset/inline" }, { test: /.svg$/, type: "asset" }] } }
上面为了演示效果,所以每个
type
属性的属性值都列举出来了。
构建的结果如下
type
的属性值为asset/inline
type
的属性值为asset/resource
type
的属性值为asset/source
type
的属性值为asset
简单的说明一下
file-loader
对标到type = "asset/resource"
url-loader
对标到type = "asset"
或type = "asset/inline"
raw-loader
对标到type = "asset/source"
file-loader
、url-loader
、raw-loader
并不是只能处理图片,还可以是其他多媒体文件,详细参见:资源模块
如果要将上面的webpack4
变成webpack5
的写法应该怎么是什么样的,毕竟还有limit
的配置,如下
module.exports = { module: { rules: [ { test: /.(png|jpg|bmp)$/, type: "asset", parser: { dataUrlCondition: { maxSize: 1024 } } }, { test: /.svg$/, type: "asset/source" } ] } }
图片优化=>压缩
图像压缩需要借助到image-webpack-loader
,所以先安装依赖,npm i -D image-webpack-loader imagemin-jpegtran imagemin-svgo imagemin-gifsicle imagemin-optipng
,因为image-webpack-loader
依赖imagemin
,所以需要额外的安装imagemin
的依赖, image-webpack-loader
提供了一系列的配置用来压缩不同类型的图片,如下:
温馨提示:如果
imagemin
安装不成功请使用cnpm
,原因是imagemin
安装时会根据终端来下载一些二进制解析文件,这些文件可能会被墙,也可能不维护丢失了,情况很多,所以可以去cnpm
的淘宝镜像找资源。
配置起来也很简单,如下:
module.exports = { module: { rules: [ { test: /.(png|jpg|bmp)$/, type: "asset", parser: { dataUrlCondition: { maxSize: 1024 } }, use: [{ loader: 'image-webpack-loader', options: { // jpeg 压缩配置 mozjpeg: { quality: 80 }, } }] } ] } }
图像优化:雪碧图
雪碧图没什么好说的,就是把一堆图片合并到一个图片文件中,然后使用的时候通过背景图片可以调整位置来定位到具体的图片上,这样做的好处就是利用浏览器缓存,可以减少http(s)
请求。
这里使用的是webpack-spritesmith
插件,npm i -D webpack-spritesmith
安装 配置如下:
const path = require('path'); const SpritesmithPlugin = require('webpack-spritesmith'); module.exports = { plugins: [ new SpritesmithPlugin({ // 将根目录下的 asset 目录下的所有 .png文件合并成一个雪碧图 src: { cwd: path.resolve(__dirname, './asset'), glob: '*.png' }, // 生成目标文件存在的路径 target: { image: path.resolve(__dirname, 'src/assets/sprite.png'), css: path.resolve(__dirname, 'src/assets/sprite.less') } }) ] }
执行
npx webpack
构建,会在src/assets
生成一个合成后的sprite.png
文件,还有一个sprite.less
的定位指导文件。
图像优化:响应式图片
响应式图片就是根据不同的需求,将图片转换为不同尺寸的产物进行输出,防止图片因为分辨率的问题产生的拉伸、变形、颗粒感,这里用到的loader
是responsive-loader
,安装npm i -D responsive-loader sharp
,配置如下:
module.exports = { module: { rules: [ { test: /.(png|jpg|jpeg|bmp)$/, oneOf: [{ type: "javascript/auto", resourceQuery: /sizes?/, use: [{ loader: "responsive-loader", options: { adapter: require("responsive-loader/sharp"), }, }], }, { type: "asset/resource", }], }, ] } }
这里配置完成之后还需要使用才行,不像雪碧图直接就合成了,使用也很简单,在使用的地方加上query
参数就可以了,这里我直接在main.js
中引用
const logo1 = require('./asset/logo.jpeg?sizes[]=300,sizes[]=600,sizes[]=1024')
然后执行npx webpack
构建就会在生成的文件中出现三张不同大小的图片啦。
总结
图片处理是有很多门道在里面的,webpack4
和之前有file-loader
、url-loader
、raw-loader
来处理这类资源,到了webpack5
专门多出一个属性来处理这类资源,同时还有其他的一些laoder
和插件来优化这类资源,这一章专门针对这类资源进行配置处理,还有很多需要深入的地方,课程中没有,自己课外补习吧。