JSド素人がJAMStackブログの爆速開発に挑んだ顛末
JavaScriptをよくわかっていない初心者が、JAMStackなブログ制作に挑戦したGatsbyの体験記。 Pelican、Hugoと試してみて、最終的にGatsbyを採用しましたが、特殊な存在であるJSXやGraphQLに慣れるまではかなりの難関でした。
発端
以前から作業記録のアウトプット用にブログが欲しかったのですが、以前の経験から色々と制約の多い無料ブログサービスは使いたくないなぁと思っていました。 かといってブログの為だけに、サーバーを契約してWordPressを使うのも面倒で、今まで手をつけられず。 (PHPわからないし)
そこで一年前くらいなのですが、今はJAMStackなるものが流行ってるらしいと知りまして。
- J = JavaScript
- A = APIs
- M = MarkUp
の頭文字を取った造語とのことで、要はアクセス時のサーバーでの処理をなくして、HTML・CSS・JSのシンプルな構成のページにしてしまうおうということらしいですね。
無駄を省いた結果として、WardPressを過去の物にする高速表示が売りなのだとか。 そして、サーバー契約不要だから、GitHubPagesやNetrifyなら無料で公開できる。 記事の更新もローカルでMarkDownで書いてもいいけど、HeadLessCMSを使えばWordPressのように記事の編集や管理をGUIで行える。 更にはWordPressのテーマのような機能もあり、自分でコードを書かなくとも既存のものを導入するだけで簡単にブログ始められる! おおっ、なんか知らんけどJAMStackって良いことずくめじゃないか!
……というのは甘すぎる目算だったのですがWoozy Face Emoji
そんな訳で、とりあえず静的サイトジェネレーターの人気を表示するサイトで調べて、使ってみることに。
静的サイトジェネレーターを比較する
例としてよく引用されているこのサイトを目安にして選びました。
最終的にインストールしてみたのは以下の三つです。
Pelican
最初にPythonで書かれているPelicanを試用してみました。 理由は単純に、私がPythonに馴染みがあったからですね。 上記の比較サイトではトップ争いにこそ加われないものの、Python製では一番人気という感じ。 静的サイトジェネレーターはどれかのプログラム言語に依存しているので、自分が一番知っている言語で使うのが一番簡単かなと予想しました。
結果、Pythonで書かれているPelicanならソースコードを読める点は楽でした。 内部の処理をちょっと変えたい時とか修正したりできますし。 ですが、Python自体が速度が早い言語ではないせいもあるんでしょうが、触っていてページビルドが遅いのが気になりましたね。 これはちょっと記事数が増えた時に辛そうだなと。 結果、別のライブラリを検討することに。
Hugo
そこで登場したのがHugoです。 Pythonじゃないなら、とりあえず評価の高そうなのを使おうと。 静的サイトジェネレーター専門ではGatsbyと人気を二分しているライブラリです。 二つを比較して「Gatsbyで使うReactとかJSXとか全く分からない、それにHugoは簡単で速度も早いらしい」という理由で選出。
結果、Pelicanで不満だったビルド速度は桁違いに早かったです。 流石は、よく優位性として速度が上げられることの多いGo言語だけあるなぁ、と。 中身もHTMLを基本としているのでとっつきやすい感じですし。
反面、私がGo言語が分からないので何かあった時に中身に触れないのが不安要素。 それと出力されたものはブラウザで動かす為のHTMLやCSSであり、Go言語はブラウザでは動かないので、別途サイトに動きをつけたり複雑な処理が欲しいなら、JSライブラリなりを追加することが必要になる訳です。 ここで、JSもGoも知らないなら、もう逃れられないJSで全部やってしまった方がいいんじゃないか、という考えが浮かんできます。 後、当時はHugoには凄く気に入ったテーマがなかったのも大きかったですね。
そこで、ふとGatsby公式を見ていると、あるGatsbyのテーマを見つけました。 (これはGatsbyでスターターと呼ばれるものですが、混ざるとややこしいので今回はWordPress的にテーマで呼称を統一しています)
Gatsby
Hugoでも大きな問題はなく、既存のテーマを改変しつつ途中まで制作していたのですが、そこでGatsbyの素晴らしいテーマを見つけてしまったんですね。
これがメニューの記事一覧がガンガン動き、ページ遷移もHTMLのみの静的サイトより高速なぐらいの高性能。 「これがSingle Page Applicationって奴なのかー」と素人丸出しで感動、これをテーマとして即使えるなら完璧じゃないかと。 Gatsbyの実力ってスゲェと完全に惚れてしまって、後先考えずに採用することに。
素晴らしいGatsbyテーマが使えないジレンマ
ところが調べてみると、gatsby-starter-personal-blogはGatsbyのver1で制作されていて、現在のGatsbyバージョンは2。 公式のGitHubを見ても2への更新予定はないようで、つまり最新環境だと動かないわけです。 流石に使い始めから中心となるライブラリ更新できないのは厳しい。 node.jsの更新にもついてこられないし、公式からの新機能もバグフィックスも期待できないわけですからね。 かと言って不慣れな言語で、構造も把握していない他人の書いたコードを、Ver2に対応させるために移植するなんて技術的に不可能。
更にインストールして色々と使ってみると、まあどうしたって「これを追加したい」という欲が出てくる訳です。 具体的にはカテゴリー以外にタグでも分類したいとか。 せっかくならMerkDownではなく、HeadLessCMS使いたいとか。 ですがGatsbyのフォルダ構成がまず読めない。 当時はReactコンポーネントって何? 状態でしたし。 その結果、色々あって
「もう面倒くさいので、勉強を兼ねて一から自作しよう」
という経緯でこのブログが制作されました。
補足・Gridsomeを試していない理由
GridsomeはVue.js製の静的サイトジェネレーターで、日本でのVue人気もあって最近はよく使われて名前を聞きますね。 これが検討対象にならなかったのは最初に調べたのが1年以上前で、当時は今ほど有名じゃなかったせいです。 VuePressはブログ用という感じでなかったですし。
後、ReactとVueの両方を使っている友人から、Reactの方がTypeScriptを使うなら簡単に導入できて相性がいいと聞いたので、せっかくJSやるならPythonのmypyのように型を使いたかったというのも大きいポイントでした。 なので、今から始めるとしてもGatsbyを使っていると思います。 (Next.jsも静的サイトジェネレーターとして使えるようになったらしいので、そっちもありかもしれません)
結局よく言われるようにGatsbyは簡単なのか?
制作開始時点での私のJavaScript周りの知識は、多少は情報を集めていたとはいえ
- npm install程度はできる
- JSはJQueryを齧った程度でVanillaJSは殆ど分からない
- ReactはチュートリアルでCreateReactAppした程度
- Gatsbyもチュートリアルと、スターターを動かした程度
この程度のレベルだと、本格的に制作開始してから最低限ブログと呼べそうなものが完成するまでに、一月~一月半ぐらいかかりましたね。 制作と平行しても、ReactやGraphQLを学ぶことに時間がかかる感じで。
もちろん既存のテーマ(スターター)を流し込んで完成! とするなら数日もかからないと思います。 ですが、始めた当初の私がgatsby-starter-personal-blogに対して「カテゴリーだけではなく、タグでの分類を追加したい」と思いましたが、色々とググって解説記事を読んでも全く理解不能でした。 所得した記事のデータをどこで加工するのかといった、内部のデータの流れが追いかけられなかったです。 その程度のカスタムでも、知識は必須になりましたので、Gatsbyを使う以上はReactからは逃れられないと思った方がいいかと。
最初に調べた時に「Gatsbyで爆速ブログ構築」とかって売り文句を見ましたけど、そんなうまい話はなかったなぁと。 (SPAなので最適化できれば、爆速でブログ「を」構築するのではなく、爆速で「動く」ブログ構築はできると思います)
この辺のネットの評価は、静的サイトジェネレーターをJavaScriptとReactのようなフロントエンド周りの知識を既に持っている人しか使っていないというのも多いのかなと思います。
とはいえ、実際に内情が分かってくると、BabelやWebPackの設定やルーティングなど「必須だけど面倒な部分」というのを全て自動で設定してくれていて、素で作るのに比べれば圧倒的に早いのは間違いないのですが。
Gatsbyの良い点・悪い点
- SPAなので出力したブログとしての性能が高い
- Pluginで機能追加が容易
- 結局JSが必用ならHTMLからCSSまで全部JSで書けるのは楽
- Hugoよりビルドか遅い
- ある程度ブログらしくする為には自分で多くのPluginを選定、導入する必要がある
- ReactとJSX、更にGraphQLの理解が必須で学習コストは高め
SPAとして閲覧時のページ遷移を高速化できるので、最終出力のクオリティを上げられるのが魅力的ですね。
反面、ビルドは超高速なHugoに比べると流石に遅いです。まあこれは流石に比較対象が強すぎますが。 そこは「パワー(ビルド速度)がてめえならスピード(ページ遷移)はオレだ!!!一生かかっても追いつけんぞ!!!」って気分で頑張りしょう。
Gatsby Plugin
Plugin方式は利点でもあり、同時に大変なところでもあります。 デフォルトでの機能は簡素なので、大量に公開されているプラグインの用途を把握して、自分のサイトに必用なものと不必要なものの所得選択を管理しないといけません。 サイト制作に慣れていて「必要なのはアレとソレ」と最初から決められる知識があれば簡単なのでしょうが、何が必須かが分かってないと知らないものを逐次調べて選ぶというのは結構な労力。
Pluginは、この記事を参考させてもらって、適宜必用になったものをインストール。 例えば、このブログ程度の内容でも、react関係のものやgatsby本体を除いて、gatsby専用のpluginだけで28個必要になりました。
"gatsby-image": "^2.4.19",
"gatsby-link": "^2.4.14",
"gatsby-plugin-catch-links": "^2.3.12",
"gatsby-plugin-emotion": "^4.3.11",
"gatsby-plugin-feed": "^2.5.12",
"gatsby-plugin-google-analytics": "^2.3.14",
"gatsby-plugin-graphql-codegen": "^2.7.1",
"gatsby-plugin-manifest": "^2.4.31",
"gatsby-plugin-next-seo": "^1.6.1",
"gatsby-plugin-nprogress": "^2.3.11",
"gatsby-plugin-offline": "^3.2.28",
"gatsby-plugin-react-helmet": "^3.3.11",
"gatsby-plugin-remove-trailing-slashes": "^2.3.12",
"gatsby-plugin-robots-txt": "^1.5.3",
"gatsby-plugin-sharp": "^2.6.36",
"gatsby-plugin-sitemap": "^2.4.13",
"gatsby-plugin-smoothscroll": "^1.2.0",
"gatsby-plugin-twitter": "^2.3.11",
"gatsby-remark-autolink-headers": "^2.3.13",
"gatsby-remark-code-titles": "^1.1.0",
"gatsby-remark-embedder": "^3.0.0",
"gatsby-remark-external-links": "^0.0.4",
"gatsby-remark-images-contentful": "^2.3.17",
"gatsby-remark-images-medium-zoom": "^1.7.0",
"gatsby-remark-line-breaks": "^1.0.0",
"gatsby-remark-prismjs": "^3.5.13",
"gatsby-source-contentful": "^2.3.47",
"gatsby-transformer-remark": "^2.8.35",
うーん、多い。
それと、一口にPluginと言っても、中でも簡単なものもあれば、設定がかなり大変なものもあります。 三割ぐらいはgatsby-configファイルに名前を一行だけ書けばOKなんですが、十数行以上必要になるものもあります。 中でもgatsby-plugin-feedは、内部でGraphQLからクエリする必用もあり、相当手間でした。 これだけでgatsby-configの3割ぐらい埋まってますWoozy Face Emoji
いずれ、こういったPluginを実際に利用した時の注意点は、ブログ記事として書き残しておきたいなーと思っています。
JSXとかGraphQLとか
始める前は特殊な構文かと思っていたJSXですが、CSS in JSのemotionを組み合わせると、もうHTMLもCSSも個別に書く必要がなく、JSの中だけでサイト全体を完結できるのが一貫性があって凄く楽でした。
CSS in JSもいいですね。 コンポーネント単位でcssが分割されるので、無駄な命名規則を考える必要がないのは素晴らしい。 一度でもcssやsassの命名規則に困って、BEMなんかで疲弊した経験があるなら革新的です。
この二つの組み合わせは、もう素のHTMLやcssを書く気にはならないぐらい便利です。
それにReactベースなのでTypeScriptとの親和性が高いのもありがたい。 最新のGatsbyではPluginなしでTypeScript対応してくれますし。 Pythonでもmypyで型定義を使っていますが、最初は手間でも総合的には型はあった方が圧倒的に開発が楽です。
ただ、GraphQLは慣れるまで「訳が分からないよ」状態になりました。 GUIがあっても、自動的に作られるedgesだのnodeだのといった分類が大量にあるので、結局データどこにどれが入ってるの? と。 これも慣れてしまえば、ページ内のどこでも好きにデータを引き出せるようになるのですが、やはり最初の敷居は高めなんじゃないかなと。 gitなんかもそうですけど、頭の良い人の作ったシステムって凡人には慣れるまでが大変。その代わり使えるようになるとその性能の高さに感謝するわけですが。
ブログ制作で実現できたこと
TypeScript対応
本体で対応してくれているので、最初からTSで開発することが出来ました。 TSの型はmypyに比べて型の扱いが厳密なので、最初は流儀の違いが辛い部分もありましたが、慣れると必須になります。
HeadlessCMS利用
定番のContentfulを利用しています。 Gatsby開発当初は無料枠が豊富なprismic.ioを検討したのですが断念。 Gatsby側からの対応状況が段違いでした……長いものには巻かれるべきですね。
OpenGraphとJsonLDでメタデータを設定
サイトを作成するに当たって、メタデータはちゃんと設定したかった部分でした。 閲覧者からは見えない部分ですが、個人的にここがちゃんとしてると「しっかりと作ってあるサイト」ってイメージがあるんですよね。 手間はかかりましたが「こだわりがあったからさ」って部分です。
設定に関しては、当初はReactHelmetで自作する予定でしたが、このプラグインがとても良かったです。
ただ、これも最初は苦戦したので、いつか使い方を記事にしたいなー。
実装できなかった今後の課題
AMP対応
現在のGatsbyには自動でAMP化する方法がないようです。 独自に対応している方の記事はあったのですが、手動での対応は中々時間がかかりそうだったので、今回は見送りました。
Twitterのタイムライン埋め込み
これ自体は技術的に確立されているのでそう難しいことではないのですが、サイトのデザインに適合させる作業の時間を考えて今回は断念。 最初から完璧を目指しているといつまで経っても終わらないよ、とはReactを紹介してくれた友人の言。
OGP画像の自動生成
需要は高そうなのに、意外と皆が使ってるプラグインというものがありませんでした。
Gatsby Plugin: Open Graph Images
前者はテンプレートとして背景画像は用意できても記事毎に個別の設定は出来ず、後者は文字と作者のアイコンは設定できても背景画像の設定ができない模様。 理想としては、GraphQLでビルド時に、記事に設定された画像を所得、そこにタイトルを載せて生成させたいのですが、そこで処理を噛ませるのは中々難しいのかもしれませんね。
まとめ
Gtasby、使いこなせるようになればとても優秀です。 しかし、「JavaScriptやReactに興味がある」という人なら勉強も兼ねられて良いでしょうけど、どうしても中身はJSX + GraphQLなので、そこを理解できるようにならないとサイトを調整することはできません。
しかしSPAのブログを作るためにはReactかVue.jsが必須になると思うので、現代的な性能のサイトを作るために避けて通れない学習コストとも言えます。 どうせ作るならベストを目指したいですしね。
まぁ、散々、大変と言いましたが、やはり当初の「JSもろくに知らない人間がSPAでサイトを作りたい」って要求が無茶だったとは思うので、それが実現できただけでGatsbyさんマジ凄いと言うべきでしょう。 なので、ここにド素人でも投げ出さずに完成できたという事実がありますので、これから静的サイトジェネレーターを使ってみようという人にもオススメです。