Remix学習メモ
RemixでWebアプリを作りたいと思います。
Cloudflareにデプロイしようと思うので、Cloudflare用のテンプレートを使用してプロジェクトを作成します。パッケージマネージャーはBunを使います。VS Codeで任意のディレクトリを開いて、以下のコマンドを実行します。
bunx create-remix@latest --template remix-run/remix/templates/cloudflare
プロジェクト名、gitで管理するかどうか(Yesが推奨のようですが自分はNoを選択)、依存関係をインストールするかを聞かれます。一通り終わったら、指定したプロジェクト名のディレクトリに移動します。以下のコマンドを実行します。
bun run dev
通常、localhost:5173でWebアプリが起動します。デフォルトのページが表示されることを確認して、準備が整いました。
Cloudflareにデプロイできることを確認します。CLI(wranglerコマンド)でCloudflareの認証を行った後に、CLIからデプロイします。
bunx wrangler logout # 他のアカウントで既に認証済みの場合は実行しておくのが吉
bunx wrangler login
この後、ブラウザが起動してCloudflareへのログインが求められます。メールアドレスとパスワードを入力してログイン後、アクセス許否を聞かれるので、「許可」を選択します。
CLIからWebアプリのビルド、そしてデプロイをします。
bun run build
bun run deploy
デプロイの時に、プロジェクト名とブランチ名の入力を求められます。自分は、プロジェクト名はディレクトリ名と同一、ブランチ名は元から入力されていたproductionをそのまま使いました(ブランチ名は、GitHubと連動してデプロイする時に使用するもの?)
コマンドの実行が終わったら、公開先のURLが表示されるのでアクセスしてみます。ページが問題なく表示されたら完了です。反映まで少し時間がかかることもあるようです。
WebアプリはPWAにしたいので、Remix PWA
というライブラリを使用してプロジェクトをビルドしたいと思います。
Service Workerは利用せず、アプリのようにインストールできるようにします。
bun i --save-dev @remix-pwa/dev
# 2024-05-20時点で公式サイトのQuick Startに記載はないが必要
bun i --save-dev @remix-pwa/sw
bun i --save @remix-pwa/worker-runtime
PWAに必要なファイル群を生成します。
bunx remix-pwa sw
bunx remix-pwa manifest # WebManifestファイルを作成
この状態でビルドした後、デプロイを試みるとエラーが発生します。
✘ [ERROR] Could not resolve "stream"
../node_modules/stream-slice/index.js:3:24:
3 │ var Transform = require('stream').Transform;
╵ ~~~~~~~~
The package "stream" wasn't found on the file system but is built into node.
Add the "nodejs_compat" compatibility flag to your Pages project and make sure to prefix the module name with "node:" to enable Node.js compatibility.
✘ [ERROR] Build failed with 2 errors:
../node_modules/@remix-run/node/node_modules/cookie-signature/index.js:5:21: ERROR: Could not
resolve "crypto"
../node_modules/stream-slice/index.js:3:24: ERROR: Could not resolve "stream"
Cloudflareのテンプレートを使ってプロジェクトを作ると、自動生成されたmanifest[.webmanifest].ts
ファイルの参照が合わないので見直します。
import type { WebAppManifest } from '@remix-pwa/dev';
-import { json } from '@remix-run/node';
+import { json } from "@remix-run/cloudflare";
export const loader = () => {
return json(
{
short_name: 'PWA',
name: 'Remix PWA',
start_url: '/',
display: 'standalone',
background_color: '#d3d7dd',
theme_color: '#c34138',
} as WebAppManifest,
{
headers: {
'Cache-Control': 'public, max-age=600',
'Content-Type': 'application/manifest+json',
},
}
);
};
root.tsxにmanifestを登録するコードを追加します。
import {
Links,
Meta,
Outlet,
Scripts,
ScrollRestoration,
} from "@remix-run/react";
+import { ManifestLink } from "@remix-pwa/sw";
export function Layout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<Meta />
<Links />
+ <ManifestLink />
</head>
<body>
{children}
<ScrollRestoration />
<Scripts />
</body>
</html>
);
}
export default function App() {
return <Outlet />;
}
この後、bun run build
そしてbun run deploy
でデプロイして、スマホでページにアクセスした後にアプリを「ホームに追加」すると、PWAとして登録できます。
/interests
にアクセスした時に、興味があることをカテゴリ別に表示したいと思います。
import { json, type MetaFunction } from "@remix-run/cloudflare";
import { useLoaderData } from "@remix-run/react";
export const meta: MetaFunction = () => {
return [
{ title: "New Remix App | Interests" },
{
name: "description",
content: "My Interests",
},
];
};
export function loader() {
const interests = [
{
key: "勉強",
value: ["Java", "TypeScript", "Rust"],
},
{
key: "生活",
value: ["料理", "掃除", "選択"],
},
];
return json({ interests });
}
export default function Interests() {
const { interests } = useLoaderData<typeof loader>();
return (
<dl>
{interests.map((interest, i) => (
<>
<dt key={i}>{interest.key}</dt>
{interest.value.map((e, j) => (
<dd key={j}>{e}</dd>
))}
</>
))}
</dl>
);
}
loader関数内で表示したいデータを用意してreturn json({データ})
で返します。実際に表示するコンポーネントでは、useLoaderDataフックを用いて、loader関数で返した値を扱うことができます。