在开发过程中,我们需要用到很多图标,这些图标的大小不是很大,但是每次需要向服务器发送请求,从而加重服务器的负担,尤其是当网站处于高访问量的情况下或网络不稳定的时候,服务器性能会明显下降。这种情况不符合被广泛遵循的雅虎军规“尽量减少HTTP请求数”的要求
例如 当我们引入如图的4个各不到1k的小图片还占用了4个请求,这显然非常浪费服务器资源
1.css方法是将小图标和背景图像合并到一张图片上,这样每个元素都会以该合成图为背景,而且页面也只加载一张合成图
然后利用CSS的背景定位(background-position)来显示需要显示的图片部分。
其中要用到 background-image,background-position
其中如下图 背景图 左上角默认和容器框重合的,现在也就是默认会显示 第一个图片 ,现在想要显示第二个图片 就需要把background-image 左移动一个(也即是X轴负方向) 所以显示的{x:-60px;y:0px}
合并图片 方法有很多,图片合并软件 , 在线合并 以及 glup webpack工具
使用时候直接引入css 文件 ,定义好对应类名 即可
主要用到:
webpack
file-loader
sass-loader
(因为 webpack-spritesmith
除了生成雪碧图之外,还会生成相应的 mixin
,使用起来很方便,所以要用 sass
)webpack配置如下
const path = require('path');
const SpritesmithPlugin = require('webpack-spritesmith');
module.export = {
// ...
module: {
rules: [
{
test: /png$/
loader:[
'file-loader?name=i/[hash].[ext]'
]
},
{
test: /\.(css|scss)$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: ['css-loader', 'postcss-loader', 'sass-loader']
})
}
]
},
resolve: {
modules: [
'node_modules',
'assets' //css在哪里能找到sprite图 文件夹的名字
]
},
plugins: [
new SpritesmithPlugin({
src: {
cwd: path.resolve(__dirname, 'src/ico'), //准备合并成sprit的图片存放文件夹
glob: '*.png' //哪类图片
},
target: {
image: path.resolve(__dirname, 'src/assets/sprites.png'), // sprite图片保存路径
css: path.resolve(__dirname, 'src/assets/_sprites.scss') // 生成的sass保存在哪里(也可以后缀改成.css 直接生成css文件,在文件中直接使用对应的类名即可)
},
apiOptions: {
cssImageRef: "sprite.png" //css根据该指引找到sprite图
}
})
]
}
注:这是纯webpack的配置的情况 , 现在很多项目才用create-reactp-app 方式创建的 ,上面配置的中rules 部分已经嵌入,可以省略。
下面执行npm start 命令 会在sprite文件夹生成 sprite.png sprite.scss
除了 对应的数据外,sass文件中自动生成 mixin 如下
//webpack 自动生成的scss文件
$icon1-name: 'icon1';
$icon1-x: 0px;
$icon1-y: 0px;
$icon1-offset-x: 0px;
$icon1-offset-y: 0px;
$icon1-width: 32px;
$icon1-height: 32px;
$icon1-total-width: 158px;
$icon1-total-height: 32px;
$icon1-image: '../sprite/sprite.png';
$icon1: (0px, 0px, 0px, 0px, 32px, 32px, 158px, 32px, '../sprite/sprite.png', 'icon1', );
//数据略...
@mixin sprite($sprite) {
@include sprite-image($sprite);
@include sprite-position($sprite);
@include sprite-width($sprite);
@include sprite-height($sprite);
}
在 自己的sass文件中 如下引用 就可以快乐的使用了 ,
//直接在页面中引入的scss文件
@import '../sprite/sprite.scss';
//生成的尺寸默认是原图大小 如何动态的缩放图片 如下
@mixin spriteScale($sprite,$scale) {
$spriteScaled: ();
$scaleItems: (3, 4, 5, 6, 7, 8);
@for $i from 1 through length($sprite) {
$item: nth($sprite, $i);
@if (null != index($scaleItems, $i)) {
$spriteScaled: append($spriteScaled, $item * $scale);
} @else {
$spriteScaled: append($spriteScaled, $item);
}
}
@include sprite($spriteScaled);
background-size: nth($spriteScaled, 7) nth($spriteScaled, 8);
}
//注释: spriteScale 把雪碧图位置以及size涉及的尺寸 scale同样的倍数
@mixin sprite_dynamic ($arg1,$arg2,$scale){
@include spriteScale($arg1 ,$scale)
@media (-webkit-min-device-pixel-ratio:3),(min-device-pixel-ratio: 3){
@include spriteScale($arg2 ,$scale)
}
}
注释:sprite_dynamic 通过@media查询 ,加载2X图或者3X ,$arg1 $arg2,$scale 分别是 2X 3X图变量名 缩放倍率,具体用法如下
.icon1{
@include sprite_dynamic($wifi_2X,$wifi_3X ,1);
}
注释 :最后在需要的类里面引用 $wifi_2x $window_3X
保存刷新页面 ,图片有显示了,但是此时network一个图片请求都没有了,在看element dom节点,webpack 把背景图片转码为base64
这样以后添加 或者去掉一个图标,只更改少量代码,运行npm runbuild 或者npm start 就ok 的
动态加载 2X &3X图 原理如下 动态加载2X&3X