有时候,Webpack打包后文件体积往往会过大,我们可以通过代码压缩的方式来减少Webpack打包后文件的体积。对代码进行压缩不仅可以有效提升网页加载的速度,还具有混淆源码的作用。就算别人下载了网页的代码,由于代码是压缩过的,也就增加了代码分析和改造的难度。

下面,我们逐一介绍如何在 Webpack中压缩代码:

压缩 HTML

在Webpack中,我们都会使用 html-webpack-plugin 插件来自动生成 HTML文件。当我们使用该插件时不配置任何选项,会生成如下未压缩的HTML文件:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Webpack App</title>
  </head>
  <body>
  <script type="text/javascript" src="main.bundle.js"></script></body>
</html>

html-webpack-plugin

html-webpack-plugin 提供的 minify 属性可以帮助我们对生成的 HTML 进行压缩,配置如下:

const htmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
    plugins: [
    new htmlWebpackPlugin({
      template: "./src/index.html", // 读取的模板文件
      filename: "index.html", // 生成的文件
      minify: {
        // 压缩HTML文件
        removeComments: true, // 移除HTML中的注释
        collapseWhitespace: true, // 删除空白符与换行符
        minifyCSS: true, // 压缩内联css
      },
    }),
  ],
};

压缩后的HTML文件如下:

<!DOCTYPE html><html><head><meta charset="UTF-8"><title>Webpack App</title></head><body><script type="text/javascript" src="main.bundle.js"></script></body></html>

压缩CSS

CSS代码也是造成文件体积过大的原因之一,因此,我们也需要对 CSS代码进行压缩。cssnano 是目前比较成熟的 CSS压缩工具。它是基于 PostCSS 的,它会在保持 CSS 代码语义不变的情况下,将多余的空白符及注释删除,对CSS选择器进行压缩,并清理没用的CSS 代码。以确保最终生成的文件对生产环境来说体积是最小的。

/* normalize selectors */
h1::before, h1:before {
    /* reduce shorthand even further */
    margin: 10px 20px 10px 20px;
    /* reduce color values */
    color: #ff0000;
    /* remove duplicated properties */
    font-weight: 400;
    font-weight: 400;
    /* reduce position values */
    background-position: bottom right;
    /* normalize wrapping quotes */
    quotes: '«' "»";
    /* reduce gradient parameters */
    background: linear-gradient(to bottom, #ffe500 0%, #ffe500 50%, #121 50%, #121 100%);
    /* replace initial values */
    min-width: initial;
}
/* correct invalid placement */
@charset "utf-8";

上面是一段未压缩过的CSS代码,使用 cssnano 进行压缩后的代码如下:

@charset "utf-8";h1:before{margin:10px 20px;color:red;font-weight:400;background-position:100% 100%;quotes:"«" "»";background:linear-gradient(180deg,#ffe500,#ffe500 50%,#121 0,#121);min-width:0}

optimize-css-assets-webpack-plugin

把 cssnano 接入到Webpack 中十分简单,在Webpack4 中我们使用 optimize-css-assets-webpack-plugin 插件,并在其实例对象中配置 cssProcessor ,将其压缩引擎指定为 cssnano 。配置代码如下:

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const htmlWebpackPlugin = require("html-webpack-plugin");
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");

module.exports = {
  module: {
    rules: [
      {
        test: /\.less$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              publicPath: "../",
            },
          },
          "css-loader",
          "postcss-loader",
          "less-loader",
        ],
      },
    ],
  },

  plugins: [
    new htmlWebpackPlugin({
      template: "./src/index.html",
      filename: "index.html",
      minify: {
        // 压缩HTML文件
        removeComments: true, // 移除HTML中的注释
        collapseWhitespace: true, // 删除空白符与换行符
        minifyCSS: true, // 压缩内联css
      },
    }),
    new MiniCssExtractPlugin({
      filename: "css/[name]-[contenthash:6].css", // 给输出的 CSS 文件加上 Hash 值
    }),
    new OptimizeCSSAssetsPlugin({
      cssProcessor: require("cssnano"), // 这里制定了引擎,不指定默认也是 cssnano
    }),
  ],
};

在 Webpack 中使用 cssnano 的另一种方式是开启 css-loader 的 minimize 选项。相关Webpack配置如下:

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const htmlWebpackPlugin = require("html-webpack-plugin");
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");

module.exports = {
  module: {
    rules: [
      {
        test: /\.less$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              publicPath: "../",
            },
          },
          {
            loader: 'css-loader',
            options: {
              minimize: true || {/* CSSNano Options */}
            }
          },
          "postcss-loader",
          "less-loader",
        ],
      },
    ],
  },

  plugins: [
    new htmlWebpackPlugin({
      template: "./src/index.html", // HTML 模板文件所在的路径
      filename: "index.html", // 输出的 HTML文件名称
      minify: {
        // 压缩HTML文件
        removeComments: true, // 移除HTML中的注释
        collapseWhitespace: true, // 删除空白符与换行符
        minifyCSS: true, // 压缩内联css
      },
    }),
    new MiniCssExtractPlugin({
      filename: "css/[name]-[contenthash:6].css", // 给输出的 CSS 文件加上 Hash 值
    }),
    new OptimizeCSSAssetsPlugin({
      cssProcessor: require("cssnano"), // 这里制定了引擎,不指定默认也是 cssnano
    }),
  ],
};

压缩 JavaScript

terser-webpack-plugin

业界中比较成熟的 JavaScript 代码压缩工具是 UglifyJS,它会分析 JavaScript 代码语法树,理解代码含义,能做到去掉无效代码、去掉日志输出代码、缩短变量名等优化。但该工具在 ES6 代码压缩上做的不够好,于是有了 uglify-es,但 uglify-es 已经不再维护了。因此我们推荐使用 terser-webpack-plugin,它是从 uglify-es 拉出来的一个分支,是 Webpack 官方维护的插件。

安装方法如下:

npm install terser-webpack-plugin --save-dev

Webpack 相关配置如下:

const TerserPlugin = require("terser-webpack-plugin");

module.exports = {
  entry: {
    "add-number": "./src/index.js",
    "add-number.min": "./src/index.js",
  },
  output: {
    filename: "[name].js", // 指定打包出来的文件名称
    library: "addNumber",  // 指定打包出来的库的名称
    libraryTarget: "umd", // 指定打包出来的规范
    libraryExport: "default", //必要
  },
  mode: "none",
  optimization: {
    minimize: true,
    minimizer: [
      // 使用 terser-webpack-plugin 压缩 JavaScript
      new TerserPlugin({
        test: /\.min\.js$/, // 指定只有 min.js 的文件才压缩
      }),
    ],
  },
};

以上就是Webpack中代码压缩常用的几种方式。