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へデプロイするようにしましょう。

    参考

    広告ここから
    広告ここまで
    Home
    Search
    Bookmark