AstroのSSRモードで作成したサイトを、Cloudflare Pagesにデプロイする際の覚書
Astroは、サーバーサイドレンダリング(SSR)モードを持つが、Cloudflare Pages / Workersにデプロイする場合、Node.jsではない実行環境に注意が必要。AstroにCloudflareのSSRモードを追加するには、`astro add cloudflare`コマンドを実行。`astro.config.mjs`の変更を自動で行い、プレビューが表示される。しかし、Markdocファイルを読み込む際のエラーが発生した場合、Cloudflare Workers / Pages Functionsの実行環境ではfsモジュールがサポートされていないため、Markdownファイルの読み込みに関しては静的にビルドしてデプロイする必要がある。
目次
Astroには、サーバー側で処理を実行できるSSRモードが搭載されています。ただ、Cloudflare Pages / Workersにデプロイする場合は、実行環境がNode.jsではないことに注意が必要です。
AstroプロジェクトにCloudflareモジュールを追加する
CloudflareのSSRモードをAstroに足す場合、astro add cloudflare
コマンドを実行します。
% npx astro add cloudflare
Astro will run the following command:
If you skip this step, you can always run it yourself later
╭────────────────────────────────────────────╮
│ yarn add @astrojs/cloudflare astro@^2.1.0 │
╰────────────────────────────────────────────╯
? Continue? › (Y/n)
astro.config.mjs
の変更まで自動で行ってくれます。実行時にプレビューが表示されるので、気になる方は確認しておきましょう。
Astro will make the following changes to your config file:
╭ astro.config.mjs ──────────────────────────────╮
│ import { defineConfig } from 'astro/config'; │
│ import mdx from '@astrojs/mdx'; │
│ import sitemap from '@astrojs/sitemap'; │
│ import markdoc from "@astrojs/markdoc"; │
│ │
│ import cloudflare from "@astrojs/cloudflare"; │
│ │
│ // https://astro.build/config │
│ export default defineConfig({ │
│ site: 'https://example.com', │
│ integrations: [mdx(), sitemap(), markdoc({ │
│ nodes: { │
│ heading: { │
│ render: 'Heading', │
│ attributes: { │
│ level: { │
│ type: String │
│ } │
│ } │
│ } │
│ } │
│ })], │
│ output: "server", │
│ adapter: cloudflare() │
│ }); │
╰────────────────────────────────────────────────╯
For complete deployment options, visit
https://docs.astro.build/en/guides/deploy/
問題なければ、yes
と回答して編集を完了させます。
✔ Continue? … yes
success Added the following integration to your project:
- @astrojs/cloudflare
AstroをCloudflareでSSRして使う際に踏んだエラー
試していたプロジェクトでは、次のエラーが出ました。
error post.render is not a function
File:
/Users/okamotohidetaka/sandbox/astro-markdoc/src/pages/docs/[...slug].astro:23:34
Stacktrace:
TypeError: post.render is not a function
at eval (/Users/okamotohidetaka/sandbox/astro-markdoc/src/pages/docs/[...slug].astro:23:34)
追いかけていくと、このエラーが根元にある様子でした。
error Could not resolve "module"
File:
dist/$server_build/_worker.mjs:10:7
Code:
9 | import 'string-width';
> 10 | import 'module';
| ^
11 | import 'node:fs/promises';
12 | import 'node:url';
13 | import 'html-escaper';
どうやら、fs
とそれに関連するモジュールが利用できない(Cloudflare Workers / Pages Functionsの実行環境にない)ため、Markdownファイルを読み込めず、後続のrender
関数が未定義になっていた・・・様子です。
そのため、このケースではMarkdownをやめて、microCMSなどのHeadless CMSでコンテンツを管理するようにしました。
まとめ: Cloudflare Pages / WorkersではMarkdownを含むサイトのSSRは難しい
Markdownファイルを読み込む際に、fs
を利用します。コード内でimport
していなくとも、利用しているライブラリが内部的に使用している可能性も高く、「ファイルを読み込む処理を、サーバー側でやる場合はだいたいfs
が使われている」と思って良いかと思います。
ただしこのfs
モジュールは、2023/10時点でCloudflare Workers / Pages functionsの実行環境でサポートされていません。そのため、Markdownファイルを読み込むタイプのサイトについては、少なくともその部分だけは、静的にビルドした状態でCloudflareへデプロイするようにしましょう。