Fresh との良くない初対面: @fedify/fresh 制作記 - 1
개발곰 @gaebalgom@hackers.pub
Fresh とは?
Deno Fresh というフレームワークを聞いたことがありますか?Deno チームが開発し推進しているフレームワークです。Fedify プロジェクトの一環として Create @fedify/fresh package for Fresh 2.0 integration という課題に取り組む中で初めて触れてみました。
レモンのロゴのように見た目は可愛いですが、実際に試してみると様々な問題に遭遇したので、それらをまとめてみました。
作業の背景
Create @fedify/fresh package for Fresh 2.0 integration 作業には主に2つの背景があります。
- Fresh が 2.X 系に移行する際に、既存のコードと互換性のない方向で開発された。
- Fedify のパッケージが整理される中で、
/x/配下にあったコードを削除し、統合のための別パッケージを作成する方向で整理された。
そのため、Fedify 2.0.0 から Fresh 2.0 をサポートする新しいパッケージを作ることに決めました。
統合用パッケージを作る際には、次のような順序で進めます:
examples配下に該当パッケージを使ったプロジェクトを作成して実行してみる- Federation 関連ファイルとミドルウェアを作成
- 正常に動作することを確認したら、別パッケージとして分離
- PR を出し、コードレビューを受け、ドキュメント化し、init コマンドに追加する...
現在は2まで進んでおり、別パッケージとして分離する作業を控えていますが、その前に遭遇した問題をまとめておくと良いと思い、整理することにしました。
遭遇した問題
(解決済み) example フォルダ配下のプロジェクトが正常に動作しません
deno run -Ar jsr:@fresh/init というコマンドで fresh はプロジェクトを作成します。いつものように fedify/examples 配下に fresh でプロジェクトを作成し、開発サーバーを実行(deno task dev)しようとしたところ、動作しませんでした。
error: Config file must be a member of the workspace.
Config: file:///home/dodok8/Development/fedify/examples/fresh/deno.json
Workspace: file:///home/dodok8/Development/fedify/
なるほど、ワークスペースの指定がされていないようです。ワークスペースに指定して追加しました。
...
╭ Warning
│
│ Ignored build scripts for packages:
│ npm:workerd@1.20251011.0
│ npm:sharp@0.33.5
│
│ Lifecycle scripts are only supported when using a `node_modules` directory.
│ Enable it in your deno config file:
│ "nodeModulesDir": "auto"
╰─
Task dev vite
error: Uncaught Error: UNHANDLED PROMISE REJECTION
at Process.<anonymous> (file:///home/dodok8/.cache/deno/npm/registry.npmjs.org/vite/7.1.12/bin/vite.js:12:11)
...
長いですが、中間にある警告が親切に強調されています。nodeModulesDir を auto に変更する必要があるとのことです。これがどのようなオプションなのか Deno 公式ドキュメント を見てみると、この値を "auto" に設定すると deno cache の代わりに node_modules からパッケージを取得するようになるとのことです。幸い fedify の他のビルド設定には影響はありませんでした。私のコンピュータの node_modules が大きくなっただけです。
フロントエンドが表示されない!(未解決)
とにかく期待を胸に deno task dev を実行してみました。Fresh と Preact との初めての出会いの瞬間でした。
しかし...

何も表示されません。おかしいですね?公式ドキュメントや別リポジトリで試した時はカウンターの例が表示されたのに。調べてみると、私と同じ症状の方が Deno の公式 Discord にいました。開発者によると、Preact の複数コピーがインストールされるとこのような現象が発生する可能性があるとのこと。Deno では 2.5.4 で修正されたバグだそうです。しかし私は 2.5.6 を使用しています。インストールキャッシュを削除しても、依然として何も表示されません。node_modules 関連で何かが混乱しているようですが、原因がわかりません。手動で node_modules から preact を削除しても、import エラーではなく空の画面が表示されるのを見ると、本当に不思議です。
もし私や Deno Discord でニックネームだけ知っている外国人の方を助けられる方がいらっしゃれば、方法を教えていただけると助かります。
Fedify ミドルウェアを作成するとサーバーが実行できない(解決済み)
ミドルウェア自体は型が変わった以外は大きく変わっていなかったので、以前のコードから多くを流用し、型と引数だけ Fresh 2.0 に合わせて変更しました。型エラーを解決した後に実行しました。正常に実行されます。では接続してみましょう。空の画面が迎えてくれるでしょう。

違いました。
幸いにも Claude Code との協力で解決できました。原理は次のとおりでした:
- Fresh 2.0 は開発サーバーとして vite を使用している
- このとき、ミドルウェアは Vite の SSR Module Runner が処理する。これは CJS をサポートしていない(代わりに HMR などの様々な機能が付いている)
- しかし Fedify には CJS 依存関係がある
- 爆発
幸いにも、開発サーバーで特定の依存関係とその依存関係を Vite を通さずに外部から実行するオプション がありました。HMR は動作しなくなりますが、@fedify/fresh を作成する際に @fedify/fedify をリアルタイムで修正する必要はないでしょう。
とにかく、これで開発サーバーは正常に動作するようになりました。

ミドルウェアも正常に動作していますね。
では、ビルド後に deno task start を試してみましょう。
error: Uncaught (in promise) Error: Cannot find module './llhttp/llhttp-wasm.js'
Require stack:
- /home/dodok8/Development/fedify/examples/fresh/_fresh/server/server-entry.mjs
at Module._resolveFilename (node:module:633:15)
at Module._load (node:module:496:27)
at Module.require (node:module:694:19)
at require (node:module:828:16)
at lazyllhttp (file:///home/dodok8/Development/fedify/examples/fresh/_fresh/server/server-entry.mjs:14671:67)
at file:///home/dodok8/Development/fedify/examples/fresh/_fresh/server/server-entry.mjs:14714:21
動きません!原因は同じく cjs でした。build.rollupOptions の external を調整したところ解決しました。
export default defineConfig({
plugins: [fresh()],
ssr: {
external: [
"@fedify/fedify",
],
},
build: {
rollupOptions: {
external: [
"@fedify/fedify",
],
},
},
});
最終的な vite.config.ts です。
これからパッケージ分離作業に入りますが、もしパッケージ分離作業中にまたバグに遭遇したり、パッケージ公開後に外部から使用しようとして失敗したりした場合は、制作記2として戻ってくるかもしれません。戻ってこなくて済むよう祈っていてください。