针对历史项目或项目中有引入CSS框架(如Bootstrap),可能会存在大量的 CSS 样式未被使用。这可能产生一些不良的影响,如:
在这里插入图片描述

  • 性能问题: 未使用的CSS会增加页面的加载时间,因为浏览器需要下载并解析这些不必要的样式表。这会导致页面加载速度变慢,影响用户体验,尤其是在低网络速度或较弱的设备上。
  • 影响加载速度: 未使用的CSS会增加样式表的文件大小,从而占用更多的带宽和存储空间。这对于移动设备用户或网络流量有限的用户来说可能是一个问题。
  • 可维护性下降: 当项目中存在大量无用的冗余样式时,代码库的整体可读性和可维护性都会下降。开发人员可能会在不确定哪些样式正在使用的情况下进行更改,这可能导致样式冲突和不一致。

如何解决呢?推荐三款工具,可根据项目情况进行选型:

PurgeCSS

PurgeCSS 通过分析你的内容和 CSS 文件,首先它将 CSS 文件中使用的选择器与内容文件中的选择器进行匹配,然后它会从 CSS 中删除未使用的选择器,从而生成更小的 CSS 文件。

// webpack
const path = require('path')
const glob = require('glob')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const PurgecssPlugin = require('purgecss-webpack-plugin')

const PATHS = {
  src: path.join(__dirname, 'src')
}

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.join(__dirname, 'dist')
  },
  optimization: {
    splitChunks: {
      cacheGroups: {
        styles: {
          name: 'styles',
          test: /\.css$/,
          chunks: 'all',
          enforce: true
        }
      }
    }
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          "css-loader"
        ]
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: "[name].css",
    }),
    new PurgecssPlugin({
      paths: glob.sync(`${PATHS.src}/**/*`,  { nodir: true }),
    }),
  ]
}

UnCSS

UnCSS 的工作方式如下:

  • 由 jsdom 加载 HTML 文件并执行 JavaScript 代码。
  • PostCSS 解析所有样式表
  • 通过 document.querySelector 筛选出 HTML 文件中未找到的选择器。
  • 将其余的样式规则转换回 CSS 代码。

由于其能够模拟 HTML 和 JavaScript 的执行,UnCSS 可以有效地从 web 应用程序中删除未使用的选择器。

但是,其模拟行为可能会在性能和实用性方面带来成本消耗。例如,要从 Pug 模板文件中删除未使用的 CSS,你需要将 Pug 转换为 HTML 并在 jsdom 中模拟页面。完成此步骤后,UnCSS 可以在每个选择器上运行 document.querySelector 并执行步骤 4。

目前,在删除未使用的 CSS 方面,UnCSS 在某些情况下可能是最准确的工具。如果你不使用服务器端渲染(server-side rendering),并且网站上只有简单的 HTML 和 javascript的话,则它应该可以正常工作,并且在 CSS 文件大小方面要优于 PurgeCSS。

PurgeCSS 针对 JavaScript 文件提供了一个提取器(extractor),目标是提供更准确的结果,这将在生成的 CSS 文件大小方面优于 UnCSS。由于 PurgeCSS 是模块化的,开发人员可以为特定框架(Vue、React、Aurelia)和文件类型(pug、ejs)创建提取器。这样,无需模拟(HTML 和 JavaScript 的执行)即可获得最准确的结果。

// postcss
postcss([require('uncss').postcssPlugin]);

PurifyCSS

PurifyCSS 可以支持任何文件类型,而不仅仅是 HTML 或 JavaScript。

PurifyCSS 的工作原理是查看文件中的所有单词,并将它们与 CSS 中的选择器进行比较。每个单词都被视为选择器,这意味着可能会错误地找到许多选择器。例如,有可能碰巧在一个段落中存在一个单词与 CSS 中的选择器相同。

PurgeCSS 通过支持自定义提取取器(extractor)来解决此问题。提取器是一个函数,它的作用是根据文件内容提取文件中使用所有的 CSS 选择器。它可以完美地删除未使用的 CSS。

提取器可用作解析器,该解析器返回 AST(抽象语法树)并在其中查找所有 CSS 选择器。这也是 purge-from-html 的工作方式。

你可以指定每种文件类型要使用的提取器,以获得最准确的结果。但是自定义提取器是可选的,你可以只使用默认的提取器。

// webpack相关配置
const path = require('path');
const glob = require('glob');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const PurifyCSSPlugin = require('purifycss-webpack');

module.exports = {
  entry: {...},
  output: {...},
  module: {
    rules: [
      {
        test: /\.css$/,
        loader: ExtractTextPlugin.extract({
          fallbackLoader: 'style-loader',
          loader: 'css-loader'
        })
      }
    ]
  },
  plugins: [
    new ExtractTextPlugin('[name].[contenthash].css'),
    // Make sure this is after ExtractTextPlugin!
    new PurifyCSSPlugin({
      // Give paths to parse for rules. These should be absolute!
      paths: glob.sync(path.join(__dirname, 'app/*.html')),
    })
  ]
};
Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐