Open5

remix spa, remix-on-hono 試してみた

RyosukeRyosuke

https://remix.run/docs/en/main/guides/spa-mode

https://github.com/yusukebe/hono-remix-adapter

https://x.com/yusukebe/status/1833098025553576218

Remix Setup

remix spaのテンプレートを利用してセットアップ

command
$ npx create-remix@latest --template remix-run/remix/templates/spa

Need to install the following packages:
create-remix@2.12.0
Ok to proceed? (y) y

 remix   v2.12.0 💿 Let's build a better website...

   dir   Where should we create your new project?
         remix-spa-on-hono

      ◼  Template: Using remix-run/remix/templates/spa...
      ✔  Template copied

   git   Initialize a new git repository?
         Yes

  deps   Install dependencies with npm?
         No
      ◼  Skipping install step. Remember to install dependencies after setup with npm install.

      ✔  Git initialized

  done   That's it!

         Enter your project directory using cd ./remix-spa-on-hono
         Check out README.md for development and deploy instructions.

         Join the community at https://rmx.as/discord
RyosukeRyosuke

hono, hono-remix-adapter install

command
pnpm add hono hono-remix-adapter

vite.config.tsに server adapterを追加

vite.config.ts
import { vitePlugin as remix } from "@remix-run/dev";
+ import serverAdapter from 'hono-remix-adapter/vite';
import { defineConfig } from "vite";
import tsconfigPaths from "vite-tsconfig-paths";

export default defineConfig({
  plugins: [
    remix({
      ssr: false,
      future: {
        v3_fetcherPersist: true,
        v3_relativeSplatPath: true,
        v3_throwAbortReason: true,
      },
    }),
    tsconfigPaths(),
+     serverAdapter({
+       entry: 'server/index.ts',
+     }),
  ],
});

RyosukeRyosuke

server/index.tsの作成

command
touch server/index.ts
server/index.ts
import { Hono } from 'hono';

const app = new Hono();

const routes = app.get('/api', (c) => {
  return c.json({ message: 'Hello World' });
});

export type AppType = typeof routes;

export default app;

RyosukeRyosuke

clientLoaderで取得

app/routes/_index.tsx
import type { MetaFunction } from '@remix-run/node';
import { useLoaderData } from '@remix-run/react';
+ import { hc } from 'hono/client';
+ import { AppType } from 'server';
import { Button } from '~/components/ui/button';

export const meta: MetaFunction = () => {
  return [
    { title: 'New Remix SPA' },
    { name: 'description', content: 'Welcome to Remix (SPA Mode)!' },
  ];
};

+ export const clientLoader = async () => {
+   const client = hc<AppType>('/');
+   const res = await client.api.$get();
+   return await res.json();
+ };

export default function Index() {
+ const { message } = useLoaderData<typeof clientLoader>();
  return (
    <div className="p-4 font-sans">
      <h1 className="text-3xl">Welcome to Remix (SPA Mode)</h1>
+     <h2>{message}</h2>
      <ul className="mt-4 list-disc space-y-2 pl-6">
        <li>
          <a
            className="text-blue-700 underline visited:text-purple-900"
            target="_blank"
            href="https://remix.run/guides/spa-mode"
            rel="noreferrer"
          >
            SPA Mode Guide
          </a>
        </li>
        <li>
          <a
            className="text-blue-700 underline visited:text-purple-900"
            target="_blank"
            href="https://remix.run/docs"
            rel="noreferrer"
          >
            Remix Docs
          </a>
        </li>
        <li>
          <Button>Button</Button>
        </li>
      </ul>
    </div>
  );
}


RyosukeRyosuke
command
pnpm dev

/api

上記では表示されるが、下記では/server以下がビルドされておらずapiがないのでエラーに・・・

command
pnpm build
pnpm preview

/api