QLITRE DIALY

Hono x microCMSブログ、Cloudflare Workers→Pagesへ置き換え記録

2024年03月31日

このブログはCloudflare Workersで動かしているが、デプロイ先をCloudflare Pagesに置き換えようと思った。

Hono開発者のゆーすけべーさんの記事によると、Workersでのフルスタックアプリケーションのデプロイは現在非推奨となっているらしい。そのため、今後のメンテナンス性や拡張性を考えて、移行作業をする。

Honoの新しいCloudflare Pagesスターターについて

置き換えでつまづいた点も多く、かなりメモ的に作業記録を追っていく。

Viteベースへの置き換え

まずはViteで開発サーバーが立ち上がる設定をする。

開発中のプロジェクトのnode_modulesを一旦削除し、package.jsonとtsconfig.jsonを以下のようにする。

// package.json
{
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "wrangler pages dev dist",
    "deploy": "$npm_execpath run build && wrangler pages deploy dist"
  },
  "dependencies": {
    "hono": "^4.1.5"
  },
  "devDependencies": {
    "@cloudflare/workers-types": "^4.20240208.0",
    "@hono/vite-cloudflare-pages": "^0.2.4",
    "@hono/vite-dev-server": "^0.9.0",
    "vite": "^5.0.12",
    "wrangler": "^3.32.0"
  }
}
// tsconfig.json
{
  "compilerOptions": {
    "target": "ESNext",
    "module": "ESNext",
    "moduleResolution": "Bundler",
    "strict": true,
    "lib": [
      "ESNext"
    ],
    "types": [
      "@cloudflare/workers-types",
      "vite/client"
    ],
    "jsx": "react-jsx",
    "jsxImportSource": "hono/jsx"
  },
}

yarn installする。

yarn install

開発に必要なライブラリを別途installする。

自分の場合はmicrocms-js-sdkdayjsを使っている。

yarn add microcms-js-sdk dayjs

ルートディレクトリにvite.config.tsを作成する。

// vite.config.ts
import build from '@hono/vite-cloudflare-pages'
import devServer from '@hono/vite-dev-server'
import adapter from '@hono/vite-dev-server/cloudflare'
import { defineConfig } from 'vite'

export default defineConfig({
  plugins: [
    build(),
    devServer({
      adapter,
      entry: 'src/index.tsx'
    })
  ]
})

この時点でyarn devをしてhttp://localhost:5173/にアクセスするとエラーになる。

require is not defined

どうもmicrocms-js-sdkにasync-retryというpackageが使用されており、その中でViteで動かせないrequire文が利用されているのが原因っぽい。

Xでつぶやいているとゆーすけべーさんが解決策を教えてくれた。感謝です。

提案されたissueの通りにvite.config.tsを以下のように修正する。

import build from '@hono/vite-cloudflare-pages'
import devServer from '@hono/vite-dev-server'
import adapter from '@hono/vite-dev-server/cloudflare'
import { defineConfig } from 'vite'

export default defineConfig({
  ssr:{
    external:['microcms-js-sdk','dayjs']
  },
  plugins: [
    build(),
    devServer({
      adapter,
      entry: 'src/index.tsx'
    })
  ]
})

起動させると今度は違うエラーが出る。

Cannot find module '__STATIC_CONTENT_MANIFEST'

Workersで静的ファイルを扱うにあたり以下のように__STATIC_CONTENT_MANIFESTを利用していた。

import { Hono } from 'hono'
import { serveStatic } from 'hono/cloudflare-workers'
import manifest from '__STATIC_CONTENT_MANIFEST'

type Bindings = {
    API_KEY: string
    SERVICE_DOMAIN: string
}

const app = new Hono<{ Bindings: Bindings }>()

app.use('/static/*', serveStatic({ root: './', manifest }))
app.use('/sitemap.xml', serveStatic({ path: './sitemap.xml', manifest }))
app.use('/favicon.ico', serveStatic({ path: './favicon.ico', manifest }))
app.use('/ads.txt', serveStatic({ path: './ads.txt', manifest }))
...

これがvite環境だと動かないらしく、以下のように設定を変更する。

※Workersの際はassetsディレクトリに静的ファイルを置いていたが、publicディレクトリに移行する。

import { Hono } from 'hono'
import { serveStatic } from 'hono/cloudflare-pages' // 変更


type Bindings = {
    API_KEY: string
    SERVICE_DOMAIN: string
}

const app = new Hono<{ Bindings: Bindings }>()
const limit = BLOG_PER_PAGE

app.use('/static/*', serveStatic())
app.use('/sitemap.xml', serveStatic())
app.use('/favicon.ico', serveStatic())
app.use('/ads.txt', serveStatic())

ここまででページが立ち上がることを確認する。

ローカルビルドしてみる

yarn buildする。

yarn build
>>>
yarn run v1.22.19
warning package.json: No license field
$ vite build
vite v5.2.7 building SSR bundle for production...
✓ 56 modules transformed.
dist/_worker.js  47.76 kB
✓ built in 495ms
Done in 1.70s.

dist配下にビルドされていることを確認する。

しかし小さくて驚く。47.76KBって…。

yarn previewして立ち上がっていることを確認したら終了。

デプロイ

これもyarn deployするだけだが、windowsだとデフォルトで用意されているデプロイコマンドが失敗する。

warning package.json: No license field
$ $npm_execpath run build && wrangler pages deploy dist
'$npm_execpath' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

以下のように編集する。

{
  ...
  "scripts": {   
    "deploy": "yarn build && wrangler pages deploy dist"
  },
  ...
}

そうするとdeployが走る。

No project selected. Would you like to create one or use an existing project?
> Create a new project
  Use an existing project

とりあえずCreate a new projectを選択。

Cloudflareのダッシュボードに行き、サイトURLを確認すると、500 Internal Server Errorが起きている。

Workersの際はデプロイ時にwrangler.tomlに設定した環境変数も併せてデプロイしてくれるが、Pagesの方は自分で設定する必要があるらしい。

ダッシュボードのSettingsタブより環境変数を追加できる。

動作に必要な環境変数を設定してyarn deployし直す。

サイトが動いていることを確認できる。

ドメイン設定

Workersに向けているドメインをPagesに向け直す。

一旦サイトを削除してPagesからカスタムドメインを設定し直す。

以下の記事を参考に設定しました。

ソースコード

https://github.com/qlitre/hono-qlitre-dialy

おわりに

ところどころつまづいたけど無事に移管ができてよかったです。

次回はSSGに挑戦してみようと思います。ではでは。