gzip、cssnano、uglifyjs压缩原理

201 阅读3分钟

gzipcssnanouglifyjs压缩原理

gzip 压缩算法

Lempel-Ziv coding (LZ77) 算法Huffman 编码来压缩文件

  • LZ77 算法检测重复的数据序列,并用偏移量和长度代替重复数据。
  • Huffman 编码进一步压缩数据,通过使用更短的位序列表示更频繁出现的数据模式。

具体的可以再次详细查找资料 看视频可能更容易理解,文字描述起来比较复杂还难以理解,如果需要可以留言,之后会尽量整理一下。

cssnano 压缩原理

cssnano主要通过 移除不必要的字符合并选择器简化颜色值等,从而减小文件大小而不影响最终样式的表现。 cssnano 的压缩算法概览:

  1. 语法分析: 首先,cssnano 读取 CSS 文件并使用 PostCSS 的解析器将其转换成一个 AST。PostCSS 使用 postcss-safe-parser 或 postcss-css-in-js 等解析器来完成这项工作。
  2. 插件优化: cssnano 会应用一系列 PostCSS 插件来优化 AST。这些插件执行不同的任务,比如:
    • 清理无用规则: 移除未使用的 CSS 规则, 清理空规则集。
    • 移除注释和空白: 删除所有 CSS 注释, 最小化空白字符,包括行尾空白。
    • 简化选择器和属性: 合并相似的选择器, 简化颜色值(例如,将 #ffffff 缩短为 #fff), 使用更短的语法替代较长的语法(例如,将 border: none 替换为 border: 0)。
    • 优化字体图标: 对于使用字体图标的 CSS,可以进行特定优化。
    • 移除冗余前缀: 移除不需要的浏览器前缀。
    • 转换属性值: 将某些属性值转换为更简短的形式(例如,background-position: 0 0 可以变为 background-position: 0)。
    • 其他优化: 转换长度单位(例如,从 px 到 em), 简化函数调用(例如,将 rgba(255, 255, 255, 1) 转换为 #fff)。
  3. 代码生成: 经过优化之后,cssnano 会将修改后的 AST 重新生成为压缩后的 CSS 文件。这一步通常会去除空白字符、注释以及不必要的分号等。

uglifyjs 原理

  1. 语法分析: 对原文件进行语法分析,生成 AST
  2. 语义分析: 对 AST 进行分析,包括但不限于变量作用域和类型推断等,这一步骤有助于确定哪些代码可以安全地被压缩或转换。
  3. 代码转换: UglifyJS 应用一系列转换规则来修改 AST 比如:
    • 死代码消除 :删除那些永远不会被执行的代码。
    • 常量折叠 :计算静态表达式的值。
    • 条件简化 :简化条件表达式。
    • 变量重命名 :将长变量名替换为单个字符或其他简短的标识符。
    • 内联函数 :替换函数调用为函数体,减少函数调用的开销。
    • 循环展开 :减少循环中的迭代次数,以减少循环控制结构的开销。
  4. 代码生成: UglifyJS 重新生成源代码,这个新生成的源代码就是压缩后的版本,这个过程中还会进行一些优化,例如移除不必要的空格、注释和换行等。

拓展

MiniCssExtract-webpack-plugin 的作用

MiniCssExtract-webpack-plugin 主要作用是提取模块中的 css 代码到单独的文件中, MiniCssExtractPlugin.loader 的主要作用是将模块中的 css 分离出来,供 MiniCssExtractPlugin 进行可以提取,生成单独的 css 文件,自动在 HTML 文件中插入 <link> 标签指向生成的 CSS 文件

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
 // ...
 module: {
   rules: [
     {
       test: /.css$/,
       use: [
          MiniCssExtractPlugin.loader, // 用于提取 CSS 到单独的文件
          "css-loader", // 解析 CSS 文件
          "postcss-loader", // 运行 PostCSS 插件
        ],
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: "[name].[contenthash].css",
      chunkFilename: "[id].[contenthash].css",
    }),
  ],
  // ...
};

MiniCssExtract-webpack-plugin 配合optimize-css-assets-webpack-plugin 或者 css-minimizer-webpack-plugin 或者 cssnano 一起使用进行 css 压缩并提取单独的文件 这个插件使用 cssnano 优化和压缩 CSS。

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');

module.exports = {
 // ...
 module: {
    rules: [
      {
        test: /.s?css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
      },
    ],
  },
 optimization: {
    minimizer: [
      // 在 webpack@5 中,你可以使用 `...` 语法来扩展现有的 minimizer(即 `terser-webpack-plugin`),将下一行取消注释
      // `...`,
      new CssMinimizerPlugin(),
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: "[name].css",
      chunkFilename: "[id].css"
    })
  ],
  // ...
};

小小结

粗略的介绍了一下它们,让大家有一个大概的了解,之后再深入了解,比如源码的实现,AST树的了解等。