新しいHP・ブログの技術スタック

2020-07-13
山下 徳光
#
AmplifyConsole
#
Nuxt.js
#
Jamstack

こんにちは、山下です。

ホームページをリニューアルしました!無事公開できてほっとしています。

公開までの紆余曲折は別の機会に譲るとして、この記事では新ホームページ・ブログの技術スタックをご紹介します。

新環境のアーキテクチャ

開発者がBitBucketに記事をコミット・プッシュすると、自動的にAmplify Consoleで静的ファイルにビルドして、Jamstackとしてデプロイする仕組みになっています。

Jamstackは事前にビルドされたHTMLをCDNで配信するため、Webサーバーが不要かつ、高パフォーマンス・高セキュリティ・高スケーラビリティ 等の特徴を有しています。

今回は、以下の技術を組み合わせて実現しました。

静的サイトジェネレーター

静的サイトジェネレーターはNuxt.jsを採用しました。

Nuxt.jsは、Vue.jsのフレームワークです。Client Side Rendering(CSR)やServer Side Rendering(SSR)等のSPAに必要な機能が揃っており、標準で静的サイトジェネレーターも付属しています。

また、近年のHP・ブログで対応必須な機能としてSNSのOGP対応があります。OGP対応とは、TwitterやFacebook等のSNSにURLをシェアした際に、ページのタイトル・概要・サムネイル等の情報をSNS上に表示する仕組みです。一般的なSPAでサイト構築すると、アクセス後にJavaScriptで画面が描画されるため、OGPに必要なメタ情報を生成できない課題があります。

主な対応方法は下記の3つです。

  1. Server Side Rendering
  2. Dynamic Rendering
  3. 静的サイト生成

(1)Server Side Rendering(SSR)は、サーバー側でHTMLを生成してからレスポンスを返す方法です。ビルドされたHTMLが返却されるので、OGPに対応できます。一方、サーバーを準備する必要があるのでコストがかかり、サーバーに負荷がかかった場合のスケールアウト等も考慮する必要があります。また、クライアント・サーバー両方のロジックが混在することになり、バグが増えがちです。

(2)Dynamic Renderingは、TwitterやFacebookからのクローラーリクエストだけHeadless Browser等で実行してレスポンスを返す方法です。ビルドされたHTMLが返却されるので、OGPに対応できます。SSRとの違いは、実際にブラウザを動かした結果を返却するので、アプリはClient Side Renderingモードで動作させることができます。そのため、 SSRで課題となっていたクライアント・サーバー両方のロジックが混在することがなくなります。一方、こちらもサーバーを準備する必要があるのでコストがかかることや、Headless Browserのパフォーマンスが悪い場合、クローラーのタイムアウト制限にかかることもあるようです。

(3)今回採用した静的サイト生成は、事前に全てのコンテンツをビルドした状態でサーバーにデプロイする方法です。当然、ビルドされたHTMLを返すだけなのでOGPに対応でき、サーバーを動作させる必要もないので 高パフォーマンス・高セキュリティ・高スケーラビリディ になります。一方、コンテンツの量が多くなるとそれだけビルド時間が増えることになるため、ブログなどには向きますが、CGMなどには合わない傾向があります。

Nuxt.jsの静的サイトジェネレーターを利用すると、(3)の静的サイト生成を利用すことができます。

Headless CMS

Headless CMSには@nuxt/contentを採用しました。

Headless CMSはContentfulやmicroCMS等をよく耳にしますが、なるべく月々安く長く運用できる方式にしたかったため、独自にMarkdownから記事を生成するロジックを構築していたところ、TwitterのTLに@nuxt/contentの紹介ツイートが流れてきました。

@nuxt/contentは.md等の静的コンテンツベースのheadless CMSになっており、サーバーがなくても利用することができます。

早速試してみると、手元でスクラッチしていた独自機能よりも圧倒的に多機能で使い勝手が良かったため、即乗り換えました。詳細は別途記事にする予定ですが、下記のような機能を有しています。

  • .md, .yaml, .csv, .json, .json5のコンテンツに対応
  • .mdのメタデータに対応
  • PrismJSのシンタックスハイライト
  • コンテンツ検索(LokiJS)
  • 全文検索(LokiDB)
  • ホットリローディング

一方、静的サイトなのでおすすめ記事・人気記事などの動的要素が苦手です。

ホスティング

ホスティングはAWS Amplify Consoleを採用しました。

Amplify Consoleは、ホスティング(CloudFront)と継続的なデプロイを組み合わせたサービスです。AWS上でGitリポジトリと紐付けた後、下記に示すようなファイル(amplify.yml)をリポジトリのルートに置くだけで、Gitのプッシュを検知して静的ファイルをビルドしてCloudFrontにデプロイすることができます。

version: 0.1
frontend:
  phases:
    preBuild:
      commands:
        - yarn install
    build:
      commands:
        - yarn generate
  artifacts:
    baseDirectory: /dist
    files:
      - '**/*'
  cache:
    paths:
      - node_modules/**/*

これまでは本システムのような構成の場合、BitBucketのCI/CDサービスであるPipelines上でCFn管理ツール(CDK, SAM, serverless等)を利用してデプロイ処理を作り込んでいましたが、Amplify Consoleの場合はCFn管理ツールの知識がなくても同様の仕組みを構築できるので、簡単で学習コストが低かったです。

ただ、キャッシュ制御や細かいリダイレクト設定ができないので、複雑なサイトでの利用は難しいかもしれません。この辺りの悩みも、別途記事にしたいと思います。

メール送信

お問い合わせ・採用で利用するメール配信機能は、シンプルにAPI Gateway + Lambda + SESで実装しました。

おわりに

AWSをフル活用したJamstackのホームページ・ブログシステムを構築することにより、完全従量課金で低コスト・堅牢なサイトに生まれ変わりました。これから沢山記事を書いていこうと思います。記事を更新したら公式Twitterアカウントに流しますので、皆様よろしければフォローをお願いいたします!

株式会社Grandreamでは、フルリモートであなたのスキルを活かし、活躍できるエンジニアを募集しております。 詳しくは採用ページをご確認いただき、お気軽にお問い合わせください。

株式会社グランドリームでは、AWSを駆使した開発からUI/UXデザインまで、Webアプリケーションに関するすべての要望に応えます。
まずは一度お気軽にご相談ください。

お問い合わせはこちら