Open9

RemixをDeno Deployへデプロイしたい

lsadsfjlsadsfj

下記を実現できるテンプレートを用意したい

  • RemixでWebアプリを開発したい
  • Deno Deployで配信したい
  • Deno KVを使いたい
  • Deno Cronを使いたい
  • 良い開発体験のためにViteを使いたい
  • (できれば)Hono上で動かして、純粋なWeb APIはRemixとは別に開発できるとうれしい
lsadsfjlsadsfj

現状のイメージ

Node.jsで開発をする。Viteを動かすのはNode.jsからだけでよい。
Denoではあくまでビルド済のリクエストハンドラーをServeする。
→Node.js と Denoどちらでも動くというのは無理そう
ランタイムに依存する処理は、都度@remix-run/nodeや@remix-run/denoをimportしているため

下記リポジトリを参考にすればいけそう。
https://github.com/redabacha/remix-deno-vite-template

lsadsfjlsadsfj

とりあえずremix-deno-vite-templateを動かす。
結果、npm run devが動かない。

npm run build

動いた

npm run dev

下記のようなエラーが出る
vite.config.mts.timestampというファイルが生成されて画面がチラつく
アプリ自体も起動できない

vite.config.mts
error: Uncaught (in promise) ReferenceError: process is not defined
  ...process?.env.NODE_ENV === "production" && {
      ^

npm run start

ちゃんと動く

lsadsfjlsadsfj

npm run devの修正

ReferenceError: process is not defined

processはNode.jsのAPIなのでDenoで動くわけない
一方でDeno.env.getにするとnpm run buildが動かなくなる。
どちらでも動くようにしてやればいい

import { vitePlugin as remix } from "@remix-run/dev";
import { defineConfig } from "vite";
import tsconfigPaths from "vite-tsconfig-paths";

function getEnvironmentVariable(key) {
  return typeof process !== 'undefined' && process.env[key] 
         || typeof Deno !== 'undefined' && Deno.env.get(key)
         || undefined;
}

export default defineConfig({
  plugins: [remix(), tsconfigPaths()],
  ...(getEnvironmentVariable("NODE_ENV") === "production" && {
    define: { "process.env.NODE_ENV": JSON.stringify("production") },
    ssr: { noExternal: true },
  }),
});
lsadsfjlsadsfj

npm run devすると画面がチラつく

vite.config.mts.timestampが生成される → 再読み込み の繰り返しが起きてそう
https://gyazo.com/073970004c9c29ef76f0373061d222b0

npm run dev実行したときdeno run -A --watch ./server.dev.tsが実行される
--watchはいらないんじゃないかと思い削除したらチラつきが解除された。
削除してもHMRはちゃんと機能していることを確認した。
https://gyazo.com/9abd44cc01a969f0e1bc5a860174bb1e

lsadsfjlsadsfj

npm installできるようにする

そのままnpm installすると失敗する。(yarn.lockあるのでyarn installだと成功する)

原因

@remix-run/react@2.11.1 は react@^18.0.0 を要求している
しかし、package.jsonではreact@18.3.0-canary-c3048aab4-20240326を設定している

remix-deno-vite-templateによると下記の通りなので18.3を使う方針でいく

Additionally this template uses a React 18.3 canary as older React versions do not allow you to import renderToReadableStream from react-dom/server in certain environments, see this issue for more details. React 18.3 solves this by introducing the react-dom/server.edge export which includes renderToReadableStream.

対処

npm install --legacy-peer-deps

lsadsfjlsadsfj

Deno Deployしてみる

deployctl deploy --prod --project=remix-deno-sample-0809 --include=build,server.prod.ts ./server.prod.ts

とりあえず動いた

lsadsfjlsadsfj

残り
【OK】RemixでWebアプリを開発したい
【OK】Deno Deployで配信したい
Deno KVを使いたい
Deno Cronを使いたい
【OK】良い開発体験のためにViteを使いたい
(できれば)Hono上で動かして、純粋なWeb APIはRemixとは別に開発できるとうれしい

lsadsfjlsadsfj

@remix-run/denoを使ったらViteのHMRが動かなくなった

次のようなエラー

16:58:34 [vite] Error when evaluating SSR module /node_modules/@remix-run/deno/sessions/fileStorage.ts: failed to import "https://deno.land/std@0.128.0/path/mod.ts"
|- TypeError: [ERR_UNSUPPORTED_ESM_URL_SCHEME] Only file and data URLS are supported by the default ESM loader. Received protocol 'https'
    at async nodeImport (file:///home/lsadsfj/work/remix-deno-vite-template/node_modules/vite/dist/node/chunks/dep-NjL7WTE1.js:52928:15)
    at async ssrImport (file:///home/lsadsfj/work/remix-deno-vite-template/node_modules/vite/dist/node/chunks/dep-NjL7WTE1.js:52786:16)
    at async eval (/home/lsadsfj/work/remix-deno-vite-template/node_modules/@remix-run/deno/sessions/fileStorage.ts, <anonymous>:3:44)
    at async instantiateModule (file:///home/lsadsfj/work/remix-deno-vite-template/node_modules/vite/dist/node/chunks/dep-NjL7WTE1.js:52844:5)

@remix-run/denoでImportしているモジュールがURL形式のため失敗したと言っているぽい

Denoで実行しているのでURL Importできるはず。Vite側に問題があると思ったが対応されている
https://github.com/vitejs/vite/pull/15599

DenoでNode.jsのコードを実行しているため問題があるのではと思われる
Node.jsの動的にURL Importするコードを用意して、Denoで動くか検証してみれば問題の切り分けができそう。

ちょっとモチベーション下がってきたので、気が向いたら着手する