10

前言

最近项目中在使用webpack,css是采用sass->postcss的结构, postcss 主要完成了下面几个功能

  1. autoprefix,样式加前缀

  2. preces

  3. 合并图片

        1) 可以合并多张雪碧图
        2) 可以按照不同的比例合并图片
        3) 对一些简单的图片可以使用base64编码
        
  4. 兼容IE浏览器

  5. 后期需要将px转换为em,使用media-query做屏幕适配

其他功能都比较容易实现,现成的插件都能满足,合并图片现在使用的是sprites,有一些编码,在这里先贴出来

webpack.config.js

let postcssSprites = require('postcss-sprites');
let sprites = postcssSprites.default;
let precss = require('precss');
let assets = require('postcss-assets');
let autoprefixer = require('autoprefixer');

{

postcss: [
        autoprefixer,
        precss,
        assets({//主要是用来做base64编码的
            basePath: __dirname + '/client',
            relative: false
        })
    ]
}

//雪碧图相关代码
let spritesConfig = sprites({
    retina: true,//支持retina,可以实现合并不同比例图片
    verbose: true,
    spritePath: './public/images/',//雪碧图合并后存放地址
    stylesheetPath: './public',
    basePath: './',
    filterBy: function (image) {
        //过滤一些不需要合并的图片,返回值是一个promise,默认有一个exist的filter
        //
        if (image.url.indexOf('/images/sprites/') === -1) {
            return Promise.reject();
        }
        return Promise.resolve();
    },
    groupBy: function (image) {
        //将图片分组,可以实现按照文件夹生成雪碧图
        return spritesGroupBy(image);
    },
    hooks: {
        onUpdateRule: function (rule, comment, image) {
            //更新生成后的规则,这里主要是改变了生成后的url访问路径
            return spritesOnUpdateRule(true, rule, comment, image);
        },
        onSaveSpritesheet: function(opts, groups) {
            return spritesOnSaveSpritesheet(true, opts, groups);
        }
    }
});

export function spritesGroupBy(image) {

   let groups = /\/images\/sprites\/(.*?)\/.*/gi.exec(image.url);
    let groupName = groups ? groups[1] : group;
    image.retina = true;
    image.ratio = 1;
    if (groupName) {
        let ratio = /@(\d+)x$/gi.exec(groupName);
        if (ratio) {
            ratio = ratio[1];
            while (ratio > 10) {
                ratio = ratio / 10;
            }
            image.ratio = ratio;
        }
    }
    return Promise.resolve(groupName);
}

export function spritesOnUpdateRule(isDev, rule, comment, image){
    var spriteUrl = image.spriteUrl;
    image.spriteUrl = '/public/' + spriteUrl;
    postcssSprites.updateRule(rule, comment, image);
}

export function spritesOnSaveSpritesheet(isDev, opts, groups) {
    let file = postcssSprites.makeSpritesheetPath(opts, groups);
    return file;
}




效果

--images
  --sprites
      --smiley@2x
      --smiley@3x
    
    生成后的雪碧图sprite.smiley@2x.png,sprite.smiley@3x.png
    假设原图片64*64,项目中想使用的大小是32*32,就把原图片放在@2x的文件夹下面
    
    相关sass代码如下
    @for $i from 1 through 4 {
       .icon-smiley-#{$i} {
        width: 24px;
        height: 24px;
        background-image: url('/images/sprites/smiley@2x/smiley_#{$i}.png');
      }
   }
   
   编译后
   
    .icon-smiley-0 {
        width: 24px;
        height: 24px;
        background-position: -24px -48px;
        background-image: url('/public/sprite.smiley@2x.png');
      }
      

遇到的一些坑

  1. 本来css不想使用sass的,存粹使用postcss,但是postcss不能检测内部文件的改动,导致webpack不能自动编译

    比如我的主文件main.css里面
    @import 'page.css'
    这时候我修改page.css后,webpack不会自动编译
    但是修改main.css,webpack可以自动编译,
    网上找了一些资料,也没有最终解决问题,
    
  2. 其他坑还没碰到。。。


qinghui
164 声望8 粉丝

码农一枚,目前在美团做前端工作