2020年1月2日星期四

把我的个人网站推倒重来(Part 9 - 精简 Bootstrap 编译)

我在很久之前一篇文章里讲述了我为何选择 Bootstrap 作为样式框架,在那篇文章的结尾我提到了一个我当时没做的优化:去掉我不使用的 Bootstrap 模块。

我现在终于有时间把这项优化做了,我可以先说说做好的效果:Bootstrap 全部的 CSS 共 152kb,在优化后变为 72kb,节省了一半的体积。(压缩后的网络传输体积由 23kb 优化到了 11kb。)这个优化的效果还是很明显的,接下来我说说我具体做了什么吧。(具体代码可以参考我的 pull request。)

引用 Bootstrap 源代码

我们要去掉了不需要的 Bootstrap 模块,就要手工选择 Bootstrap 的 SCSS 文件,然后只编译和引用我们需要的。我们当然可以下载 Bootstrap 的 SCSS 文件,不过更好的做法是直接用 Git 的 submodule 概念引用 Bootstrap 源代码。在我的源代码目录下执行以下的命令就可以添加指向 Bootstrap 官方 GitHub 的 submodule:

git submodule add https://github.com/twbs/bootstrap.git

不过官方 GitHub 的 master 分支并不总能通过编译,这是我后来才发现的。修复的办法也很简单,就是强迫 submodule 指向特定 Bootstrap 版本的 commit。在 Bootstrap 源代码我们可以找到 v4.4.1 tag,然后定位到它的 commit 是 dca1ab7

接下来进入 bootstrap 子目录,里面就如同另外一个 Git 仓库一样,我可以用 git reset v4.4.1 --hard 把它的 HEAD 从 master 上最新的 commit 指向到 v4.4.1 的 dca1ab7。因为这个子目录是个 submodule,改变它的当前 commit 会修改我项目源代码的状态,这个改变在本地 commit 和 push 后就能在别处 pull 出来。这保证了 Netlify 在编译我的项目时使用的是同样的 Bootstrap v.4.4.1。

导入 Bootstrap 模块

Harp 内置了对 SCSS 的支持,所以我们不需要自己安装任何工具来编译 SCSS。现在 Bootstrap 已经以子目录的形式存在了,如何在我的项目中引用呢?我删除了原来直接引用的 bootstrap.min.css,然后添加了一个 bootstrap-custom.scss,并在页面里引用 bootstrap-custom.css。Harp 会发现这个 CSS 文件不存在但存在同名的 SCSS 文件,然后就编译同名 SCSS 文件并把输出结果保存到同名 CSS 文件。

bootstrap-custom.scss 件里,我直接复制粘贴了 Bootstrap 自己的 bootstrap.scss。这个文件本身不包含任何 CSS 规则,它只通过一大堆 @import 指令引用 Bootstrap 的所有模块。在我更新所有 @import 指令的路径后,引用 bootstrap-custom.css 的效果就跟引用完整的 Bootstrap 一样,包含了所有的模块。只不过这次我们不是用 Bootstrap 编译好的文件,而是让 Harp 从源代码开始进行编译。

精简 Bootstrap 模块

接下来要精简 Bootstrap 模块就很简单了,我可以一个一个地剔除我不需要 @import 的模块,只留下我需要的。精简后的 bootstrap-custom.scss 只用到不到原来一半的模块,体积自然下来了。

很可惜的是,这些模块不能进一步地分拆和精简了。例如说 _variables.scss 这个文件,其实它为大量我用不到的模块提供了常量定义,但就算我用不到这些常量我也无法把它们剔除。只要我用到的模块依赖于其中某些常量,我就必须把所有的常量带上。因此,尽管精简后 CSS 体积减半,但仍然有大量不需要用到的 CSS 被打包进去了。

配置 Autoprefixer

尽管 Harp 能够编译 Bootstrap 的 SCSS 文件,但还有一件事情是 Bootstrap 官方编译做了但 Harp 不会做的,那就是 Autoprefixer,这个工具会为 CSS 规则加上浏览器厂商前缀,保证 CSS 的兼容性。例如说,如果我们手写了 user-select: none,Autoprefixer 会自动添加 -webkit-user-select: none-moz-user-select: none 等等。

Autoprefixer 自己不能直接在命令行里使用,必须通过 PostCSS 调用。也就是说,调用 PostCSS 处理 CSS 文件,然后指定使用 Autoprefixer 插件。为此我们需要安装 PostCSS 和 Autoprefixer,这强迫我把我的项目变为一个 NPM 模块,这样我才有 package.json 文件,然后才能安装我所需的 NPM 模块。

需要注意的是,Autoprefixer 必须在 Harp 编译之后调用。Harp 编译先把 SCSS 编译为 CSS,然后再把输出的 CSS 交给 Autoprefixer 处理一遍。Harp 把项目目录里面的 public/ 编译后输出到 www/,然后我让 Autoprefixer 编译 www/css/ 并原地覆盖就好了。最后我写出来的编译命令如下:

harp compile .
npx postcss www/css/*.css --use autoprefixer -d www/css/

配置 Netlify 执行上述命令进行编译,我们的工作也就完成了。如果你对这类技术文章感兴趣,欢迎通过邮件RSS/Atom 订阅我的博客。

没有评论:

发表评论