2021-04-29

このブログの表示速度改善

簡素なサイトなので油断していましたが表示速度を改善する余地があったためいくつか対策しました。

サマリー

改善前

Developer toolsで通信内容を確認すると以下のことがわかります。

Step 1: Webフォントをやめる

OSによって利用できるフォントが異なることにより、本文とコードブロックのフォントサイズのバランス等 が崩れることを懸念してWebフォントを指定していました。 しかし、想定以上にサイズが大きかったため諦めて各OSで利用できるフォントの指定に変更しました。 ※ Androidには明朝体が入っていないためゴシック体で表示されます。

before:

css
@import url('https://fonts.googleapis.com/css2?family=Lora&family=Ubuntu+Mono&family=Shippori+Mincho:wght@500&display=swap');

body {
  font-family: 'Lora', 'Shippori Mincho', serif;
}

after:

css
body {
  font-family:
  'Noto Serif CJK JP',    /* for Ubuntu */
  'Hiragino Mincho ProN', /* for macOS */
  'Yu Mincho',            /* for Windows */
  serif
  ;
}

Step 2: CSS, JavaScriptを並列でGETする

before: サイト全体に適用したいsite.cssとページ固有のpage.cssに分け、page.cssからsite.cssをimportしていましたが、これではCSSのGETリクエストが直列になってしまいます。

css
/* page.css */
@import '../site.css';

after: importではなく、linkタグで読み込むように変更しました。

html
<!-- posts/index.html -->
<link rel="stylesheet" href="/site.css" type="text/css" media="all">
<link rel="stylesheet" href="page.css" type="text/css" media="all">

JavaScript Modulesも同様です。コンテンツ(Markdown)のfetchとレンダリングをするmain.jsとMarkdownを処理する markdown.jsに分けていて、main.jsからmarkdown.jsをimportしていたため、JavaScriptファイルのGET リクエストが直列になっていました。

before:

javascript
// posts/main.js
import * as markdown from '/modules/markdown.js'

after: index.htmlでまとめてimport、dependency injection風に依存moduleを渡すように書き換えました。 (この方法ではModuleが増えると破綻しそうですね。)

modulepreloadという仕組みもありますが、画面のレンダリングがブロックされて白い画面が表示される時間が長くなってしまったため今回は利用しませんでした。

html
<!-- posts/index.html -->
<script type="module">
  import * as markdown from '/modules/markdown.js'
  import * as main from './main.js'
  window.onload = () => main.render({ modules: { markdown } })
</script>

ここまでの修正でCSSファイル2つ、JavaScriptファイル2つを並列でGETするようになりました。

Step 3: インデックスページで最新の記事をPrefetchする

Query stringからMarkdownファイルのURLを組み立てているため、 JavaScriptとMarkdownのGETリクエストはどうしても直列になってしまいます。 インデックスページで最新の記事をprefetchするよう設定しました。

※ 2021-04-29時点でSafariではサポートしていません。また、この方法でJavaScript ModulesをPrefetchすることはできません。 参考:Preloading modules

html
<!-- index.html -->
<!-- Prefetch latest post -->
<link rel="prefetch" href="posts/?post=2021-04-24--markdown-to-html">
<link rel="prefetch" href="posts/2021-04-24--markdown-to-html.md">

結果、Markdownファイルのfetch時間がほぼなくなりました。

おまけ: ローディング画面を表示して、白い画面が表示される時間を短くする

このブログの作り上、Prefetchできない状況ではMarkdownファイルをfetchするまで白い画面が表示されてしまいます。 読み込み中であることが分かるようにローディング画面を表示するように修正しました。

before:

after:

今後の課題