3この記事は11671文字で約30分で読めます2023年はもっといい年にしたいですね。Actionsでまとめおまけあけましておめでとうございます〜あけましておめでとうございます。本年もよろしくおねがいします。本年こそは何かを成し遂げたい私ですが、2017年からこまごま続けているこのブログの技術スタックについてもだいぶ固まってきた気がするので新年早々まとめ記事を書いていこうかと思います。はじめにこのブログのソースコード、記事のMarkdownなどはすべてGitHubで管理してます。そこに載っているReadmeをみればある程度やっていることがわかるようにはなっているのですが、せっかくなので、どうしてその技術スタックなのかなどの深堀りもできたらなぁーと思ってます。対象の読者は主に個人開発で無料でできるだけそれっぽいサイトが作りたいという人です。無料にこだわってます。高度なことはお金を払ってしましょう...。思い切ってすべてまとめてみようと思ったら、異常なくらい記事が長くなりそうなので、手始めにブログ本体に関することを中心にまとめます。全3回くらいを予定してます。Generator)で構築・運用されています。それ以前はWordPressでした。WordPressは個人ブログの定番ですね。当時フロントエンドの技術がさっぱりわからず、いよいよ危機感を感じたところから勉強のためブログでも作ってみるか〜というノリでGatsbyで作り始めたと思います。CLIを使ってBuild、静的サイトを作成する仕組みです。これもいくつかの技術変遷がありました。ホスティングはNetlifyを使ってます。これは当初から変えてません。浮気しようと思ったこともあるんですけどね。使い続けている理由などは後述します。基本的な技術スタックを聞く限り、「あ〜良くあるSSGを使った個人ブログね〜」という印象と思いますが、結構紆余曲折してます。Gatsby?SSGでサイトを作るなら例えばNext.jsだったり、Hugo、最近だとAstroなんかも流行ってますし、Vue.jsのフレームワークになれているならVuePress、Denoで作りたければlumeなんかの選択肢も上がってきます。そのなかでなぜGatsbyがこのブログで採用され続けているかというと、このサイトを作り込み過ぎて他のフレームワークへの移行コストがドエライことになっているからです。Reactのコンポーネントもたくさん作ってしまいました。いわゆるサンクコストというやつです。こと、SSGの分野でGatsbyが何となく最近他のフレームワークに押されているのを感じますが、理由としてなんとなくGraphQLの存在を常に意識させ続けられる開発体験がちょっと辛くなる瞬間、特にReactのコンポーネント書いていると裏にいるGraphQLとべったり依存しているナ〜というあの感覚が嫌いで使わなくなっていく人が多い印象があります。それらは何年も運用しているともはや慣れっこになってしまいました。GraphQL最高!オマエもGraphQL最高と叫びなさい!!︎というのは冗談で、データソースをある意味GraphQLが媒介してくれるので、ある程度データソースに依存しないサイトを作ることはできるのは事実あります。別にNext.jsでもgetStaticPropsの処理次第でMarkdown読み込みの依存度を減らしてあげるような作り方は全然できると思いますが、何も考えずに作れるのがGatsbyのいいところではないでしょうか?唐突ですが、未来の悪魔のお腹の中、臭そう...。カンガルーのお腹の袋は臭いらしいですよ。プラグインがだいたいなんとかしてくれるこれです。コミュニティーが成熟し、ちょっとしたやりたいことなら自分で実装しなくてよく、だいたいプラグインが用意されてます。installしてgatsby-config.jsに定義してあげるだけです。今、使っているプラグインを列挙すると次のものがありました。gatsby-plugin-preact後述します。Reactの軽量版のPreactが使えるようになんかごにょごにょやってくれるやつ。プラグインを入れるだけでよかったので優秀。gatsby-plugin-typegen後述します。GatsbyをTypeScript化するときに、GraphQLの型を自動生成します。Generatorを使って.graphqlファイルからtypes.tsを作る感じです。gatsby-plugin-excludeStorybook編でお話します。Storybook対応の際に一部のxxx.stories.tsxをbuildの際に読み込んでしまう問題があったため、対象から除外する目的で導入してます。gatsby-plugin-react-helmet超定番プラグイン。TemplateごとにHeadタグを作りたいときに便利です。ブログサイトだとSEOを意識させられるので必須ですね。gatsby-plugin-react-helmet-canonical-urlsreact-helmetでcanonicalをつけてくれるプラグイン。gatsby-plugin-sass後述します。このブログのStyleはSass(SCSS)で管理されています。gatsby-plugin-minify-classnames後述します。build時に短くしてサイズをちっちゃくしてくれます。gatsby-plugin-purgeCSS後述します。CSSフレームワークとして使っているBootstrapが重たいので少しでも小さくするために使ってます。gatsby-remark-copy-linked-filesこのブログではあんまり使ってませんが、ファイルを公開するときによしなにpublicからのリンクを作ってくれます。gatsby-plugin-webpack-bundle-analyser-v2Webpackのバンドルサイズを確認します。後述しますが、React時代はめちゃくちゃでかかった...。Preactになってちょっと小さくなった。gatsby-source-filesystemファイルとして保存されているMarkdownをGraphQLとして読み込み、記事化するために必要なデータソースプラグインです。Markdownをデータソースにしている場合、ほぼ必須のプラグインだと思います。gatsby-plugin-robots-txtSEO対策です。Deployの場合、そちらをGoogleにIndexされないように制御もしてます。詳しくはCIの回で話します。gatsby-plugin-feedRSSを生成してくれます。gatsby-plugin-algolia後述します。ブログ内検索としてAlgoliaを使ってます。Deploy時にIndexされないように制御しています。gatsby-transformer-remarkMarkdownのRemarkをやってくれるプラグインです。gatsby-remark-numbered-footnotesあまり使えてませんが脚注を入れるのに使ってます。gatsby-remark-prismjs-titlePrismjsでシンタックスハイライトしたコードブロックにタイトルを付けるときに使います。gatsby-remark-prismjsPrismjsを使ってコードブロックをシンタックスハイライトします。技術ブログには必須ですね。gatsby-remark-autolink-headers記事内のh1,h2とかにアンカーをつけてくれる。技術記事は引用が多そうなのでつけています。gatsby-remark-external-links外部リンクを別タブで開かせるためにつけてます。gatsby-remark-check-linksサイト内リンク切れを防止するプラグインです。今までこちらの動作に引っかかったbuildが一度もないので、使っているかと言えばつかっていないかもです。gatsby-plugin-layoutいわゆるWFのLayout(共通的な側を作る)機能です。このブログでは、全ページで表示されるNavbarの実装とページ遷移時のトランジションの実装で使ってます。gatsby-plugin-sitemapサイトマップを作ります。gatsby-plugin-nprogressページ遷移時にprefetchされていないpage-data.jsonがあった場合、ロードが発生してしまうので、そこで出すグルグルを出してます。出てくる場面が少ないほうがよいですね。gatsby-plugin-optimize-svgsSVGの最適化をしてくれるプラグインです。だいたい50%くらい削れているそうです。gatsby-plugin-manifestPWAのマニフェストファイルを作ってくれます。モバイルからのアクセスも結構あったりしますのでPWAは重要です。gatsby-plugin-minifyいわゆるminify系のプラグイン。ビルドされた成果物をとことん読みにくくしてくれる代わりにサイズを小さくしてくれます。1%くらい小さくなっているっぽいです。Worker対応をかんたんに実装してくれます。gatsby-plugin-manifestと合わせればモバイルの場合、アプリっぽい実装が実現できます。(このブログでその必要があるのか疑問ですが...)gatsby-plugin-netlifyNetlifyが解釈できる_headersファイルを生成しています。Controlを定義しており、できるだけCacheを見てもらう感じで攻めます。APIを使って定義します。これが結構優秀でただMarkdownを読み込んでHTMLをPropsでTemplateにそのまま渡すだけではなく、独自にcontextを生成し、Propsで渡すことができます。build時に実施するようにしてます。Reactが処理するコード量を小さくしてあげ、必要な情報をcontext経由で渡してあげることで、ページ遷移時のレンダリングコストを小さくできると信じてます。(逆に転送量が上がる気もするので微妙かもしれません。)もはや自己満足の世界です。可読性は大きく損ねるしバグの温床なのであまりおすすめはしません。Reactで処理させたり、Markdownで直接定義したほうが100倍わかりやすいです。});};GatsbyのTypeScript化GatsbyのTypeScript化は2021年の年末くらいに実施しました。TypeScript化の前に依存ライブラリの都合上Gatsby自体のバージョンアップ(v2=>v4)を先にしないといけない状況で、結構苦労した記憶があり本当はちゃんと記事を書きたかったのですが、もうすべてを忘れてしまいました。今ではTypeScriptの型を存分に享受してます!特にGatsbyのTypeScript化で苦労するところはMaybe型の扱いだと思います。基本的にgatsby-plugin-typegenがGraphQLのスキーマーから型を自動生成してくれるのですが、その際の型がほとんどMaybe型といういわゆるundefinedが返る可能性を示すものとなります。chainingをひたすら書かないといけません。chainingに慣れておきましょう!まじで...。Preactの導入ブログをGatsbyで作りはじめて色々詰め込みすぎたため1年位たったあたりでやたら重たいブログになってしまったという苦い経験があり、なんとなくReact→Preactへの切り替えを実施した記憶があります。こちらはプラグインの指示通り入れればすんなり動いた感じで特に苦労しませんでした。複雑な遅延処理やstateの管理、useEffectのような副作用を使わないサイトだったのでpreact/compatを使わないで実装しきれたからだと思います。Preactの効果は結構あって、gatsby-plugin-webpack-bundle-analyser-v2でバンドルサイズを比較して1MB以上の削減効果があった(らしい)です。当時のPreact切り替えのつぶやきを綺麗サッパリ消してしまっていました。tw-del-backupは削除したつぶやきを暗号化してバックアップしているので、そちらを確認すると1MB以上削減できたということです。tw-del-backupは定期的にTweetのバックアップと削除を行なう便利ツールですが、つぶやきが消えることで、添付している画像も合わせて消してしまう仕様になっており、これはまずいですね。画像も暗号化して保存するように作り直そうかしら...。詳しくはCI/CD編でお話しようかと思うのですが、現在のProductionバンドルサイズはhttps://tubone24.github.io/blog/ba/にホスティングするようにしているのでいつでも確認可能です。Parsedで1.35MB、GZip圧縮で343KBなのでやや重いですが、まぁ妥当な数字ではないでしょうか?(内半分はGitalkというコメント管理のライブラリです。ModulesこのブログのスタイルはCSSフレームワークBootstrapがベースとなってます。いう感じでBootstrapをそのまま使うことにしました。v3で使うjQueryとBootstrapのCSSのloadタイミングが狂ってしまい、うまく動かなくなってしまい実にツライことになりました。v5へのバージョンアップを済ませてから各ライブラリのバージョンアップを行ない、最後にTypeScript化する、という大工事を強いられたのです。CSSなどへの切り替えも検討していたのですが、モバイル対応のため採用していたGridシステムの置き換えが想像以上に大変だったことと、今のブログデザインを大きく変えたくなく、Bootstrapのほうが逆に古臭くて好きなのでいいかなと思ってBootstrapを使い続けることにしてます。UIとか、tailwind-gridとかいろんな技術を触ってみましたがいずれしっくりこなかった、というより技術力がなくて使いこなせませんでした。今年こそは技術力を上げていきたいですね。v3を何とかするに詳細がありますので詳しくはそちらをご覧ください。細かいスタイルの調整にはSass(SCSS)を使ってます。コマンドを実行した際にできるテンプレートで採用されていたこととCSSライクな記述なら初心者でもとっつき安いかなという安易な考えで採用しました。Modulesに移行しました。会社ではstyled-componentsを使ってますが、CSSに弱い私にはCSSはCSSで分かれたファイルの方がIDEでの補完がききやすく個人的にはSassに満足してます。Tailwindへの憧れはPurgeCSSで解決しろ!とはいえ、流行っているTailwindへの憧れを捨てきれずにいた私は、どうしてBootstrapではなくTailwindを使いたいのかを改めて自分に問いかけました。CSSできるようにgatsby-plugin-purgeCSSを使いました。CSS処理で巨大なCSSを作り、Purgeさせてます。削れているっぽいです。Modulesもできるだけ小さくするべく、こちらはgatsby-plugin-minify-classnamesを使ってます。1rem;}といった感じでクラス名がちっちゃくなります。これでどれくらいサイズが小さくなっているのかは不明ですが、多分自己満足の世界だと思います。Gatsby嫌なところここまでGatsbyのいいところを紹介してきましたが数年運用していてツライと感じる点もご紹介しておきます。これはいいところの相反ですが、やはりGraphQLを否応がなく意識させられます。それもGatsbyのプラグインシステムが作ったスキーマーを正しく理解することが求められます。言い方かもしれませんが、GraphQLの知識は求められるのにGraphQLが使いこなせるようにはならない感覚に近いです。GraphQLを勉強したい!という理由一点張りで採用することはあまりおすすめできないなというのが私の所管です。あと、プラグインが便利すぎて使いまくっているのですが、結構動作原理がわかりにくいです。プラグイン同士の競合もめっちゃします。そのデバッグは骨が折れるので、ちゃんとコードが書ける人はスクラッチしたほうが無駄な時間を過ごさなそうです。一例ですが、gatsby-plugin-typegenとgatsby-source-filesystemみたいに、コード自動生成系のプラグインとデータソースのプラグインはお互いの処理をトリガーに処理が走る可能性があるので、処理がループしがちです。いったところを解きほぐしていくのはプラグインでサクサク実装したい思想から外れてしまう動きなのかもしれませんね..。その他の要素技術ブログ本体に関するその他の要素技術についてもサクッとまとめていきます。Blog内検索ブログ開設当初から、ブログ内で記事検索ができたらいいなぁーとずっと思ってました。キーワードつけてあげれば実装できそうですが、いったんGoogleに遷移する動きもちょっとダサいですし、公開直後の記事が反映されないのもツライです。独自に検索できる仕組みを用意することにしました。gatsby-plugin-algoliaを使えば比較的かんたんに検索窓を実装できます。Algoliaという全文検索エンジンにIndexを作っておけばBuild時にGraphQLのQueryから抽出されたdataをIndexしてくれます。このブログではタイトル、タグの他本文も少し加えるようにして検索性向上を図ってます。検索窓(Searchbox)の動きはこのブログのコンポーネントを管理しているStorybookから確認できます。画像のホスティングこのブログの特徴でもありますが、画像のホスティングはimgurを使ってます。他の画像ホスティングサービスも検討しましたが無料は正義なのと、URLのsuffixをいじると画像サイズが変えられるのが魅力で採用しております。GatsbyにはSharpを使って画像最適化する仕組みがありますが、画像枚数が多くなると著しくBuild時間がかかるので、こちらの採用は見送りました。コメント機能ブログといえば、コメント機能ですね。コメント機能は入れております。このブログではGitalkをコメント機能で採用してます。GitHubのIssueがデータソースになる仕組みで、記事ごとにIssueが作られ、コメントはIssueへのコメントの形で反映されます。非常に良くできたプロダクトだと思います。この数年コメントが来てません...。Icomoonブログで使うアイコンはFontawesomeを使ってますが、Fontawesomeのアセットが大きかったので、Icomoonを使って利用する最小限だけFontファイルに再パッケージする形にしてます。Icomoonを使うことで任意のIconfontを作ることができるので、Fontawesomeだと全部入りすぎてちょっと...というとき、結構使えるかもしれません。独自に設定したFontであるので、下記のように文字コードとの対応をCSSで設定する必要があります。SitemapブログだとRSSとSitemapも作らないといけません。SEO上でも重要ですね。それぞれgatsby-plugin-feedとgatsby-plugin-sitemapというGatsbyプラグインで実現してます。変わったことはせず、Build時にXMLを生成しているだけです。実はa11yにちゃんと対応しているこのブログです。会社のフロントエンドツヨツヨエンジニアさんと去年勉強会する機会があり、a11y対応についての共有をいただきました。それまでは「ほ~ん」くらいの興味しかなかったa11yですが、知れば知るほどHTMLというマークアップ言語の正しいあり方を示されてるようでそこからこのブログのa11y対応が始まりました。今ではトップページLighthouseで100点を取ることができるくらいに改善できました。勉強会してもらい、ありがとうございます!!!ちなみにa11yってなんて読むんですか?「アリー?」「エーイレブンワイ?」Sentry一応監視系もしっかりしたほうがええな、ということでSentryを導入してます。ほとんどがChunkLoadErrorですが、たまにライブラリーアップデート起因のエラーもでるのですごく重宝してます。あと、パフォーマンスメトリックも取っているのでパフォーマンス改善への意欲づくりに貢献してます!意欲だけあって実行しないですが。Netlifyこのブログのホスティング先はNetlifyを採用しております。理由はこのブログを作ろうと思ったとき無料で使える良さそうなホスティングがNetlifyとFirebaseホスティングくらいしかなかったのでGitHubと連携すればBuildまでやってくれるNetlifyを採用しました。Firebaseホスティングに比べると帯域制限が少ないのが魅力ではありましたが、やはり上がる課題として日本からのTATが遅すぎる(最寄りのCDNエッジはシンガポールとのこと)点です。課題は有りまくりです。Pagesとか別のホスティングも検討したいですが、CI/CD含めて作り込んでしまったのでサンクコストになって移行できてません。その代わりにバンドルサイズを下げたりして、TATが遅くてもなんとかなるようにしてやってます。CLIでDeployする形式を採用してます。Actionsで0時間にして月末のヒヤヒヤから解放されよう!に詳しく書いてあります。マジで細かく記事をコミットしたいような書き方してると無料枠簡単に突破します。まとめという感じで結構いろんなことをやっているブログですが、パフォーマンスはどんな感じでしょうか?GTmetrixで計測するとスコアはA。metricもおおむね良さそうです。Insight)で測ってみるとデスクトップはまずまずですが、モバイルの結果がすこぶる悪いです。ある程度スピードを要求されるため、スコアを上げるには、JavaScriptの節約がモット必要なようです。v4を使ってアクセス解析も実施してます。Insightが使えるので、せっかくなのでこのブログの稼ぎ頭記事も見てみましょう。Particles、ラズパイ電子ペーパーあたりが上位っぽいです。今年こそバズる記事を量産したい...。