携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第10天,点击查看活动详情
在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和插件来优化这类资源,这一章专门针对这类资源进行配置处理,还有很多需要深入的地方,课程中没有,自己课外补习吧。