Fastly Compute で Remix アプリをホスト
Remix は、人気の高い最先端の JavaScript ベースのフルスタック Web フレームワークです。Remix を使用することで、開発者は Web 標準をサポートしながらユーザーインターフェイスの構築に専念し、レスポンシブでパワフルなユーザーエクスペリエンスを提供できます。最近公開された remix-compute-js ライブラリを使用して、Fastly の Compute プラットフォームで Remix アプリケーションをホストすることが可能になりました。これにより、オリジンサーバーなしでも Fastly のグローバルエッジネットワークで配信することができます。
Compute で JavaScript のサポートが強化されるのに伴い、より多くのツールとの統合が可能になり、さまざまな既存の JavaScript ライブラリやフレームワークを使用して作業できるようになりました。昨年このブログでは、静的Webサイトを完全にエッジで配信する方法と Next.js サイトをエッジで実行する方法についてご説明しました。今回は、Remix の実行をサポートするためのこれまでの取り組みをご紹介したいと思います。
Remix は広く使用されている JavaScript ベースのフルスタック Web フレームワークで、Web 標準のサポートと先進的な機能が特徴です。この斬新なフレームワークは、Fetch API インターフェイスを完全にサポートし、同じくこれをサポートする Compute との相性が良いのです。特に Remix は、独自のランタイムを使用できるよう設計されており、さまざまなサーバーランタイムやサーバーアダプタ―を使用できることを前提として構築されているので、多様なプラットフォームで実行できます。
そのため、私たちは Remix ランタイム、エントリーポイントアダプター、プロジェクトテンプレートを構築し、Remix を Compute で実行できるよう、完全にサポートすることができました。
これにより、Compute アプリケーションで Remix のパワーを完全に活かし、Remix による Web 標準の優れたサポートと先進的な機能を活用することが可能になりました。つまり、Remix の便利な機能を利用しながら、自由に Remix プロジェクトを構築できるのです。Remix の優れた機能として、規則ベースのルーティングの定義、React Router のパワーの活用、MDX のレンダリング、API Routes の構築が挙げられます。
そしてもちろん、バックエンドへのフェッチコールや、ポリフィルを使用して NPM でサポートされる互換性のあるモジュールと統合するといった、Compute のメリットも活用できます。
Remix プロジェクトを作成する
Fastly Compute のテンプレートは GitHub (https://github.com/fastly/remix-compute-js/tree/main/packages/remix-template) でアクセスできます。つまり、ローカルに Node.js をインストールするだけで、公式のcreate-remix
コマンドラインツールを使用して Remix プロジェクトを作成できます。
npx create-remix@latest ./my-app --template https://github.com/fastly/remix-compute-js/tree/main/packages/remix-template
その際、JavaScript と TypeScript のどちらを使用してプロジェクトを作成したいか聞かれます (個人的に私は TypeScript の方が好みです)。残りのプロセスは自動的に行われます。
./my-app
ディレクトリに切り替えると、プロジェクトの構造体がビルトされているのを確認できます。作成されたのは Remix プロジェクトですが、同時に JavaScript ベースの Compute アプリケーションでもあります。このアプリケーションは、アプリケーションの詳細を Fastly に提供する fastly.toml
ファイルと、src/index.js
のエントリーポイントを備えています。
このアプリケーションは、Fastly の開発サーバーで動作するよう事前に設定されています。このサーバーは、Fastly CLI をインストールするだけで利用できます。以下のコマンドを実行します。
npm run dev
Web ブラウザで http://127.0.0.1:7676 を開くと、Remix テンプレートアプリケーションが表示されます。
このファイルは app/routes/index.jsx
(TypeScript を使用している場合は .tsx
) ファイルからビルトされています。このファイルに変更を加えると、アプリケーションがリビルドされ、ブラウザウィンドウが自動的にリフレッシュされます。
ここでは実際、2つのプロセスが実行されています。Remix のコンパイラと Fastly の開発サーバーの2つで、両方ともウォッチ モードで実行されています。app/
ディレクトリのファイルに変更を加える度に、Remix コンパイラによってリビルドがトリガーされ、出力ファイルが build/
と public/build/
のディレクトリで更新されます。この場合、あるいは public/
ディレクトリにあるファイルを更新する度に、Fastly の開発サーバーもリビルドされます。これで、Compute で実行される Remix アプリケーションのために自動的にリフレッシュする開発環境が整いました。
サーバーアダプタ―
Remix のパワフルなアーキテクチャでは、2つのコンポーネントが分けられています。Remix アプリケーション自体 (Remix フレームワーク内で記述されたコード) と、Remix とサーバープラットフォーム間のインターフェイスの2つです。これにより、サーバープラットフォームが Remix にインターフェイスで接続される方法に柔軟性が生まれます。これは、Fastly のようなプラットフォームプロバイダーにとって、とてもありがたいです。
最もシンプルな使用方法 (プロジェクトテンプレートでも実装されています) は、Fastly がサーバーアダプタ―パッケージからエクスポートする createEventHandler
関数を使用することです。ここでは、(このテンプレートを使用した際に自動的にインストールされた) Static Publisher によって生成された ./statics
ファイルから staticAssets
がインポートされることが想定されています。
import { createEventHandler } from "@fastly/remix-server-adapter";
import { staticAssets } from "./statics";
addEventListener("fetch", createEventHandler({ staticAssets }));
また、Remix と一緒に使用する ServerBuild
モジュールや、静的アセットのリクエストを処理する方法に対してよりきめ細かいコントロールを必要とするお客様向けに、以下のように下位レベルの関数を作成しました。
import { createRequestHandler, handleAsset } from "@fastly/remix-server-adapter";
import { staticAssets } from "./statics";
const build = staticAssets.getAsset("/build/index.js").module;
const requestHandler = createRequestHandler({build});
addEventListener("fetch", (event) => event.respondWith(handleRequest(event)));
async function handleRequest(event) {
let response = await handleAsset(event, staticAssets);
if (!response) {
response = requestHandler(event);
}
return response;
}
本番に移行する
公開する準備ができたら、プロダクションビルドを作成し、サイトにアクセスして正常に動作していることを確認します。
開発サーバーの使用を停止し、以下のコマンドを実行します。
npm run build
npm start
これにより、アプリケーションのプロダクションビルドが生成され、最適化された JavaScript ファイルが作成されます。次にブラウザをリフレッシュし、開発サーバーで実行されていたアプリケーションのプロダクションビルドバージョンを確認します (プロダクションビルドでは、ライブの再読み込みはサポートされていません)。
サイトのプロダクションビルドが正常に見えることを確認できたら、Fastly にデプロイできます。まだアカウントをお持ちでない場合は、アカウントを作成し、新しいアカウントの認証情報を使用して Fastly CLI を設定します。これで、アプリケーションを Fastly アカウントにデプロイできます。
npm run build
npm run deploy
ここで、新しい Fastly サービスを作成するよう求められます。既存のサービスを使用したい場合は、上記のコマンドを実行する前に、fastly.toml
で、その service_id
値をサービス ID に設定します。
Compute で Remix を使用するのに必要なステップは本当にこれだけです。npm run dev
を使用して通常どおり開発します。npm run build
と npm start
でテストを実施し、本番環境に移行する準備が整ったら、npm run build
と npm run deploy
でエッジにデプロイします。
既存の Remix アプリケーションを Compute に移行する
すでに構築済みの Remix アプリケーションがありますか? その場合、Node.js バックエンドでホストされていますか? Remix アプリケーションを Compute 上で動くように適応させるのは、(ファイルシステムとやり取りをするなど、概念上 Fastly で不可能な動作をしようとしない限り) 大抵の場合それほど難しくはありません。
最も簡単な方法は、上記のテンプレートを使用して、空の Remix プロジェクトを作成することです。これにより、すべての依存関係がインストールされ、プロセスの一環としてサーバーアダプタ―も作成されます。そして、元のプロジェクトが参照するすべての依存関係パッケージを新しいプロジェクトにインストールします。次に、既存プロジェクトのファイルを新しいプロジェクトに移します。Remix では、アプリケーションのファイルは app/ and public/ に保存されています。一般的に、これらのディレクトリにあるファイルのほとんどは、新しいプロジェクトに簡単にコピーできますが、以下の点に留意する必要があります。
1. ソースファイルの中には、@remix-run/node
、@remix-run/cloudflare
、@remix-run/deno
など、Remix のランタイムパッケージを参照するものがあります。これらのリファレンスを @fastly/remix-server-runtime
に変更してください。
例えば以下の場合は、
import { json } from "@remix-run/node";
次のように変更します。
import { json } from "@fastly/remix-server-runtime";
2. app/
ディレクトリの entry.client.tsx
、entry.server.tsx
、root.tsx
については、一般的に新しいプロジェクトにあるものから始めることをお勧めします。ソースプロジェクトにある、これらのファイルを確認して変更箇所を探し、必要に応じて同様の変更を新しいプロジェクトでも実施します。
3. /public/build/
はスキップします。これは、ビルドステップで生成されるディレクトリです。
4. プロジェクトで使用されている依存関係によっては、Compute で実行するためにポリフィルを追加する必要がある場合があります。
以上です!前のセクションと同様に、アプリケーションをビルドしてエッジにデプロイします。
Compute で Remix アプリケーションをホストする
Remix と Compute の統合がサポートされ、オリジンサーバーを使用する必要なくエッジで完全に Remix アプリケーションをホストできるようになりました。Remix のパワフルなアーキテクチャのメリットを活かしながら、Compute にデプロイして Fastly ネットワーク上の何千ものサーバー上でアプリケーションを実行できます。
Fastly では、お客様が使い慣れたツールを使用してより多くのコードを開発し、エッジで実行することを可能にするツールを提供できるよう日々、取り組んでいます。お客様がどのように Fastly のツールを活用しているか、私たちはとても興味があります。 皆さまが構築しているものについて、Twitter にてぜひお聞かせください!