この 1 年半くらい、 MonCargo という会社で創業 CTO をしています。たまには技術ブログっぽいものを書きます。
概要
自社サービスを Next.js から Astro + Vite に移行して分割したメモ。
LP 等の静的なページは Astro で、 SPA の部分は Vite にした。 これにより、 MonCargo 社のスタックから Next.js が消えた。創業して約 1 年半、お世話になりました。
前提
- Netlify にて Next.js を Static Export して使っていた
- ドメインは moncargo.io でサブドメイン運用はしていない
モチベーション
- LP とサービスのコードベースを分けたかった
- LP の修正でサービスに影響がでる、みたいな事態を避けたいため
- Next.js は静的サイトジェネレーター的に使うと不自由があった
- 多言語対応がいい感じにできない
- せっかくの
next/image
は Static Export では使えない
- Next.js は静的なサイトにはオーバースペックに感じた
- 逆にダッシュボード的な SPA だと SSR 周りでたまにハマったりした
意思決定
- サブドメイン運用は一旦やらない
- 本当は下記のようにしたかったが、認証などで既存ユーザーの手間をかけたくなかった
- LP: moncargo.io
- Blog: moncargo.io/blog
- SPA: app.moncargo.io
- 本当は下記のようにしたかったが、認証などで既存ユーザーの手間をかけたくなかった
- コンポーネント志向が良い
- React 分かってれば OK な状態にして学習コストを減らしたい
- TypeScript で書きたい
- フロントもバックもすべて TypeScript なため
- 型安全に開発したい
移行と選定基準
まず、 LP は Astro 一択だった。現在のコードがほとんど活用できるし、型安全だし、 LSP いい感じで現代的に書ける雰囲気を感じた。多言語対応のガイドも公式ドキュメントにあったのでやりやすそうだった。 なお、お問い合わせフォームの部分だけ React を使っている。コードはほとんど変えていない。
SPA の方は一旦 Next.js のままでも良いかなと思ったが、勢いで Vite に乗り換えた。 起動もビルドもやや速くなった気がするが誤差かも。
また、これを機に Netlify から Cloudfront に移行した。 Netlify は無料プランだったので、日本からだと配信がやや遅かったので、 Cloudfront にして明らかに速くなった。 最近は Cloudfront で Brotli がサポートされたので、その辺りを気にしなくて良いのも嬉しい。
なお、静的サイトの公開においては /about
を /about.html
にするなど、各種リダイレクト・リライトが必要になるので、その辺りは Cloudfront Functions でやった。
cloudfront function for static sites
Function めっちゃ便利だった。移行の過程で多少リダイレクトが必要になる箇所があったのだが、全て Function で対応できた。言語別に LP をリダイレクトさせるとかも割と簡単にできる。コードは Terraform で管理できるしいい感じ。
良かったこと
- やはり LP と SPA のコードが分かれているのは嬉しい
- LP の方は気軽にデプロイしたり修正したいので、気が楽になった
- デプロイ時間も短縮された(GitHub Actions で 30 秒とかのレベル)
- Astro 最高
- 画像の最適化に一番感動した
- コード量は 1 つのコンポーネントあたり 7 割くらいに削減された気がする
- 1 ファイル = 1 コンポーネント にしないといけないので、自然と読みやすいコードになった
- Lighthouse のスコアほぼ 100 点。まあ拘らなくて良いかな
困ったこと
- Astro の
<script>
タグの扱いにはまった- 1 つのファイルに複数書いたら動作しなくなったりした
- Vite みたいに index.html 的なところに書けたら楽なのかも
- React Router が高機能すぎてめちゃめちゃ使いにくくなってた
- Remix 推してるからか?
- 代替として Wouter にした。 Hooks の API あんま好きじゃないけど…
- ちなみに多言語対応は模索中
- ttag で生成したコードを使っているのだが、 Astro では使えないので別の方法を検討している
- 個人的な好みで GNU gettext 形式 (.po ファイル)で管理したいので、無かったら作ろうかなと考えている
- gettext 形式、名前と分類を考えなくて良いのでめっちゃ楽なんだよな…