こんにちは、エンジニアの@dachi_023です。最近、MacBook Proの調子が悪いのですが修理に行くのが面倒で行っていません。放置し続けていたら直ったりしないかな・・・。
今回の記事はGatsbyで100ページ超えの静的サイトを構築したときの学びについてです。Gatsbyって実際どうなん?って思っている方に読んでもらえたら幸いです。
つくったもの
ママリユーザーが本当に使ってよかったと思う商品・サービスの口コミを元に、自分と家族に合うものを探すことができる「ママリ口コミ大賞」の2019年 秋版のサイトをGatsbyで実装しました。妊娠中の方、育児中の方におすすめしたいサイトです。私も実際つかってみて、「これ、子どもが産まれた時にあったらもっと便利だったな〜!」って毎回思っています。
これまでの技術選定
ママリ口コミ大賞は今回で3回目なのですが、毎回使用する技術が変わっています。その時のリソース事情や要件などに合わせていた結果そうなったわけですが、ママリ口コミ大賞を3回とも実装してみた感想は「リソース足りなくても出来るところまででいいから最初からちゃんとやればよかったな」です。考えが甘かった。
- 第1回:ejs + webpack
- 第2回:自作のジェネレーター + pug + Spreadsheet (DB) + webpack
- 第3回:Gatsby + MySQL
といった歴史があり、自作ジェネレーターの実装やSpreadsheetをDBとして運用するのがめちゃくちゃしんどかった辛さから今回はGatsbyでつくり直し + 商品や口コミのデータをちゃんとRDBに格納、GraphQL経由でデータを取得できるようになりました。開発がとても快適になったのと、RDBの偉大さを再認識することができました。ただ、Gatsbyは使った方が良いケース、悪いケースがはっきりしているのでその辺のPros/Consを書けたら、と思っています。
ちなみに: 第2回をつくったときの登壇資料
良かったところ
開発環境
静的ページしかない時なんかはwebpackをはじめとしたビルドできる環境をつくってもあんまり恩恵なかったりするんですが、自分で構築しなくてもサクッとReactが使えてビルドもやってくれる環境があるよっていうのは体験として良かったです。create-react-appという手もありますが、ejectした後の整理が大変すぎるので仕事では使っていません。
GraphQL
GraphQLを使うとなるとGraphQLサーバ立てて、そのサーバーにリクエストを投げて、だと思ってるんですがGatsbyの場合は内部でやってくれるのでqueryを書けばいいだけです。まあ静的サイトつくるのにGraphQLサーバ立てなきゃいけないってなってたら中々使わないですよね・・・。
※ www.gatsbyjs.org より引用
プラグイン
Gatsbyにはプラグインの機構があります。公式ページのプラグイン一覧からつなぎこみたいデータソース用のプラグインを探したりするのですが、今回繋ぎこみたかったデータソースに関するプラグインは全部ありました。この辺の開発は結構盛んなのかな?と思いました。
接続情報を設定するだけでGraphQL経由でデータを取得することができるようになりました、とても便利です。あとはgatsby-plugin-typescriptを入れてTypeScriptで書けるようにしたりなどでプラグインを導入しました。
デプロイ
$ gatsby build
して成果物をS3の静的ウェブサイトホスティング用のバケットなどのストレージサービスに置けばデプロイ完了です。AWSならCodeBuildを使えば自動化も簡単です。
buildspec.ymlの例
version: 0.2 phases: install: runtime-versions: nodejs: 10 pre_build: commands: - npm install build: commands: - npm run build - aws s3 sync ./public s3://{YOUR_BUCKET_NAME} --delete --acl "public-read"
パフォーマンス
静的サイトなのでバックエンドのパフォーマンスチューニングは基本不要です(とはいえ重いQuery書くとビルドは遅くなるのである程度は気をつけていますが)。Reactの実装だけ気をつけていればそうそう遅くはならないと思います。
注意すべきところ
使いどころは限られる
データ更新が頻繁に行われる、リアルタイムにデータを取得したい、などの要件がある場合は使わないほうがいいです。その条件でReact + SSRを実現したいならNext.jsかなーと。Gatsbyの場合、データ更新=再デプロイ(再ビルド)になります。ReactDOM.hydrate()
してクライアント側で動的にごにょごにょするとかも出来ますが、もうそれGatsby使わなくてよくない?感がすごいので・・・。データの更新が頻繁でないコーポレートサイトやブログなどとの相性はいいと思います。
Gatsbyのお作法
Gatsby Node API(ビルド時に動作するスクリプト)を理解するために結構時間をかけました。動的なページの生成、GraphQLスキーマ周りのカスタマイズなど、中身が盛りだくさんかつGatsby独自の仕組みも結構あるので、調べて→動かして→実行結果を確認して、を繰り返しました。慣れれば楽ですが慣れるまでが大変なヤツです。今回は複数のデータソースから取得したデータのマージやページ生成を行うための事前データの取得など、色んなロジックが絡んだためその分複雑になってしまったかな、という印象でした。コンテンツがシンプルなページをつくるのであればそもそも深くまで知らずともサクッと構築できると思います。
規模が大きくなるとまあまあ遅い
ビルド時間の大半がGraphQLスキーマの構築とページの生成で持っていかれるのですが、外部データを取得したりページ数が増えてきたりして、現状は2分くらいかかっています。JSのビルドにしては遅いよね〜ってくらいなのでデプロイ全体で見ればまあそんなに遅い訳ではないかも?とは思いますが、長い目で見るといくらビルド処理全任せしているとはいえ、コード書く側もちゃんと気を遣わないとね〜といった感じでした。
その他やったこと
imgixの導入
S3 + CloudFrontの構成に加えてimgixという画像配信に特化したCDNを利用しています。WebPへの自動変換や画像のリサイズなどをQuery Stringで指定できるので、画像周りのパフォーマンス改善が簡単にできました。imgixに関しては@shnagaiさんの下記の記事が参考になると思います。
おまけ
Gatsbyの仕様を噛み砕いたり、実装する際に詰まった部分など残したりするために使っていたメモをScrapboxで公開していますので読んでみてください。本記事の社内レビューで「おまけの方が技術的には本編感ある」と言われたので多分こっちのほうがより具体的だと思います。
PR
コネヒトではエンジニアを募集しています!家族向けサービスをつくりたいエンジニアの皆さん、お待ちしています。 www.wantedly.com