在项目中不可避免的会依赖图片资源,引入图片的方式有如下几种:
- 在js中通过new Image()对象或者document.createElement('img')的形式引入;
- 在css中通过background(url)的形式引入;
- 直接在html中通过img标签引入。
file-loader
yarn add file-loader -D
需要注意:file-loader可以将引用文件打包到指定目录,同时获得文件的地址。可以处理任何文件,并不局限于图片。
我们这里用来处理图片,file-loader默认会将js和css文件中引入图片代码替换为正确的图片地址,同时将图片文件输出到打包目录下。
相关配置如下:
module.exports = {
module: {
rules: [
{
test: /\.(png|jpg|jpeg|gif)$/,
use: {
loader: 'file-loader',
options: {
// 配置占位符,[name]是源文件名称,[ext]是源文件后缀
// [hash:6]是根据文件内容的计算出的Hash值的前6位,用来防止缓存
name: '[name]-[hash:6].min.[ext]' // 配置打包后的文件名称
}
}
}
]
}
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
new Image()
对象的形式引入
在js中通过// 通过import语法把图片引入
// avatar返回的结果是一个新的图片地址
import avatar from './assets/avatar.jpg';
const image = new Image();
// console.log(avatar);
// image.src = './assets/avatar.jpg'; // 不能直接这样写,就是一个普通的字符串
image.src = avatar;
document.body.appendChild(image);
2
3
4
5
6
7
8
在css中通过backgroud(url)的形式引入
.box {
width: 300px;
height: 300px;
background: url('../assets/avatar.jpg') no-repeat;
}
2
3
4
5
这种情况下,css-loader会将css里面的图片引用转化为require的格式,有了require,相当于引用了图片,webpack就会对相应的图片打包。例如上述代码实际上被转化为:
.box {
width: 300px;
height: 300px;
background: url(require('../assets/avatar.jpg')) no-repeat;
}
2
3
4
5
被file-loader转换后输出的CSS会变成这样:
.box1 {
background: url(/Users/liujie/study/Blog/前端相关/Webpack学习总结/webpack4-study/demo5/dist/avatar-9bf3b4.min.jpg) no-repeat;
}
2
3
并且在输出目录dist
中也多出../assets/avatar.jpg
对应的图片文件avatar-9bf3b4.min.jpg,输出的文件名的命名规则为:[name]-[hash:6].min.[ext]
。
- name:原图片名称;
- hash:6:根据文件内容的计算出的Hash值的前6位;
- ext:原图片的后缀名
同理,在JS中导入图片的源码如下:
import avatar from './assets/avatar.jpg';
document.querySelector('.box2').innerHTML = `
<img src='${avatar}' />
`;
2
3
4
5
经过file-loader处理后输出的JS代码如下:
/* 1 */
/***/ (function(module, exports, __webpack_require__) {
module.exports = __webpack_require__.p + "48c211196cf9b1f5b994e8bcf7a41763.jpg";
/***/ })
2
3
4
5
6
也就是说,avatar的值就是图片对应的URL
地址。
<img>
标签引入
直接在html中通过<body>
<div class="box"></div>
<div class="box2"></div>
<img src="./assets/avatar.jpg">
</body>
2
3
4
5
需要使用html-withimg-loader
进行处理:
yarn add html-withimg-loader -D
rules: [
{
test: /\.html/,
use: ['html-withimg-loader']
}
]
2
3
4
5
6
url-loader
url-loader可以将指定大小的图片经过base64编码后注入到JavaScript或者CSS中去。
举个🌰:
.box3 {
background: url(../assets/images/test.jpg) no-repeat;
}
2
3
被url-loader转换后输出的CSS
会变成这样:
.box3 {
background: url(data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/
/* 结尾省略了剩下的base64编码后的数据 */
}
2
3
4
从上面的例子中可以看出,url-loader会将根据图片内容计算出base64编码的字符串直接插入到对应的代码中。
合理使用file-loader和url-loader
- file-loader:会把图片打包到dist目录下,对于小图片而言,会额外增加一次http请求,有点浪费;
- url-loader:通过设置limit参数来合理控制图片的打包形式,小图片进行base64编码插入到代码中去以减少http请求数。因为在HTTP/1.x中,每加载一个资源都需要建立一次HTTP连接,对于小图片而言,新建一次HTTP连接是没有必要的。对于大图片则打包到dist目录下。但是需要注意:在使用url-loader时,图片体积限制不能设置太大,否则会导致JavaScript或者CSS文件过大而带来的页面加载缓慢的问题。
具体配置如下:
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
mode: 'none',
entry: {
app: './src/index.js'
},
output: {
publicPath: __dirname + '/dist/', // 静态资源引用路径或者CDN地址
path: path.resolve(__dirname, 'dist'), // 打包文件的输出目录
filename: '[name].bundle.js'
},
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader']
},
{
test: /\.(png|jpg|jpeg|gif)$/,
use: {
// loader: 'file-loader',
// options: {
// name: '[name]-[hash:6].min.[ext]'
// }
loader: 'url-loader',
options: {
name: '[name]-[hash:6].min.[ext]',
limit: 1024 * 30, // 30kb以下的文件采用url-loader转为base64编码
outputPath: 'assets/images/', // 指定打包后文件放到dist目录下的assets/images目录下
publicPath: 'www.baidu.com',
// 否则采用file-loader,默认值是file-loader
fallback: 'file-loader'
}
}
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[id].css'
})
]
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
options中的publicPath和outputPath
loader: 'url-loader',
options: {
name: '[name]-[hash:5].min.[ext]',
limit: 1024 * 30, // 30kb以下的文件采用url-loader转为base64编码,否则使用file-loader生成对应的图片文件
outputPath: 'assets/images/', // 指定打包后文件放到dist目录下的assets/images目录下
publicPath: 'www.baidu.com',
// 否则采用file-loader,默认值也是file-loader
fallback: 'file-loader'
}
2
3
4
5
6
7
8
9
- outputPath:设置静态资源打包后存放的目录
- publicPath:指定静态资源的CDN存放地址或者服务器上静态资源的存放地址
图片压缩(imagemin-webpack-plugin)
yarn add imagemin-webpack-plugin --dev
引包:
const ImageminPlugin = require('imagemin-webpack-plugin').default;
配置:
new ImageminPlugin({
// disable: process.env.NODE_ENV !== 'production',
pngquant: {
quality: '80'
}
})
2
3
4
5
6
压缩前:
压缩后:
自动合成雪碧图
yarn add postcss-loader postcss-sprite -D
const spritesConfig = {
spritePath: './dist/assets/images/', // 设置雪碧图的输出位置
retina: true // 处理两倍图片的大小
};
{
loader: 'postcss-loader',
// 会把项目中用到的图片合并成雪碧图
options: {
ident: 'postcss',
plugins: [require('postcss-sprites')(spritesConfig)]
}
}
2
3
4
5
6
7
8
9
10
11
12
.sprite1 {
background: url('../assets/douban.png');
}
.sprite2 {
background: url('../assets/qq.png');
}
.sprite3 {
background: url('../assets/weibo.png');
}
2
3
4
5
6
7
8
9
还可以通过
webpack-spritesmith
插件制作雪碧图。
雪碧图的实际应用
雪碧图是为了减少网络请求,所以被处理雪碧图的图片多为各式各样的 logo 或者大小相等的小图片。而对于大图片,还是不推荐使用雪碧图。 除此之外,雪碧图要配合css代码进行定制化使用。要通过css代码在雪碧图上精准定位需要的图片(可以理解成从雪碧图上裁取需要的图片)。
SVG打包处理
SVG好处
SVG作为矢量图的一种标准格式,已经得到了各大浏览器的支持,也成为了Web中矢量图的代名词。在网页中采用SVG代替位图有如下好处:
- SVG比位图更清晰,在任意缩放的情况下都不会破坏图形的清晰度,能方便地解决高分辨率屏幕下图像显示不清楚的问题。
- 在图形线条比较简单的情况下,
SVG
文件的大小要小于位图,在扁平化UI
流行的今天,在多数情况下SVG
会更小。 - 图形相同的
SVG
比对应的高清图有更好的渲染性能。 SVG
采用和HTML
一致的XML
语法描述,灵活性很高。
画图工具能导出一个个.svg
文件,SVG
的导入方法和图片类似,既可以像下面这样在CSS
中直接使用:
.box {
width: 200px;
height: 200px;
background: url(../assets/images/svg1.svg) no-repeat;
}
2
3
4
5
也可以在HTML
中使用:
<img src="../assets/images/svg1.svg" />
也就是说,可以直接把SVG
文件当成一张图片来使用,方法和使用图片时完全一样。
使用file-loader
和使用url-loader
对SVG
来说同样有效,只需要把Loader test
配置中的文件后缀改成.svg
,具体webpack配置如下:
const path = require('path');
module.exports = {
mode: 'none',
entry: './src/index.js',
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
publicPath: __dirname + '/dist/'
},
module: {
rules: [
{
test: /.svg$/,
use: 'file-loader'
},
{
test: /.css$/,
use: ['style-loader', 'css-loader']
}
]
}
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
index.css
.box {
width: 200px;
height: 200px;
background: url(../assets/images/svg1.svg) no-repeat;
}
2
3
4
5
index.js
import './style/index.css';
console.log('hello svg');
2
3
index.html
<body>
<div>
<h2>加载svg了</h2>
<div class="box"></div>
</div>
<script src="./dist/main.bundle.js"></script>
</body>
2
3
4
5
6
7
运行webpack打包:
publicPath(一般只用于生产环境中)
不配置publicPath:
配置publicPath:设置了打包后的静态资源加载目录。
由于
SVG
是文本格式的文件,除了以上两种方法外还有其它方法,下面来一一说明。
使用Raw-Loader
raw-loader
可以将文本文件的内容读取出来,注入到JavaScript或CSS
中去。
例如,在index.js
中这样写:
import svgContent from './assets/images/svg1.svg';
document.querySelector('.box').innerHTML = svgContent;
console.log('hello svg666');
2
3
经过raw-loader
处理后输出的代码如下:
module.exports = "<svg xmlns=\"http://www.w3.org/2000/svg\"... </svg>" // 末尾省略 SVG 内容
也就是说,svgContent
的内容就等于字符串形式的SVG
,由于SVG
本身就是 HTML
元素,所以在获取到SVG
内容后,可以直接通过以下代码将SVG
插入到网页中:
document.querySelector('.box').innerHTML = svgContent;
使用raw-loader
时相关的Webpack
配置如下:
module.exports = {
module: {
rules: [
{
test: /\.svg$/,
use: 'raw-loader'
}
]
}
};
2
3
4
5
6
7
8
9
10
如下图所示:
.box
的div里填充该svg图片。
需要注意:由于
raw-loader
会直接返回SVG
的文本内容,并且无法通过CSS
去展示SVG
的文本内容,因此采用本方法后无法在CSS
中导入SVG
。也就是说,在CSS
中不可以出现background-image: url(./svgs/activity.svg)
这样的代码,因为background-image: url(<svg>...</svg>)
是不合法的。
SVG
的压缩功能)
使用Svg-Inline-Loader(增加了对svg-inline-loader
和上面提到的raw-loader
非常相似,不同之处在于:svg-inline-loader
会分析SVG
的内容,去除其中不必要的部分代码,以减少SVG
的文件大小。
在使用画图工具如Adobe Illustrator
、Sketch
制作SVG
后,在导出时这些工具会生成对网页运行来说不必要的代码。举个例子,以下是Sketch
导出的SVG
的代码:
<svg class="icon" verison="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
stroke="#000">
<circle cx="12" cy="12" r="10"/>
</svg>
2
3
4
被svg-inline-loader
处理后会精简成如下:
<svg viewBox="0 0 24 24" stroke="#000"><circle cx="12" cy="12" r="10"/></svg>
也就是说svg-inline-loader
增加了对SVG
的压缩功能。
使用svg-inline-loader
时相关的Webpack
配置如下:
module.exports = {
module: {
rules: [
{
test: /\.svg$/,
use: 'svg-inline-loader'
}
]
}
};
2
3
4
5
6
7
8
9
10