craco 中的图片处理

使用 craco 覆盖框架默认的 webpack 配置

从前我以为 HTTP/2 开启以后,雪碧图可以逐渐退出舞台,现在感觉到自己的天真。且不论 svg 如果做成雪碧图可以通过 gzip 受益不少,多个单张的 png 还是比起一张要浪费请求。

  1. 雪碧图 使用插件 webpack-spritesmith,该插件的原理是,监听目标文件夹中的图片变化,根据开发者设定的规则,生成对应的雪碧图和样式。 我们的项目有 2x 和 3x 的图片,需要生成两张雪碧图和两份 css 文件。思路:将 2x 和 3x 资源分开放,写两套规则来生成两组文件。 生成雪碧图还有另一种原理,是反过来的,找到样式文件中用到图片,再合成雪碧图,比如 postcss-sprite,如果是使用大量图片资源的项目,建议使用这种方法,不容易产生冗余代码和图片。
// craco.config.js

const SpritesmithPlugin = require("webpack-spritesmith");
...

const templateFunction = function(data) {
  const ratio = data.sprites[0].name.split("@")[1].split("x")[0] || 1;

  // 2x 配置
  let shared = ".ico { display: inline-block; background-image: url(I); background-size: Dpx Hpx; }"
    .replace("I", data.sprites[0].image)
    .replace("D", data.sprites[0].total_width / ratio)
    .replace("H", data.sprites[0].total_height / ratio);

  let perSprite = data.sprites
    .map(function(sprite) {
      let name = sprite.name.split("@")[0].replace(/_/g, "-");
      return ".ico-N { width: Wpx; height: Hpx; background-position: Xpx Ypx; }"
        .replace("N", name)
        .replace("W", sprite.width / ratio)
        .replace("H", sprite.height / ratio)
        .replace("X", sprite.offset_x / ratio)
        .replace("Y", sprite.offset_y / ratio);
    })
    .join("\n");

  // mq 配置
  let result = {
    x2: `${shared}\n${perSprite}\n`, // 默认使用 2x
    x3: `@media only screen and (-o-min-device-pixel-ratio: 9/4),
          only screen and (-webkit-min-device-pixel-ratio: 2.25),
          only screen and (min-device-pixel-ratio: 2.25),
          only screen and (min-resolution: 2.25dppx) {\n${shared}\n${perSprite}\n}`
  };

  if (ratio != 3) {
    return result.x2;
  } else {
    return result.x3;
  }
};

...

// 注!以下配置大部分来自 https://www.chauncywu.com/?p=232
// 两套配置有很多重复的地方,应该不少也能提成统一的变量
const webpack = {
  ...
	plugins: [
		new SpritesmithPlugin({
      src: {
        cwd: path.resolve(__dirname, "public/assets/slice/2x"), // 图标根路径
        glob: "*.png" // 图标类型
      },
      target: {
        image: path.resolve(
          __dirname,
          "src/styles/img/sprite2x.png"
        ), // 生成雪碧图的名称和路径
        css: [
          [
            path.resolve(
              __dirname,
              "src/styles/sprite2x.css"
            ),
            {
              // 生成CSS文件的名称和路径
              format: "function_based_template" // 模板配置,注意在customTemplates中配置对应名称的属性名
            }
          ],
          [
            path.resolve(
              __dirname,
              "src/styles/sprite2x.json"
            ),
            {
              // 生成json文件的名称和路径,想看图片数据的可以配置该项
              format: "json_texture"
            }
          ]
        ]
      },
      customTemplates: {
        function_based_template: templateFunction // 上一项使用到的模板变量
      },
      apiOptions: {
        cssImageRef: "./img/sprite2x.png" // 生成的CSS中引用的雪碧图路径
      },
      spritesmithOptions: {
        algorithm: "binary-tree", // 生成的雪碧图图标排列方式
        padding: 2 // 图标的间隔
      }
    }),
    new SpritesmithPlugin({
      src: {
        cwd: path.resolve(__dirname, "public/assets/slice/3x"), // 图标根路径
        glob: "*.png" // 图标类型
      },
      target: {
        image: path.resolve(
          __dirname,
          "src/styles/img/sprite3x.png"
        ), // 生成雪碧图的名称和路径
        css: [
          [
            path.resolve(
              __dirname,
              "src/styles/sprite3x.css"
            ),
            {
              // 生成CSS文件的名称和路径
              format: "function_based_template" // 模板配置,注意在customTemplates中配置对应名称的属性名
            }
          ],
          [
            path.resolve(
              __dirname,
              "src/styles/sprite3x.json"
            ),
            {
              // 生成json文件的名称和路径,想看图片数据的可以配置该项
              format: "json_texture"
            }
          ]
        ]
      },
      customTemplates: {
        function_based_template: templateFunction // 上一项使用到的模板变量
      },
      apiOptions: {
        cssImageRef: "./img/sprite3x.png" // 生成的CSS中引用的雪碧图路径
      },
      spritesmithOptions: {
        algorithm: "binary-tree", // 生成的雪碧图图标排列方式
        padding: 2 // 图标的间隔
      }
    }) 
  ]
}

// craco 的文件入口
module.exports = {
  ...
  webpack
};
  1. 图片压缩 未完

参考资料

  1. 基于Webpack的CSS Sprites实现方案
  2. webpack雪碧图生成
  3. Webpack3之雪碧图插件(WEBPACK-SPRITESMITH配置简述)
  4. add-stylelint/craco.config.js
  5. Media Queries for @2x, @3x, and @4x images

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券