这个“静态”网站逐渐添加了越来越多的渲染脚本 (, Highlight.js, Mermaid.js, 等)。它们极大地拖慢了渲染速度。
由于这些渲染结果都是一致的,应当移到编译期完成。让静态的归静态。
最开始,我研究了一下搭配 jsdom 和 jquery 后,Highlight.js, Mermaid.js 在 Node.js 上的表现。我想看看是不是能执行一个非常简单的 Node.js 脚本就能达到我的需求。
花费了一两个小时后,我放弃了。基本上它们很难在 Node.js 上如在浏览器里一样可用。
最后的方案还是变成了 Puppeteer。将页面灌到 Chrome 里,然后拿到渲染完毕的 HTML,然后删掉那些渲染脚本。
首先给渲染脚本的 tag 添加 data-stage="prerender"
属性,以便于后续将它们从 HTML 中删除。
<script data-stage="prerender"> renderMathInElement(document.body); </script>
然后通过 Post Renderer 遍历整个生成的 public
目录,忽略掉那些 size 小于 1000 的文件(一般是 Hugo 生成的重定向 HTML),然后将它们一个个灌入 Puppeteer。
得到生成的 HTML 后,通过 jsdom 和 jquery 把 data-stage="prerender"
的元素全部删除。
这样就得到了完全渲染好的页面,给 Actions 添加一个新的部署流程,就完成了。目前本站已经应用了这个预渲染方式。
- name: Setup Nodejs
uses: actions/setup-node@v2
with:
node-version: '12'
- name: Pre Render Pages
run: mkdir rendered && cd post-render && npm install && node ./render.js .. ../rendered
- name: Deploy Pre Rendered
uses: peaceiris/actions-gh-pages@v3
with:
publish_branch: rendered
personal_token: ${{ secrets.PERSONAL_TOKEN }}
publish_dir: ./rendered
external_repository: lingsamuel/lingsamuel.github.io
这样即使在禁用了 JS 的环境中,也可以获得完整的阅读体验。同时也避免了页面载入后花费几秒钟渲染,然后元素一直在抽搐的问题。这很文明。
可以通过在 DevTools 中,通过 Ctrl + Shift + P
搜索 Disable Javascript
来测试一下,例如这个页面。
目前的预渲染脚本:
- 渲染中文引号,FuHsi.js
- 预处理 Mermaid 代码块,避免使用 Shortcode
- 渲染 Mermaid 图,mermaid.js
- 语法高亮,highlight.js
- 数学公式渲染,
- 一些样式处理
虽然还存在一些问题,例如如果 js/css 文件使用相对路径的话,Puppeteer 会从本地寻找;使用绝对路径的话,会去寻找线上版本,而使得运行的 js/css 实际上低了一个版本。
由于实际上我只有一个自定义 js,这个问题还不是非常严重,我懒得折腾了。