【2020年版】個人的にベストなフロントエンドJAMstack構成
2020年版現在の、個人的にベストなフロントエンドJAMstack構成(Vue.js + HUGO)とサーバーについてまとめてみました。
公開日: 2020.3.25
JAMstackサイトの構成
開発コスト、ユーザーメリット、サーバーコスト、どれをとっても個人的には今後は「JAMstackだな」と感じていて、より低コストで高速なWebサイトを構築する方法を模索していました。
ここ1年くらい試行錯誤して「Vue.js + HUGO」という構成に落ち着きました。
Vue.js (Javascript)
Vue.jsは基本的にはドキュメントルートから読み込んだ時のみ発火する設定にしています。
というのも、後述するSSRやAMPに対応しようとすると、どうしてもAMP用の静的ファイルが必要で、そうするとAMPページでは「router-link」が発火できないためです。
ただし、PWA化することで、Service Workerが先んじてAMPページからVueアプリ側をプレキャッシュしてくれるので、Vue.jsファイルの重さを軽減させることができます。
HUGO (HTML/AMP/json)
コンテンツの中身(データ)は、AMPページ + コンテンツjsonファイル(APIがわり)の配信元として、静的ファイルジェネレータのHUGOを使っています。
流れ的には、
- HUGOでHTMLページ(フルAMP)、ページデータのjsonを出力
- 検索エンジンにはHTML(AMP)ページをインデックス
- Vue.js側からはjsonファイルをロードしてSPAとして動作
とすることで、HUGOが吐き出すHTMLをSSRとして利用&AMPにも対応しつつ、jsonファイルも出力することで、HUGO自体をAPIサーバーにしてAPIサーバーコストも削減しています。
SPAだと、SNSなどでリンクを貼られた時にogpヘッダをロードしてくれない問題がありますが、この方法ならそこも回避できます。
データ構造的には下記のようなイメージです。
- index.html // Vue.js
- /topics/hoge/index.html // HTML(AMP) -> ここを検索エンジンにインデックス
- /topics/hoge/index.json // データのjson
CI/CDでビルドする際は、
- HUGOで静的サイトをビルド(HUGOの/index.htmlも吐き出すけど、yarn buildで上書き)
- yarn buildでVue.jsをビルド
という感じにしています。
SSR & API
HUGOで吐き出すHTMLは、基本的にフルAMPで生成しています。
こうすることで、AMP用のURLを別途用意する必要もなく、SSRも必要がないため、ビルドもスピーディになります。
また、JAMstackと言えばコンテンツをAPIから出すというイメージですが、Vue.jsでデータを受け取るためのデータ(json)は、基本的にHUGOで生成して同一ドメインから配信しています。
HUGOはコンテンツだけでなくデータも扱えるので、データベース的にも使えます。
データをAPI的に使うためには、
- データベースからdataテンプレートにjsonファイルを出力する
- APIサーバーを用意して、HUGOで取り込む
という2パータンを使用しています。
検索などリアルタイムで使いたいAPIがある時はAPIサーバーから、記事などの静的コンテンツのみを使う場合はすべてHUGOから吐き出しています。
サーバー
配信サーバー
サーバーは、NetlifyとGitlab pagesを使い分けています。
どちらもHUGOをビルドできるのですが、両者で使い分けるポイントは、
- Netlifyはrewrite/redirectができる
- Gitlab pagesはビルドタイムが多い(2000分 vs 300分)
- Gitlabはdocker imageが使える
という点です。
ビルド時間が多いので基本的には、Gitlab pagesを使って、rewriteなど高度な設定が必要な場合はNetlifyという形で使い分けています。
動的APIが必要な際は、Node.jsのexpressでGraphQL APIとしてnow.shから配信しています。
CDN
CDNは定番のCloudflareで、静的ファイルは基本的にキャッシュさせています。
CloudflareはPage ruleを設定すれば、jsonファイルもキャッシュしてくれるので、データによってはHUGOが吐き出すjsonファイルもキャッシュさせて、Netlifyへのデータ転送量を削減させています。
データ転送量という意味では、Webサイト自体が、
- 検索経由はAMPなのであまり転送がない
- PWAなのでアプリ本体はprecacheでローカル保存させている
という構造なので、そもそも転送量は少ないのですが、そこからさらにCloudflareで削減する感じです。