Nuxt 3 を Cloudflare Workers で使ってみた

2021/11/05に公開

Nuxt 3 の特徴のひとつに Nitro を使ったレンダリングがあります。
CDN の Serverless Functions を使って、設定無しで SSR できるようになっただけでなく ISG (インクリメンタル静的ページ生成)を様々な環境で利用できるようになります。

Serverless Architecture が普及し Jamstack によるコンテンツの提供やサイト開発を行う下地が整ってきていることが背景にあるのでしょう。
Nitro および Nuxt が優れているのは Netlify や Vercel といった Nuxt でおなじみの環境にとどまらず、そのほか多くの環境において少ない(もしくはゼロ)設定で利用できることです。

ベータリリース時点でドキュメントに記載されている環境は次のとおりです。
Azure, Cloudflare Workers, Firebase Hosting, Netlify, PM2, Vercel, AWS Lambda, Node.js server (default), Node.js function, Service worker

Cloudflare Workers で試してみた

これまで試せずにいた Cloudflare Workers をこの機会に利用してみました。
Edge Side Rendering という言葉がありますが Edge Side といえば AWS だけでなく、大手 CDN の Cloudflare をイメージする人も多いのではないでしょうか。
通常200ミリ秒未満でコールドスタートするという Cloudflare Workers は Cloudflare の強みを活かした、他社がおいそれとは真似できないサービスだと思います。

アカウントの取得 と アカウント ID の確認

運営している コワーキングスペース茅場町 Co-Edo の Web サイトは Cloudflare の DNS を利用しています。
Cloudflare Workers でも同じアカウントが使用できましたので、今回あらたにアカウントを取得する必要はありませんでした。

Cloudflare Workers の利用には アカウントID が必要になりますがダッシュボードの右カラムの「Workers」のリンクより遷移したページで、右カラムにアカウントIDが確認できます。

*.workers.dev のサブドメインを設定できますので、お気に入りのものを設定しておきましょう。
次のURLを利用できるようになります。

project-name.your-sub.workers.dev

CLI ツールのインストール

Cloudflare Workers の CLI ツール wrangler が用意されています。
どこでも使えるように -g オプションをつけてインストールしておきます。

npm i @cloudflare/wrangler -g

つづいて Cloudflare の認証を行います。

wrangler login

ブラウザを開いて [Wrangler を認証] ボタンをクリックしログイン後、画面の支持に従いアクセス権限を付与します。

Nuxt 3 を始める

通常ですと npx nuxi init で Nuxt 3 を入れます。
ここ最近何度も環境を作っているのでお手軽に始められるスターターテンプレートを用意したので、それを利用します。
Nuxt 3 に VueUse と Windi CSS を入れたシンプルなテンプレートです。

git clone git@github.com:monsat/nuxt3-starter.git nuxt-cloudflare-app
cd nuxt-cloudflare-app
yarn

必要に応じて Git 環境を入れ替えてください。

git remote rename origin template  # origin → template に変更
gh repo create                     # 自分の GitHub リポジトリを作成
git push -u origin main            # main ブランチをプッシュ

これで template:main がclone元のリモートブランチで origin:main が自分の GitHub アカウント上のリモートリポジトリのブランチになりました。

ghGitHub CLI のコマンドです
代わりに git remote add origin ~~~ としても、もちろん自分のリモートリポジトリを設定できます

Nuxt 3 の動作確認

次のコマンドで開発環境で動くことを確認します。

yarn dev

http://localhost:3000 でフロントページが表示されたら無事 Nuxt 3 が動いています。

wrangler.toml の作成

Nuxt 3 の公式ドキュメントに従って、プロジェクトフォルダ直下に wrangler.toml を作成します。
アカウントID以外は下記のままで構いません。

wrangler.toml
name = "playground"
type = "javascript"
account_id = "<アカウントIDをここに>"
workers_dev = true
route = ""
zone_id = ""

[site]
bucket = ".output/public"
entry-point = ".output"

[build]
command = "NITRO_PRESET=cloudflare yarn nuxt build"

[build.upload]
format = "service-worker"

ビルドし wrangler dev で Cloudflare Workers と同様の環境で動くか確認しましょう。

NITRO_PRESET=cloudflare yarn build
wrangler dev

http://localhost:8787 で同じくフロントページが表示されることが確認できるはずです。

デプロイは次のようにします。

NITRO_PRESET=cloudflare yarn build
wrangler publish

package.json を更新しておくと便利ですね。

package.json
  "scripts": {
    "deploy": "NITRO_PRESET=cloudflare yarn build && wrangler publish",
    "dev": "nuxi dev",
    "build": "nuxi build",
    "start": "node .output/server/index.mjs"
  },

https://your-sub-domain.workers.dev/ でフロントページが表示されれば、無事デプロイ完了です。
デプロイも速いし、ページの描画も速いし、どちらも軽く衝撃を受けました。

/server/api/hello.ts で API を作成する

せっかくなので /api/hello でアクセスし JSON を返す API を作りましょう。
Nuxt 3 では /server/api/ 以下の JavaScript ファイルで簡単に API を作成できます。

server/api/hello.ts
import type { IncomingMessage, ServerResponse } from 'http'

export default (req: IncomingMessage, res: ServerResponse) => {
  return {
    message: 'Hello World',
  }
}

http://localhost:3000/api/hello で JSON を取得できるでしょう。

いちおうアプリケーションで fetch するところも用意します。

components/GetHello.vue
<script setup lang="ts">
const { data } = await useFetch('/api/hello')
</script>

<template>
  <div>
    <p>{{ data.message }}</p>
  </div>
</template>
pages/hello.vue
<template>
  <div>
    <GetHello/>
  </div>
</template>

デプロイして無事 Hello World が表示されれば完了です。 🎉

Cloudflare Pages を使うと管理が便利になりそうなので、別途試してみたいと思います。

GitHub Actions で自動デプロイ(現時点では動きません)

公式ドキュメントに GitHub Actions を使った自動デプロイ環境の構築方法も掲載されています。
マイプロフィールの API トークン より [トークンを作成する] 後 GitHub の Actions secrets に CF_API_TOKEN で登録すれば、公式ドキュメントの .github/workflows/cloudflare.yml をそのまま利用するだけです。

が、現時点でデプロイに失敗します。

最後の Publish to Cloudflare で次のようなメッセージが表示されます。

yarn run v1.22.15
$ /github/workspace/node_modules/.bin/nuxt build
[log] Nuxt CLI v3.0.0-27258467.4e424d0
Error:  Unexpected token '.'
  at Loader.moduleStrategy (internal/modules/esm/translators.js:140:18)
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
Error: Build failed! Status Code: 1

原因が分かりましたら追記したいと思いますが、解決方法が分かる方がいらっしゃいましたら、ぜひ教えてもらえると嬉しいです。

Discussion