@fastly/next-compute-js を試す
fastlyでnext.jsのホスティング用の機能がリリースされていたので試してみる。
知りたいこと
いまのところ Static HTML Exportを利用して pages/xxx/[id].jsx
のような動的ルーティングを動かすためには下記の手段が必要になると思っている↓
(getStaticPropsでビルド時にデータは参照せず、マウント後に非同期で取得するケース)
- vercelを利用する
static利用が中心だが帯域だけでエンプラ料金になる可能性がある -
serverless next pluginを利用する or これ相当のデプロイ機構を準備する
ライブラリの中身を理解する必要がありそう (コードで管理されるためnext.jsの変更によっては、対応することが出てきそう) -
lambda, cloud functionsなどでルーティングのみ動的に解決する
ルーティング層のメンテが必要になりそう - 自前でサーバを立てて
$ next build && next start
で動かす (next exportを利用しない)
サーバのメンテナンスを行う必要があり graceful shutdownなどにも配慮する必要が出てくる
(custom serverでシグナルのハンドリングを行う)
上記のようにvercelを利用するか自前でサーバーを立ててメンテナンスをする必要が出てくるため大変な印象がある。
(これが理由でnuxt.jsを選んでいるプロジェクトも多いのかな..?と想像している)
前述のリリース記事には オリジンサーバーも必要ありません という記載があり、vercel以外の選択肢でサーバのメンテナンスが不要になるのか確認したい。
next export
の説明付近にFastly を介して静的サイトを配信することはもちろんできますが (これに関する耳寄りなニュースを近日中にお届けします!)と記載があるため、 @fastly/next-compute-js
を利用しない方法も提供されそう?(静的ホスティング + 動的ルーティングの自動解決)
next build コマンドで生成されるのとまったく同じビルド成果物上で動作し、Next.js ランタイムのあらゆる機能を利用できるようにすることを目指して作成されています
この機能はserverless next pluginでAWS上に next start
で動くサーバーを立てたときと同じ動作を提供してくれるものらしい。
(恐らくapiやpages単位でedgeサーバ(serverless function)を作ってくれる)
下記リポジトリにサンプルコードを乗せていく↓
セットアップ
next-compute-jsの初期化
$ npx @fastly/next-compute-js
./compute-js/
が作成される。
fastly CLIでデバッグ
fastly CLIをhomebrewでインストールする。
$ brew install fastly/tap/fastly
$ cd compute-js
$ fastly compute serve
$ open http://localhost:7676
./compute-js/statics.js
が作成される。
Compute@Edge上で動いた時の挙動をローカルで確認できるコマンドらしい (fastly初心者)
fastly CLIでデプロイ
事前設定
- fastlyアカウント作成
- personal api tokenの発行
- CLIのセットアップ (プロファイル作成)
https://zenn.dev/hrmsk66/articles/74e2e890726e99
$ fastly profile create test
# ここでtokenの入力が求められる
# => created ~/Library/Application\ Support/fastly/config.toml
$ fastly compute publish
# => created ./fastly.toml
fastly.tomlに個人情報が追記されるがリポジトリではignoreしている。
CLIで色々聞かれるがすべてenterでデフォルトにした。
なぜか1回目は失敗した..
1回目
Create new service: [y/N] y
Service name: [fastly_next-next-compute-js-app]
✓ Initializing...
✓ Creating service...
Domain: [xxx.edgecompute.app]
Backend (hostname or IP address, or leave blank to stop adding backends):
✓ Creating domain 'xxx.edgecompute.app'...
✓ Uploading package...
✗ Activating version...
ERROR: the Fastly API returned 503 Service Unavailable: .
2回目
✓ Initializing...
✓ Verifying package manifest...
✓ Verifying local javascript toolchain...
✓ Running [scripts.build]...
✓ Creating package archive...
SUCCESS: Built package (pkg/package.tar.gz)
✓ Uploading package...
✓ Activating version...
Manage this service at:
https://manage.fastly.com/configure/services/xxx
View this service at:
https://xxx.edgecompute.app
CLIの出力にデプロイ先のURL https://xxx.edgecompute.app
に無事アクセスができ、
next build && next start
と同じ内容が表示された。
npm scriptsにfastly CLIのコマンドを追加しておく
ダイナミックルーティングの挙動を確認する
serverless next pluginと同様にedgeサーバを作成していそうなため、
できると思うが一応試してみる。
動的ルーティングを行うpagesとダミーデータを返すapiを追加
- api/
- posts/
- index.ts
- [id].ts
- posts/
- pages/
- posts/
- index.tsx
- [id].tsx
- posts/
これでデプロイ結果を見る (よく考えたらドメインは公開しても問題ないため貼っておく)
- /posts
https://absolutely-amused-beetle.edgecompute.app/posts - /posts/uuid-1
https://absolutely-amused-beetle.edgecompute.app/posts/uuid-1
途中で気づいていたけど当たり前に動いた😇
結論
-
@fastly/next-compute-js
を利用すればvercelを利用しなくても自前でサーバーを用意せずに next.js が利用できる。- next/image, preview mode, middleware, ISR, dynamic import などは使えないが、静的ホスティング目的なら十分そう
- デフォルトでedgeサーバが利用されるためパフォーマンスも良い
- 価格は調査する必要がある (vercelよりは優位性がある価格だと信じている)
- 静的ホスティングができればもっと安くなるはずなので続報を待つ
最後に静的ホスティングの手段も触れられていた↓
次はこれを見ていく
@fastly/compute-js-static-publish
api routes は $ next export
時に怒られるため削除
$ npm run build
# => .next/ の生成
$ npm run export
# => out/ に静的ホスティング用のファイルが出力される
下記に沿って進める↓
上のセクションで作成した compute-js/
を削除してから下記を実行
$ npx @fastly/compute-js-static-publish --preset=next
# => created compute-js/
$ cd compute-js
$ npm i
$ fastly compute serve
$ open http://localhost:7676
ローカルでは詳細ページが404になる。
新しく compute service をfastlyの管理画面から追加しておく。
./compute-js/fastly.toml
の service_id
を作成したものに書き換える。
$ fastly compute publish
やはり詳細ページは404になる..
[id].html
のルーティングが解決できていない。
(next/routerでのspa遷移はできているが直接URLを叩いてアクセスはできない)
- posts
https://reasonably-shining-rhino.edgecompute.app/posts - posts/uuid-1 (追記: 後述の対応で見れるようになっている)
https://reasonably-shining-rhino.edgecompute.app/posts/uuid-1 - posts/[id].html
https://reasonably-shining-rhino.edgecompute.app/posts/[id].html
compute-js/index.js
でルーティング処理が記載されていたため、
下記のように変更したら詳細ページのURLも解決できた↓
ただ、ルーティングのメンテが必要になるため最初の問題に帰結する 😇
issueを作ったが2つ目なので次の記事を待った方が良さそうな気がしてきた。
上記のissueに回答をいただいた。
やはりnext exportで出力されたコンテンツを静的ホスティングする場合に、プレビルド時に解決されないダイナミックルーティングはサポート外らしい。
エッジと合わせて新しく出たサービスだったので、ルーティングが自動解決される仕組みも期待していた。
(vercelも自サービスを使ってほしいはずなので、今後next.js自体でのサポートもされないと予想される)
とはいえ @fastly/next-compute-js
に関しては next start
で動かす際のホスティング候補にfastlyのcompute@edgeが加わったため、インフラコスト・敷居を下げてくれてくれそうだと思う。
fastlyはCDNとしてのキャッシュパージの仕組みも充実しているため、メンテナンスやチューニングフェーズでの移行も踏まえると少し高くてもawsやgcpに自前でサーバー(+ストレージ, サーバレス関数)を用意するよりは中長期的にコストも回収できると思っている。
(値段は比較していない)