前言
这篇文章主要介绍了浅谈webpack4 图片处理,觉得挺不错的,现在分享给大家,也给大家做个参考。
目录结构:
webpack4中的图片常用的基础操作:
如项目代码目录展示的那样,除了常见的app.js作为入口文件,我们将用到3张图片放在/src/assets/imgs/目录下,并在样式base.css中引用这些图片。
剩下的内容叫给webpack打包处理即可。样式文件和入口app.js文件的代码分别如下所示:
/* base.css */*,body {margin: 0;padding: 0;}.box {height: 400px;width: 400px;border: 5px solid #000;color: #000;}.box div {width: 100px;height: 100px;float: left;}.box .ani1 {background: url('../assets/imgs/1.jpg') no-repeat;}.box .ani2 {background: url('../assets/imgs/2.png') no-repeat;}.box .ani3 {background: url('../assets/imgs/3.png') no-repeat;}
在app.js中
import ‘./css/base.css’
安装依赖:
npm install url-loader file-loader —save-dev
(二)图片处理和base64编码
在webpack.config.js中module.rules选项中进行配置,以实现让loader识别图片后缀名,并且进行制定的处理操作。
module.exports = {
module: {
rules: [
{
test: /\.(png|jpg|jpeg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
name: '[name]-[hash:5].min.[ext]',
outputPath: 'images/', //输出到 images 文件夹
limit: 20000 //把小于 20kb 的文件转成 Base64 的格式
}
}
]
}
]
}
}
完整的配置文件
const path = require('path')
const CleanWebpackPlugin = require('clean-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin') // 将 css 单独打包成文件
module.exports = {
entry: {
app: './src/app.js'
},
output: {
publicPath: './', // js 引用的路径或者 CDN 地址
path: path.resolve(__dirname, 'dist'), // 打包文件的输出目录
filename: '[name].bundle.js', // 代码打包后的文件名
chunkFilename: '[name].js' // 代码拆分后的文件名
},
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader
},
'css-loader'
]
},
{
test: /\.(png|jpg|jpeg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
name: '[name]-[hash:5].min.[ext]',
outputPath: 'images/', //输出到 images 文件夹
limit: 20000 //把小于 20kb 的文件转成 Base64 的格式
}
}
]
}
]
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
// 打包输出HTML
title: '自动生成 HTML',
minify: {
// 压缩 HTML 文件
removeComments: true, // 移除 HTML 中的注释
collapseWhitespace: true, // 删除空白符与换行符
minifyCSS: true // 压缩内联 css
},
filename: 'index.html', // 生成后的文件名
template: 'index.html', // 根据此模版生成 HTML 文件
chunks: ['app'] // entry中的 app 入口才会被打包
}),
new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[id].css'
})
]
}
打包项目,查看打包结果,并在浏览器中打开index.html文件:
可以看到除了1.jpg,另外两张图片已经被打包成base64格式,在app.css文件中1.jpg这个文件超过了我们在url-loader选项中设置的limit值,所以被单独打包
这就是利用了 file-loader 的能力,如果在 url-loader 中设置了 limit 的值,却没有安装 file-loader 依赖,会怎么样?来试试看,首先卸载 file-loader 依赖,npm uninstall file-loader,再运行打包命令,npm run build
如果图片较多,会发很多http请求,会降低页面性能。 url-loader会将引入的图片编码,转为base64字符串。在把这串字符串打包到文件中,最终只需要引入这个文件就能访问图片了,节省了图片请求。
但是,如果图片较大,编码会消耗性能。因此url-loader提供了一个limit参数,小于limit参数的文件会被转为base64,大于limit的使用file-loader进行处理,单独打包。
url-loader依赖file-loader,url-loader可以看作是增强版的file-loader
(三)图片压缩
图片压缩需要使用img-loader插件,除此之外,针对不同的图片类型,还要引用不同的插件。例如,我们项目中使用的是png图片,需要引入的是imagemin-pngquant,并且指定压缩率。压缩jpg/jpeg图片为imagemin-mozjpeg 插件
这里有个bug,可以先不急着操作,先把这一小节看完,在决定!!
安装依赖
npm i img-loader imagemin imagemin-pngquant imagemin-mozjpeg —save-dev
在之前的配置上更改:
{
test: /\.(png|jpg|jpeg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
name: '[name]-[hash:5].min.[ext]',
outputPath: 'images/', // 输出到 images 文件夹
limit: 20000 //把小于 20kb 的文件转成 Base64 的格式
}
}
]
}
更改为:
{
test: /\.(png|jpg|jpeg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
name: '[name]-[hash:5].min.[ext]',
limit: 1000, // size <= 1KB
outputPath: 'images/'
}
},
// img-loader for zip img
{
loader: 'img-loader',
options: {
plugins: [
require('imagemin-pngquant')({
quality: '80' // the quality of zip
}),
require('imagemin-mozjpeg')({
quality: '80'
})
]
}
}
]
}
打包结果:
原因在 png 图片上,jpg 图片可以压缩,但是去 imagemin-pngquant github 上也没发现有人提出类似 issue ,百度、google 找了半天,还是没发现怎么解决 ~_~,于是使用另一种压缩图片的插件 image-webpack-loader
首先卸载了之前的依赖:
npm uni img-loader imagemin imagemin-pngquant imagemin-mozjpeg
安装依赖:
npm i image-webpack-loader —save-dev
这个依赖安装的时间会比较久。。。可以做下其他的。
在之前的配置上更改:
{
test: /\.(png|jpg|jpeg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
name: '[name]-[hash:5].min.[ext]',
outputPath: 'images/', // 输出到 images 文件夹
limit: 20000 //把小于 20kb 的文件转成 Base64 的格式
}
}
]
}
更改为:
{
test: /\.(png|jpg|jpeg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
name: '[name]-[hash:5].min.[ext]',
limit: 1000, // size <= 1KB
outputPath: 'images/'
}
},
// img-loader for zip img
{
loader: 'image-webpack-loader',
options: {
// 压缩 jpg/jpeg 图片
mozjpeg: {
progressive: true,
quality: 65 // 压缩率
},
// 压缩 png 图片
pngquant: {
quality: '65-90',
speed: 4
}
}
}
]
}
这里故意吧url-loader的limit属性值设的很小,不让它转化png图片为base64,因为我们要测试压缩png图片
打包结果:
图片压缩成功,这里我仔细看了下image-webpack-loader 的 github,其实这里的image-webpack-loader 插件内置了好几种图片压缩的插件
这里让我很疑惑,为什么我直接安装 imagemin-pngquant 不行,反而使用 image-webpack-loader却可以,于是我去查看 package-lock.json 文件,搜索 image-webpack-loader
我看了下我之前安装的最新版本,7.0.0!!!
终于找到原因了,,新版本有些问题没有处理好,导致压缩png图片失败,找到问题就好办了,在package.json中,将imagemin-pngquant 版本改为 ^6.0.0,重新 npm install
按照之前的操作,就可以压缩成了,对应如下:
{
"devDependencies": {
"imagemin": "^6.1.0",
"imagemin-mozjpeg": "^8.0.0",
"imagemin-pngquant": "^6.0.0",
"img-loader": "^3.0.1"
}
}
如果使用 image-webpack-loader ,版本为 4.6.0 .
这次我还是使用了image-webpack-loader,朋友们可以自行选择使用哪个插件,只是image-webpack-loader引入了其他图片格式压缩的依赖,如 svg/webp/gif 等,只安装 image-webpack-loader 就够了,而另一种则是要一个个插件装过去,其实原理都一样。我个人比较推荐使用image-webpack-loader
(四)生成雪碧图
安装依赖:
npm i postcss-loader postcss-sprites —save-dev
完整配置:
const path = require('path')
const CleanWebpackPlugin = require('clean-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin') // 将 css 单独打包成文件
/*********** sprites config ***************/
let spritesConfig = {
spritePath: './dist/images'
}
/******************************************/
module.exports = {
entry: {
app: './src/app.js'
},
output: {
publicPath: './', // js 引用的路径或者 CDN 地址
path: path.resolve(__dirname, 'dist'), // 打包文件的输出目录
filename: '[name].bundle.js', // 代码打包后的文件名
chunkFilename: '[name].js' // 代码拆分后的文件名
},
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader
},
'css-loader',
/*********** loader for sprites ***************/
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: [require('postcss-sprites')(spritesConfig)]
}
}
/*********************************************/
]
},
{
test: /\.(png|jpg|jpeg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
name: '[name]-[hash:5].min.[ext]',
limit: 1000, // size <= 1KB
outputPath: 'images/'
}
},
// img-loader for zip img
{
loader: 'image-webpack-loader',
options: {
// 压缩 jpg/jpeg 图片
mozjpeg: {
progressive: true,
quality: 65 // 压缩率
},
// 压缩 png 图片
pngquant: {
quality: '65-90',
speed: 4
}
}
}
]
}
]
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
// 打包输出HTML
title: '自动生成 HTML',
minify: {
// 压缩 HTML 文件
removeComments: true, // 移除 HTML 中的注释
collapseWhitespace: true, // 删除空白符与换行符
minifyCSS: true // 压缩内联 css
},
filename: 'index.html', // 生成后的文件名
template: 'index.html', // 根据此模版生成 HTML 文件
chunks: ['app'] // entry中的 app 入口才会被打包
}),
new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[id].css'
})
]
}
打包后查看结果:
雪碧图是为了减少网路请求,所以被处理雪碧图的图片多为各式各样的logo或者是大小相同的小图片。
而对于大图片,不推荐使用雪碧图。这样会使得图片体积很大。
除此之外,雪碧图要配合css代码定制化使用,要通过 css 代码在雪碧图上精准定位需要的图片。
总结
以上只是webpack处理图片部分,webpack还有更多的功能配置,请参考https://www.webpackjs.com/concepts/ 根据自己的项目需求,进行配置。
