当サイト開発におけるライブラリ・フレームワーク等の選定について(Next.js / TailwindCSS / WPGraphQL…)|ONE SWORD株式会社

当サイト開発におけるライブラリ・フレームワーク等の選定について(Next.js / TailwindCSS / WPGraphQL…)

システム事業部
十川 涼

システム事業部の十川です。
システム事業部では、普段Webアプリケーションの開発を行っているのですが、それ以外にもヘッドレスCMSのサイト制作や、Shopifyを使ったオリジナルヘッドレスECサイト制作等も承っています。

本記事では主に開発者の方に向けて、ヘッドレスCMSを採用している当サイトで選定したライブラリやフレームワーク等をざっくり紹介していきたいと思います!

はじめに

自慢させてください。。
当サイトのTOPページ(Desktop)はlighthouseにてパフォーマンス100点となりました!

アクセシビリティの点数も本当は100点にしたいのですが、利用しているライブラリ準拠の減点と、デザイン的な要素(コントラスト比)が原因でほぼ諦めてます。
※lighthouseのコントラスト比はこんなにしなくてもってくらいシビアですよね。。

当サイトがパフォーマンス100点を出すのに欠かせなかった技術が

  • ヘッドレスCMS
  • SSG

となります。

(この2つのキーワードについては先日社内勉強会を開きましたので、こちらの記事ももしよかったら見てみてください。)

一覧(目次)

当サイト開発に使用した技術はだいたい以下のとおりです。

フロントエンド

バックエンド

インフラ

どのような技術なのか、なぜ採用したのか、どのようなメリット(やデメリット)があったかを挙げていきたいと思います。

Next.js

Next.jsはVercel社によるReactのフレームワークです。

TikTok、Hulu、Twitch等の名だたるサービスでも使われているようです。

2020年、Next.jsにはたくさんの魅力的なアップデートがありました。(2021年に入ってもなお続いています)

それもあってか開発元のVercel社は40億円を超えるファンディングに成功し、今まさに飛ぶ鳥を落とす勢いのフレームワークと言えるでしょう。

昔はヘッドレスCMSを構築する際にフロントエンドではReactのSSGフレームワークであるGatsbyを使っていましたが、2020年に追加された以下の2機能を使うために最近はNext.jsを採用しています。

①fallback

SSGでは、新しく記事を追加しても再ビルドが完了するまで該当のURLはNot Foundとなります。

しかし、fallbackを利用することで、該当URLがNot Found時にSSRでページ情報を取得してさらに静的ページの生成まで同時に行うことが出来るようになりました!

図解するとこんな感じになります。

  1. 記事はあるがページファイルがまだ生成されていないURLにアクセスするとNot Foundとなる(fallbackがなければここで終わり)
  2. サーバーにアクセスして該当の記事データがあればページを動的に生成してユーザーに返却する
  3. その裏で同記事のページファイルを生成する
  4. それ以降にアクセスしたユーザーには3で生成したページファイルを返却する

②ISR

ISRはIncremental Static Regenerationの略です。

SSGで生成されたページからの更新差分を自動で再生成してくれます。

文章でも図解でも表現するのがとても難しいのですが、だいたいでいうと、

  1. アクセスすると、現時点での生成済みのページを表示する
  2. その裏で最新のデータを取得して新しくページファイルを生成する
  3. 次にアクセスすると新しいデータのページが表示される

といった具合に、誰かのアクセスをトリガーとして、ページの内容を更新してくれます。

これまでGatsbyでSSGしていた頃は記事更新に3分程度かかっていたため、なんとかならんかといったところだったのですが、ISRを利用することで記事更新がほぼ瞬時に出来るようになりました!

ISR(その他CSR/SSR/SSGとの違い)の挙動についてのデモサイトを作りましたので、こちらで実装の挙動を確認していただけるといいかもしれません。

ざっくりいうと、fallback記事の追加を反映させる技術で、ISR記事の更新を反映させる技術といって差し支えないかと思います。

この2つの技術を組み合わせることで、SSGのサイトでも、CMSの操作に対してに再ビルドが基本的に不要となり、運用者や制作者がとても楽できるようになりました。

複数のWebサイトをVercelのようなサービスで運用する制作者にとっても、最大同時ビルド数を圧迫しなくなるため嬉しい機能だと思います。

次に、実装時にちょっと手こずったようなことを挙げたいと思います。

metaタグ生成

next/headを使って地道に書いてもいいのですが、next-seoなるライブラリがあるようです。

JSON-LDもサポートしているため、パンくずや記事ページの構造化データもついでくらいのノリでぱぱっと書けたのでおすすめです。

構造化データはGoogleが推奨するページの情報を構造的に表したデータで、検索結果をリッチに表示するのに利用されたりします。

sitemap.xml

シンプルなSSGではビルド時に全ページの情報があるのでsitemap.xmlも同時に作ってしまえばいいのですが、fallbackやISRを使うとビルド後にサイトが更新されることになるので、sitemap.xmlも更新する必要が出てきます。

そこで当サイトではsitemap.xmlのみSSR(Server Side Rendering)にて描画するようにしています。

実装はこちらの記事を参考にしました。

ちなみにsitemap.xmlには

  • priority(優先度)
  • changefreq(更新頻度)

という項目があるのですが、Googleはその2つの値を無視することを名言しています。

Google は、<priority> と <changefreq> の値を無視します。

TailwindCSS

次にTailwindCSSについて。ずっと気になってたCSSフレームワークだったのですが、今回自社サイトということもあり、実験的に導入してみました。

TailwindCSSは「ユーティリティーファースト」という謳い文句で有名ですが、これはつまり、要素ごとにクラスを定義してそこに複数のプロパティを指定する従来のCSS設計を否定し、ユーティリティクラスの組み合わせでスタイリングすることを本命とするフレームワークであることを意味します。多分。

CSSは多くのプログラミング言語とはちょっと気質が違い、とても運用が難しい独特な言語だと思っています。

それを補うために人類はBEMといった命名規約を作ったりして、色々頑張ってきたわけですが、昨今のコンポーネントベースの開発スタイルやCSS-in-JS等のscopedなCSSの登場により、少し流れが変わったのかもしれません。

「ユーティリティをどんどん使って、スタイルが重複するものはコンポーネントに書き出せばいい」というシンプルな思想はこれまでCSSに苦しめられた人にほど響いたと思います。

よかったこと

  • クラス名を考えなくていい。
  • configでサイト全体のデザインルールが定義しやすい。特に色とbreakpointの扱いが楽。
  • コードレビュー時にHTMLとCSSを往復しなくてよい。HTMLだけでどこにどんなスタイルがあたっているかが分かる。

微妙だったこと

  • CSSも普通に書くことになる。Tailwindだけでは完成しない。
  • CSSを書いたコンポーネント内で、CSSに記述されたスタイルとHTML側にあるスタイル(Tailwindのクラス)が混ざるとだいぶ分かりにくい。
  • @applyを使ってCSS側にまとめてもなお分かりにくい。(慣れかも)

Tailwind-JIT等の素晴らしい技術も出てきてるのでこれからの進化にも期待です。

WordPress案件でも本当は使いたいんですけどどうなんでしょう。
使っている方いらっしゃいましたら感想を教えて下さい。

Storybook

フロントエンドのコンポーネントカタログとしてStorybookを採用しています。

実装時にデザイナーやレビュアーが確認しやすいのが主なメリットで、実装者としても、様々なpropsを試すことが簡単に出来るのがいいですね。

TypeScriptを使うことで各propsのinput typeが変わったりするのも便利機能でした。

ONE SWORD HPのStorybook。テキスト等を自由に変更してテストできます。

ただ、今回はTailwindCSSとCSS Modulesを使ったこともあり、環境構築がかなり大変でした。(&まだ理想的ではない)

おもにTailwind/Storybook/Next.js間のpostCSSのバージョン不整合が原因ですが、ここはちょっと対応待ちな感じがあります。

ちなみにStorybookはNetlifyでデプロイしていて、プルリク時にプレビューデプロイでレビュアーがローカル環境でビルドしなくても確認できるようにしているので、デザイナーの方にも先にレビューしてもらうことができます。

Sentry

Sentryはエラートラッキングツールで、クライアント側で発生したエラー情報を追跡して一覧にまとめることができます。無料プランで出来ることの多さも魅力的です。

サーバーサイドのエラーはサーバーのログを見ればいいのですが、Sentryを使うことでクライアント側でのエラーを把握することができます。

例えばお問合せフォームが動作しなかった時用のエラーハンドラーを登録したり、404以外のエラーページでは、エラー発生時の訪問者にどのような操作をしたか等を質問するフォームの表示等を実装していて、サイトの安定した運用に一役買っています。

その他、Sentryではパフォーマンスの集計も出来ます。

URLごとにクライアント側で実際にどのくらいのパフォーマンスが出てるのかを見ることができ、パフォーマンス改善の指標として使えます。

例えばFirstContentPaintがGoodでないことが13%あるみたいなのですが…

ページごとの評価を見てみると、特定のブログ記事のパフォーマンスが低いことが分かりました!

インフラとして使っているVercelにも同様の機能があるのですが、そちらは$10/月かかるので、Sentryの無料利用枠がおすすめです。

WordPressAPI

ここからはバックエンド側の話になります。

ヘッドレスCMSには多くのサービスもあり、選択肢がたくさんあるのですが、我々は主にWordPressAPIを選んでいます。

その理由は主に

  • 安い(サーバー費用のみで運用できる)
  • 投稿者がWordPressの管理画面に慣れているケースが多い
  • ショートコードを自由に実装出来る

といったところです。

※詳しくは社内勉強会の記事を参照ください。

デフォルトのWordPressAPIでは

  • プレビューが効かない
  • データ取得時に複数のクエリを実行してそれを付け合わせる必要がある

等のデメリットがありますが、プレビュー等にも対応したオリジナルWordPressAPIテーマを開発し、データ取得効率はWPGraphQLのプラグインで改善することができました。

WPGraphQL

WordPressAPIをGraphQLクエリで操作出来るようになるプラグインです。
割と最近、ついにv1.0.0が正式リリースされました。

GraphQLとは

Facebook社が開発したクエリ言語で、クライアントとAPI間のやりとりをシンプルに実装することができるようになる技術です。

RESTと比較したときの特徴としては、以下のサイトで詳しく説明されています。

RESTではユーザー、投稿、フォロワーの情報をそれぞれで取得し、つなぎ合わせる必要があります。また、それぞれの情報には必要のないプロパティまで含まれているかもしれません。

GraphQLでは一回のクエリで全情報を取得できるうえ、不要なフィールドを削った最小限のデータ量でやりとりできます!

個人的にこの技術がとても好きで、Webアプリケーションの開発案件でも積極的に採用するようにしています。

GraphQLのことを書くだけでも1記事になりそうなのでここでは細かいお話はしませんが、素晴らしい記事がありましたのでシェアしたいと思います。

WPGraphQLによって出来ること

WordPressAPIはデフォルトではRESTなので、たとえば記事一覧ページでカテゴリ名と著者名を表示しようとすると、

  • 記事一覧取得
  • カテゴリ一覧取得
  • 著者情報一覧取得

の3つのAPIに対してリクエストを送って、それを組み合わせて情報を構成する必要がありました。

さらに、記事一覧で必要な情報は数個程度に収まるのに対して、それぞれのAPIのレスポンスには、各データの全情報が含まれているため、データの通信速度にも悪影響があります。

これに対して、WPGraphQLでは、

  • 記事一覧の中で必要な情報
  • その記事に紐付いたカテゴリ名や著者名といった情報

といった必要な情報1度のリクエストで過不足なく取得することができます。

SSGではあまり気にすることはないですが、

  • ビルド速度
  • SSRしているページ(fallback時/sitemap.xml等)の表示速度

あたりにいい影響が期待できます。

Extensionについて

WPGraphQLには

  • Offset Pagination(ページネーション実装用)
  • Total Counts(記事総数取得用)
  • Cors
  • JWT Authentication

といったさまざまな拡張機能があります。

手が届かないちょっとかゆいところを解消してくれます。

nullableの悲しみ

GraphQLではクエリが定義されたスキーマファイルを用いるのですが、これとGraphQL Code Generator等のツールを組み合わせることにより、TypeScriptで型安全な開発が出来ます。

DBにおいて必須な項目と紐付いたフィールドをクエリで指定した場合、そのレスポンスデータはほぼ確実にnullでない値が入っているのですが、WPGraphQLによって作成されるGraphQLスキーマではあらゆるtypeの中の(ID等を除く)ほとんどのフィールドがnullableなものとして定義されています。

そして、GraphQL Code GeneratorがGraphQLスキーマからTypeScriptの型定義ファイルを作成するとき、nullableなフィールドはoptionalなプロパティとして反映されます。

そのため、ほぼ全てのプロパティが基本的にoptionalとして型定義されます。

結果、生成された型をextendするなどして適した型を自前で定義することになり、理想まではもう一歩といった感じになりました。

Vercel

インフラとしてはNext.jsの開発元であるVercel社によるVercelを利用しています。

Next.jsでISRをする場合でもゼロコンフィグで簡単に動作させられるのが主なメリットで、その他にも、国内リージョンのCDNにコンテンツをキャッシュさせることによる、アクセスの負荷分散とレスポンス速度の向上が強みです。

また、お問い合わせ時のメール送信はVercelのserverless functionを使ってメール送信用のAPIを実装しています。

かつてヘッドレスCMSをやり始めたときはNetlifyを使おうとしていたのですが、高額プランでなければ国内のCDNが使えなかったためVercelにした経緯があったりします。

Next.jsのISRを利用しているzenn.devがVercelからGCPに移行したということが話題になっていましたが、エンタープライズの料金プランにはちょっと難がありそうです。

Previewデプロイに対してパスワードをかけるだけで月$150かかるのももう少し安くしてほしいですね。。

おわりに

以上、当サイトで利用している技術の紹介でした。

Webの技術進歩はとても早くて、ついていくので精一杯ですが刺激的で楽しいですね。

ヘッドレスCMSの技術はこの1年で大きく進化していて、より簡単によりよい仕組みが作れるようになりました。

本記事の内容が誰かの技術選定等の参考になれば幸いです。
(また、間違っている内容等ありましたら、やさしく指摘していただきたいです。)

ONE SWORDではヘッドレスCMSのサイト制作のほか、Shopifyを使ったオリジナルヘッドレスECサイト制作も承っています。

お気軽にお問い合わせください。

contact

お問い合わせ

仕事のご相談・ご質問など、お気軽にお問い合わせください。

お問い合わせフォーム