博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
webpack雪碧图生成
阅读量:5771 次
发布时间:2019-06-18

本文共 2709 字,大约阅读时间需要 9 分钟。

腾讯DeepOcean原创文章:

前言

在HTTP/2.0还没有普及的现在,css sprite(雪碧图)仍是前端工程化中必备的一环,而随着webpack应用的普及,构建工具切换到webpack后雪碧图该如何处理呢?

目标

先说下我们希望达到的效果。

1、需要合成的雪碧图icon统一放在src / assets / sprite文件夹下

2、在src / img 会生成一份以上级目录名称命名的雪碧图,如icon文件夹中用到的图标拼合成icon.png

3、雪碧图从上到下的方式排列,并且每个图标间隔20px,如图所示

4、在sass中编写,按需合并。

5、编译后得到的样式如下,包括width、height也一同输出

 

常见方案

目前主要的解决方案有两种

一种是以webpack-spritesmith、postcss-sprites为代表的插件,webpack-spritesmith主要的运行方式是会预先把sprite目录中的图标拼合好,页面主要依赖生成后的雪碧图。而postcss-sprites则是通过对已经生成的 CSS 文件进行分析,将其中的 background 或 background-image 作为依赖收集,合并成雪碧图后再将相关参数替换。

第二种是loader处理方式,不过网上基本上没有很好的方案,比如说这种

这种通过注释的方式来识别并不是很好。

目前市面上的方案都不能满足我们的个性化要求,相对于插件针对某一文件夹/文件处理方式,我们更希望采用loader链式处理的方式来实现。

解决方案

采用loader的话只能通过添加标记的方式告知需要合成,比如在background url加上“?_sprite”,然后利用正则获取图片路径,给到相关的库去合成。

这里主要利用spritesmith开源项目来进行开发,spritesmith很强大,它可以比较灵活的合成雪碧图,通过相应的API可以获得图标的相关信息。

其中sprites是需要被合成的图片路径,里面包含了图标的绝对路径

  1. Spritesmith.run({
    src: sprites,algorithm:'top-down',padding: 20}, function handleResult (err, result) {
  2.    if(err) {
  3.        throw err;
  4.    }
  5. });            
另外还提供了多种排列的规则,以及可以设置图片间的间距
  1. Spritesmith.run({
    src: sprites,algorithm:'top-down',padding: 20}, function handleResult (err, result) {
  2.    if(err) {
  3.        throw err;
  4.    }
  5. });  
打印result可以看到返回的数据主要包括图片的绝对路径,坐标、宽高以及雪碧图的Buffer

利用这些信息我们可以对返回的样式进行重新处理,满足前面第5点的样式要求

  1. let imageW = image.width;
  2. let imageH = image.height;
  3. if(mobile){
  4.    imageW = imageW/2;
  5.    imageH = imageH/2;
  6. }
  7.  
  8. let imgWidth = 'width:' + imageW + 'px;';
  9. let imgHeight = 'height:' + imageH + 'px;';
  10.  
  11. if(i < afterContent.length) {
  12.  
  13.    if(afterContent[i] == ';') {
  14.        end = i + 1;
  15.        afterContent = afterContent.substring(0, end) + backgroundSize+ imgWidth+ '\n' + imgHeight + afterContent.substring(end);
  16.    } else {
  17.        end = i;
  18.        afterContent = afterContent.substring(0, end) + ';\n' +  backgroundSize +imgWidth+ '\n' + imgHeight+ afterContent.substring(end);
  19.    }
  20.  
  21. }
  22. let imagePosX = image.x;
  23. let imagePosY = image.y;
  24. if(mobile){
  25.    imagePosX = imagePosX/2;
  26.    imagePosY = imagePosY/2;
  27. }
  28. let imageX = image.x == 0 ? ' 0' : ' -' + imagePosX + 'px';
  29. let imageY = image.y == 0 ? ' 0' : ' -' + imagePosY + 'px';
  30. let imagePosition = '';
  31. if(image.x || image.y){
  32.    imagePosition = imageX + imageY;
  33. }
  34.  
  35. let cssVal = 'url("' + spriteRelativePath + '")' + imagePosition;
一般项目中的h5采用的都是双倍图,这里可以增加个判断,如果h5的话则width、height、background-size都减半处理
  1. module:{
  2.      rules:[
  3.          {
  4.              test:/\.(scss|css)$/,
  5.              use: ExtractTextPlugin.extract({
  6.                fallback: "style-loader",
  7.                publicPath: '../../',
  8.                use: [{
  9.                  loader:'css-loader'
  10.                },{
  11.                  loader:'isprite-loader',
  12.                  options:{
  13.                    outputPath:'./src/assets/img/',
  14.                    mobile:true
  15.                  }
  16.                },{
  17.                  loader:'sass-loader'
  18.                }],
  19.              })
  20.          },
  21.      ]
  22. }
 

最后

到这里已经基本能达到预期的效果,不过仍有些问题没有处理好,比如每次都会生成雪碧图,这对于编译速度会有一定的影响,针对这种问题,可以采用hash值进行对比,如果文件没有改动的话则不处理。

每一个业务都有不同的需求场景,这种方式可能不一定适用于其他项目,希望对大家有所帮助。

附上demo

欢迎关注"腾讯DeepOcean"微信公众号,每周为你推送前端、人工智能、SEO/ASO等领域相关的原创优质技术文章:

看小编搬运这么辛苦,关注一个呗:)

转载地址:http://ohaux.baihongyu.com/

你可能感兴趣的文章
nginx在响应request header时候带下划线的需要开启的选项
查看>>
Linux下DHCP服务器配置
查看>>
AndroidStudio中导入SlidingMenu报错解决方案
查看>>
我的IDEA配置
查看>>
myeclipse显示行号
查看>>
编写高性能的java程序
查看>>
Spring 的配置详解
查看>>
linux已经不存在惊群现象
查看>>
上位机和底层逻辑的解耦
查看>>
关于微信二次分享 配置标题 描述 图片??
查看>>
springcloud使用zookeeper作为config的配置中心
查看>>
校园火灾Focue-2---》洗手间的一套-》电梯
查看>>
css控制文字换行
查看>>
bzoj1913
查看>>
L104
查看>>
分镜头脚本
查看>>
链表基本操作的实现(转)
查看>>
邮件发送1
查看>>
[转] libcurl异步方式使用总结(附流程图)
查看>>
编译安装LNMP
查看>>