本节课会讲述webpack4中的图片常用的基础操作:

  • 图片处理 和 64编码
  • 图片压缩
  • 合成雪碧图

1. 准备工作

如项目代码目录展示的那样,除了常见的app.js作为入口文件,我们将用到的 3 张图片放在/src/assets/img/目录下,并在样式文件 .css中引用这些图片。

剩下的内容交给webpack打包处理即可。样式文件和入口 js 文件的代码分别如下所示:

/*  .css */
*, body {
  margin: 0;
  padding: 0;
}
.box {
  height: 400px;
  width: 400px;
  border: 5px solid #000;
  color: #000;
}
.box div {
  width: 100px;
  height: 100px;
  float: left;
}
.box .ani1 {
  background: url(\"./../assets/imgs/1.jpg\") no-repeat;
}
.box .ani2 {
  background: url(\"./../assets/imgs/2.jpg\") no-repeat;
}
.box .ani3 {
  background: url(\"./../assets/imgs/3.png\") no-repeat;
}
// app.js
import \"style-loader/lib/addStyles\";
import \"css-loader/lib/css- \";

import \"./css/ .css\";

在处理图片和进行 64编码的时候,需要使用url-loader

在压缩图片的时候,要使用img-loader插件,并且针对不同的图片类型启用不同的子插件。

postcss-loaderpostcss-sprites则用来合成雪碧图,减少网络请求。

因此,在 npm 安装完相关插件后,package.json的内容如下所示:

{
  \"devDependencies\": {
    \"css-loader\": \"^1.0.0\",
    \"extract-text-webpack-plugin\": \"^4.0.0-beta.0\",
    \"file-loader\": \"^1.1.11\",
    \"imagemin\": \"^5.3.1\",
    \"imagemin-pngquant\": \"^5.1.0\",
    \"img-loader\": \"^3.0.0\",
    \"postcss-loader\": \"^2.1.6\",
    \"postcss-sprites\": \"^4.2.1\",
    \"style-loader\": \"^0.21.0\",
    \"url-loader\": \"^1.0.1\",
    \"webpack\": \"^4.16.1\"
  }
}

同时,我们编写如下index.html(假设已经打包好了项目文件,现在直接引入):

<!DOCTYPE html>
<html lang=\"en\">
<head>
  <  charset=\"UTF-8\">
  <  name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">
  <  http-equiv=\"X-UA-Compatible\" content=\"ie=edge\">
  < >Document</ >
  <  rel=\"stylesheet\" href=\"./dist/app.min.css\">
</head>
<body>
  <div id=\"app\">
    <div class=\"box\">
      <div class=\"ani1\"></div>
      <div class=\"ani2\"></div>
      <div class=\"ani3\"></div>
    </div>
  </div>
  <  src=\"./dist/app.bundle.js\"></ >
</body>
</html>

2. 图片处理 和 64 编码

2.1 webpack 配置

为了方便样式提取,还是利用extract-text-webpack-plugin来提取样式文件。

同时,在module.rules选项中进行配置,以实现让 loader 识别图片后缀名,并且进行指定的处理操作。

代码如下:

// webpack.config.js

const path = require(\"path\");
const ExtractTextPlugin = require(\"extract-text-webpack-plugin\");

let extractTextPlugin = new ExtractTextPlugin({
  filename: \"[name].min.css\",
  allChunks: false
});

module.exports = {
  entry: {
    app: \"./src/app.js\"
  },
  output: {
    publicPath: __dirname + \"/dist/\",
    path: path.resolve(__dirname, \"dist\"),
    filename: \"[name].bundle.js\",
    chunkFilename: \"[name].chunk.js\"
  },
  module: {
    rules: [
      {
        test: /.css$/,
        use: ExtractTextPlugin.extract({
          fallback: {
            loader: \"style-loader\"
          },
          use: [
            {
              loader: \"css-loader\"
            }
          ]
        })
      },
      {
        test: /.(png|jpg|jpeg|gif)$/,
        use: [
          {
            loader: \"url-loader\",
            options: {
              name: \"[name]-[hash:5].min.[ext]\",
              limit: 20000, // size <= 20KB
              publicPath: \"static/\",
              outputPath: \"static/\"
            }
          }
        ]
      }
    ]
  },
  plugins: [extractTextPlugin]
};

通过配置url-loader的 limit 选项,可以根据图片大小来决定是否进行 64编码。这次配置的是:小于 20kb 的图片进行 64编码。

2.2 打包结果

之前提到过,在项目中引入了 3 张图片,其中3.png是小于 20kb 的图片。在命令行中运行webpack进行打包,size 小于 20kb 的图片被编码,只打包了 2 个 size 大于 20kb 的图片文件:

打开浏览器的控制台,我们的图片已经被成功编码:

3. 图片压缩

3.1 压缩配置

图片压缩需要使用img-loader,除此之外,针对不同的图片类型,还要引用不同的插件。比如,我们项目中使用的是 png 图片,因此,需要引入imagemin-pngquant,并且指定压缩率。

我们只需要在上面的配置文件中将下方代码:

// ...
{
  test: /.(png|jpg|jpeg|gif)$/,
  use: [
    {
      loader: \"url-loader\",
      options: {
        name: \"[name]-[hash:5].min.[ext]\",
        limit: 20000, // size <= 20KB
        publicPath: \"static/\",
        outputPath: \"static/\"
      }
    }
  ]
}
// ...

替换为下方代码即可,因为执行顺序问题,我们将 url-loader 的 limit 设置成 1kb,来防止压缩后的 png 图片被 64 编码:

// ...
{
  test: /.(png|jpg|jpeg|gif)$/,
  use: [
    {
      loader: \"url-loader\",
      options: {
        name: \"[name]-[hash:5].min.[ext]\",
        limit: 1000, // size <= 1KB
        publicPath: \"static/\",
        outputPath: \"static/\"
      }
    },
    // img-loader for zip img
    {
      loader: \"img-loader\",
      options: {
        plugins: [
          require(\"imagemin-pngquant\")({
            quality: \"80\" // the quality of zip
          })
        ]
      }
    }
  ]
}
// ...

3.2 打包结果

运行 webpack 打包,查看打包结果:

是的,如你所见,10.5kb 大小的迅雷图标,被压缩到了 1.8kb。图片信息可以去 github 上查看,在文章开头有提及 github 地址。

3.3 遗留问题

并没有解决jpg格式图片压缩。根据img-loader的官方文档,安装了imagemin-mozjpeg插件。

但是这个插件的最新版本是7.0.0,然而配置后,webpack 启动会用报错。

查看了 github 上的 issue,我将版本回退到6.0.0。可以安装,也可以配置运行,正常打包。但是打包后的 jpg 图片大小并没有变化,也就是说,并没有被压缩!!!

希望有大佬可以指点一下小生,万分感谢

4. 合成雪碧图

4.1 webpack 配置

在之前的基础上,配置还是很简单的,loader 的引入和环境变量都在注释里面了:

const path = require(\"path\");
const ExtractTextPlugin = require(\"extract-text-webpack-plugin\");

let extractTextPlugin = new ExtractTextPlugin({
  filename: \"[name].min.css\",
  allChunks: false
});

/*********** sprites config ***************/
let spritesConfig = {
  spritePath: \"./dist/static\"
};
/******************************************/

module.exports = {
  entry: {
    app: \"./src/app.js\"
  },
  output: {
    publicPath: __dirname + \"/dist/\",
    path: path.resolve(__dirname, \"dist\"),
    filename: \"[name].bundle.js\",
    chunkFilename: \"[name].chunk.js\"
  },
  module: {
    rules: [
      {
        test: /.css$/,
        use: ExtractTextPlugin.extract({
          fallback: {
            loader: \"style-loader\"
          },
          use: [
            {
              loader: \"css-loader\"
            },
            /*********** loader for sprites ***************/
            {
              loader: \"postcss-loader\",
              options: {
                ident: \"postcss\",
                plugins: [require(\"postcss-sprites\")(spritesConfig)]
              }
            }
            /*********************************************/
          ]
        })
      },
      {
        test: /.(png|jpg|jpeg|gif)$/,
        use: [
          {
            loader: \"url-loader\",
            options: {
              name: \"[name]-[hash:5].min.[ext]\",
              limit: 10000, // size <= 20KB
              publicPath: \"static/\",
              outputPath: \"static/\"
            }
          },
          {
            loader: \"img-loader\",
            options: {
              plugins: [
                require(\"imagemin-pngquant\")({
                  quality: \"80\"
                })
              ]
            }
          }
        ]
      }
    ]
  },
  plugins: [extractTextPlugin]
};

4.2 效果展示

按照我们的配置,打包好的雪碧图被放入了/dist/static/目录下,如下图所示:

4.3 雪碧图的实际应用

雪碧图是为了减少网络请求,所以被处理雪碧图的图片多为各式各样的 logo 或者大小相等的小图片。而对于大图片,还是不推荐使用雪碧图。

除此之外,雪碧图要配合 css 代码进行定制化使用。要通过 css 代码在雪碧图上精准定位需要的图片(可以理解成从雪碧图上裁取需要的图片),更多可以百度或者 google。

收藏 打印