zzxworld

使用 PurgeCSS 精简 CSS 代码

对于 Web 前端界面,我已经习惯于使用 Bootstrp。好处是能够快速的搭建产品原型界面,问题是即便一个很小的项目,也不得不引入一百多千字节(KB)的样式文件。虽然使用压缩技术可以降低传输大小并提升加载速度,但治标不治本。因为那些没有用到的 CSS 代码依然还在传输和加载。PurgeCSS 是一个能移除未使用 CSS 的前端工具,能显著降低 CSS 代码体积。

关于精简 CSS 代码的功能,我在昨天分享的 Tailwind CSS 文章中有相关介绍。

Tailwind CSS 使用入门了解 Tailwind CSS 界面框架的安装,CSS 按需输出和合并 class 的功能。

如果不想自己折腾,那么直接使用 Tailwind CSS 会是一个更加省事的选择。Tailwind CSS 虽然给我的感觉不错,也很想立即投入使用,但目前线上的大部分项目还是使用的 Bootstrap。全部都换成 Tailwind CSS 的工作量有点大,所以决定还是先尝试看看在 Bootstrap 中实现类似的功能。

PurgeCSS 安装和使用

作为一个小工具,PurgeCSS 的安装和使用比较简单。

npm i -D purgecss

然后就可以通过以下命令来使用了。

npx purgecss --css /path/file.css --content /path/file.html -o /path/output.css

命令中使用的三个参数作用如下:

  • --css: 制定项目使用的 CSS 文件,有多个就通过空格分割输入多个。
  • --content: 制定项目使用的 HTML 或者 JS 模板文件,同样支持使用空格分割多个。
  • -o: --output 参数的简写,指定精简 CSS 代码后输出的文件路径。

其中 --css--content 后面的路径可以提供多个,也支持 path/**/*.html 这种范围通配符格式。

通过一个小例子来看看实际效果。

首先创建一个 CSS 文件,命名为 style.css,代码如下:

.title {
    font-size: 1em;
}

.other {
    color: #C00;
}

这个样式文件定义了两个 CSS 选择器。接下来继续创建一个 HTML 文件,命名为 index.html,代码如下:

<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>PurgeCSS Test</title>
</head>
<body>
    <h1 class="title">zzxworld</h1>
</body>
</html>

可以看到,在 HTML 文件中,只使用了 .title CSS 选择器。那么通过 PurgeCSS 处理后,输出的 CSS 文件应该只包含 .title 选择器。执行以下代码输出一个新的 CSS 文件: app.css

npx purgecss --css style.css --content index.html -o app.css

命令执行完后查看 app.css 文件内容如下:

purgecss-demo-output

可以看到,只输出了 .title 选择器样式内容。

在 Laravel 框架中使用

Laravel 框架默认就集成了 Laravel Mix,Laravel Mix 已经有了 PurgeCSS 插件。执行以下命令安装这个插件:

npm i -D laravel-mix-purgecss

然后在 laravel.mix.js 文件头部引入插件:

// ...
require('laravel-mix-purgecss');
// ...

然后在调用 CSS 打包的配置后面使用 purgeCss 方法就可以了:

mix.sass('resources/sass/app.scss', 'public/css').purgeCss();

我在一个项目中实际使用了一下,效果还挺不错。没精简前的大小有 160K 左右,精简后就只有 30K 左右了,几倍的差距。经过压缩后会更小。

另外也碰到了一个问题。因为使用了一个 JS 的代码高亮库。这个工具动态的生成一些样式选择器,而 PurgeCSS 无法感知这些操作,就把一些本来需要的 CSS 代码给过滤了。从而导致 pre 标签中的代码高亮样式都无法正常显示。碰到这种情况,就需要使用 PurgeCSS 提供的配置功能。

修改后的 laravel.mix.js 文件配置代码如下:

mix.sass('resources/sass/app.scss', 'public/css').purgeCss({
    extend: {
        safelist: {
            deep: [
                /^pre/,
                /^token/
            ]
        }
    }
})

以上就是新增了一个 safelist 配置项。它定义了要保留的样式选择器前缀,对于配置的这些 CSS 名称,即便是没有用到,在输出的 CSS 代码中也会被保留。