Vite
Vite は、JavaScript プロジェクトのための強力で高性能、かつ拡張可能な開発環境です。Remix のバンドル機能を向上させ、拡張するために、代替コンパイラとして Vite をサポートするようになりました。将来的には、Vite が Remix のデフォルトコンパイラになります。
クラシックRemixコンパイラ vs. Remix Vite
remix build
と remix dev
CLIコマンドでアクセスし、remix.config.js
で設定される既存のRemixコンパイラは、現在「クラシックRemixコンパイラ」と呼ばれています。
Remix Viteプラグインとremix vite:build
および remix vite:dev
CLIコマンドは、まとめて「Remix Vite」と呼ばれます。
特に断りのない限り、今後のドキュメントではRemix Viteの使用を前提とします。
はじめに
いくつかの異なるViteベースのテンプレートを用意して、すぐに始められるようにしました。
これらのテンプレートには、Remix Viteプラグインが設定されているvite.config.ts
ファイルが含まれています。
設定
Remix Viteプラグインは、プロジェクトルートにあるvite.config.ts
ファイルで設定されます。詳細については、Vite設定ドキュメントを参照してください。
vite-config: (This needs a URL to be added here. Replace with the actual link to the Vite config documentation.)
Cloudflare
Cloudflareを使い始めるには、cloudflare
テンプレートを使用できます。
Cloudflareアプリをローカルで実行するには、2つの方法があります。
Viteはより優れた開発エクスペリエンスを提供しますが、WranglerはNodeではなくCloudflareのworkerd
ランタイムでサーバーコードを実行することで、Cloudflare環境により近いエミュレーションを提供します。
template-cloudflare: template-cloudflareへのリンク cloudflare-workerd: cloudflare-workerdへのリンク
Cloudflare プロキシ
Vite で Cloudflare 環境をシミュレートするために、Wrangler は ローカル workerd
バインディングへの Node プロキシを提供します。
Remix の Cloudflare プロキシプラグインは、これらのプロキシを自動的に設定します。
その後、これらのプロキシは loader
関数または action
関数内の context.cloudflare
で利用できます。
これらのプロキシの詳細については、Cloudflare の getPlatformProxy
ドキュメント を参照してください。
バインディング
Cloudflare リソースのバインディングを構成するには:
- Vite または Wrangler を使用したローカル開発には、wrangler.toml を使用します。
- デプロイには、Cloudflare ダッシュボード を使用します。
wrangler.toml
ファイルを変更するたびに、バインディングを再生成するために wrangler types
を実行する必要があります。
その後、context.cloudflare.env
を介してバインディングにアクセスできます。
たとえば、MY_KV
としてバインドされたKV 名前空間 の場合:
ロードコンテキストの拡張
ロードコンテキストに追加のプロパティを追加したい場合は、共有モジュールからgetLoadContext
関数をエクスポートします。これにより、Vite、Wrangler、Cloudflare Pagesのロードコンテキストがすべて同じ方法で拡張されます。
getLoadContext
を両方のCloudflare Proxyプラグインとfunctions/[[path]].ts
のリクエストハンドラーに渡す必要があります。
まず、Viteを実行する際のロードコンテキストを拡張するために、Viteの設定でCloudflare ProxyプラグインにgetLoadContext
を渡します。
次に、Wranglerを実行する場合やCloudflare Pagesにデプロイする場合のロードコンテキストを拡張するために、functions/[[path]].ts
ファイルのリクエストハンドラーにgetLoadContext
を渡します。
クライアントコードとサーバーコードの分割
Viteは、クライアントコードとサーバーコードの混合使用を、従来のRemixコンパイラとは異なる方法で処理します。詳細については、クライアントコードとサーバーコードの分割に関するドキュメントを参照してください。
新しいビルド出力パス
Viteがpublic
ディレクトリを管理する方法と既存のRemixコンパイラとの間には、注目すべき違いがあります。Viteはpublic
ディレクトリからファイルをクライアントビルドディレクトリにコピーしますが、Remixコンパイラはpublic
ディレクトリをそのままにして、サブディレクトリ(public/build
)をクライアントビルドディレクトリとして使用していました。
Viteの動作に合わせてRemixプロジェクトのデフォルト構造を調整するため、ビルド出力パスが変更されました。個別のassetsBuildDirectory
とserverBuildDirectory
オプションに代わって、デフォルトで"build"
となる単一のbuildDirectory
オプションが追加されました。これは、デフォルトではサーバーがbuild/server
に、クライアントがbuild/client
にコンパイルされることを意味します。
これにより、次の設定のデフォルト値も変更されました。
- publicPathはViteの"base"オプションに置き換えられ、デフォルトは
"/"
ではなく"/"
になりました。 - serverBuildPathは
serverBuildFile
に置き換えられ、デフォルトは"index.js"
になりました。このファイルは、設定されたbuildDirectory
内のサーバーディレクトリに書き込まれます。
RemixがViteに移行する理由の1つは、Remixを採用する際に学習する内容を減らすためです。 つまり、使用したい追加のバンドル機能については、Remixのドキュメントではなく、ViteのドキュメントとViteプラグインコミュニティを参照する必要があります。
Viteには、既存のRemixコンパイラには組み込まれていない多くの機能とプラグインがあります。 このような機能を使用すると、既存のRemixコンパイラではアプリをコンパイルできなくなるため、Viteを今後専ら使用する予定の場合のみ使用してください。
移行
Viteの設定
👉 開発依存関係としてViteをインストールする
Remixは現在Viteプラグインなので、Viteに接続する必要があります。
👉 Remixアプリのルートにあるremix.config.js
をvite.config.ts
に置き換える
サポートされているRemixの設定オプション のサブセットは、プラグインに直接渡す必要があります。
HMR & HDR
Viteは、HMRのような開発機能のための堅牢なクライアントサイドランタイムを提供するため、<LiveReload />
コンポーネントは不要になりました。Remix Viteプラグインを開発で使用する場合、<Scripts />
コンポーネントは自動的にViteのクライアントサイドランタイムとその他の開発時のみのスクリプトを含みます。
👉 <LiveReload/>
を削除し、<Scripts />
を保持
TypeScript統合
Viteは様々な種類のファイルのインポートを処理しますが、既存のRemixコンパイラとは異なる方法で処理することがあります。そのため、非推奨になった@remix-run/dev
からの型ではなく、vite/client
からViteの型を参照しましょう。
vite/client
によって提供されるモジュール型は、@remix-run/dev
に暗黙的に含まれるモジュール型と互換性がないため、TypeScriptの設定でskipLibCheck
フラグを有効にする必要があります。Viteプラグインがデフォルトのコンパイラになれば、Remixはこのフラグを必要としなくなります。
👉 tsconfig.json
の更新
tsconfig.json
のtypes
フィールドを更新し、skipLibCheck
、module
、moduleResolution
が正しく設定されていることを確認してください。
👉 remix.env.d.ts
の更新/削除
remix.env.d.ts
内の以下の型宣言を削除してください。
remix.env.d.ts
が空になった場合は、削除してください。
Remix App Serverからの移行
開発環境でremix-serve
(または-c
フラグなしのremix dev
)を使用していた場合は、新しい最小限の開発サーバーに切り替える必要があります。
これはRemix Viteプラグインに組み込まれており、remix vite:dev
を実行すると動作します。
Remix Viteプラグインは、グローバルNodeポリフィルをインストールしないため、remix-serve
に依存していた場合は、自分でインストールする必要があります。これを行う最も簡単な方法は、Vite設定の先頭でinstallGlobals
を呼び出すことです。
Vite開発サーバーのデフォルトポートはremix-serve
とは異なるため、同じポートを維持したい場合は、Viteのserver.port
オプションで設定する必要があります。
また、サーバーにはbuild/server
、クライアントアセットにはbuild/client
という新しいビルド出力パスに更新する必要があります。
👉 dev
、build
、start
スクリプトを更新する
👉 Vite設定でグローバルNodeポリフィルをインストールする
👉 Vite開発サーバーポートを設定する(オプション)
カスタムサーバーの移行
開発でカスタムサーバーを使用していた場合、Viteのconnect
ミドルウェアを使用するようにカスタムサーバーを編集する必要があります。これにより、開発中にアセットリクエストと最初のレンダリングリクエストがViteに委任され、カスタムサーバーを使用する場合でも、Viteの優れた開発者エクスペリエンスを活用できます。
その後、開発中に仮想モジュール"virtual:remix/server-build"
をロードして、Viteベースのリクエストハンドラーを作成できます。
また、サーバーコードを更新して、新しいビルド出力パスを参照する必要があります。サーバービルドの場合はbuild/server
、クライアントアセットの場合はbuild/client
です。
たとえば、Expressを使用している場合、次のように実行できます。
👉 server.mjs
ファイルの更新
👉 build
、dev
、start
スクリプトの更新
必要に応じて、TypeScriptでカスタムサーバーを作成することもできます。その後、tsx
やtsm
などのツールを使用してカスタムサーバーを実行できます。
ただし、これを行うと、サーバーの初回起動時に顕著な遅延が発生する可能性があることに注意してください。
Cloudflare Functions の移行
Remix Vite プラグインは、フルスタックアプリケーション向けに特別に設計されたCloudflare Pagesのみを正式にサポートしています。Cloudflare Workers Sitesとは異なります。現在 Cloudflare Workers Sites を使用している場合は、Cloudflare Pages 移行ガイドを参照してください。
👉 Vite開発サーバーのミドルウェアを正しく上書きするには、remix
プラグインの前にcloudflareDevProxyVitePlugin
を追加してください!
Cloudflare アプリケーションでは、Remix 設定の server
フィールドを設定して、キャッチオール Cloudflare Function を生成している可能性があります。
Vite では、この間接参照は不要になりました。
代わりに、Express やその他のカスタムサーバーと同様に、Cloudflare 用のキャッチオールルートを直接作成できます。
👉 Remix のキャッチオールルートを作成する
👉 context.env
ではなく context.cloudflare.env
を使用して、バインディングと環境変数にアクセスする
開発中は主に Vite を使用しますが、Wrangler を使用してアプリのプレビューとデプロイを行うこともできます。
詳細については、このドキュメントのCloudflareセクションを参照してください。
👉 package.json
スクリプトを更新する
ビルド出力パスの参照を移行する
既存のRemixコンパイラのデフォルトオプションを使用する場合、サーバーはbuild
ディレクトリに、クライアントはpublic/build
ディレクトリにコンパイルされていました。Viteがpublic
ディレクトリを扱う方法と既存のRemixコンパイラとの違いにより、これらの出力パスが変更されました。
👉 ビルド出力パスの参照を更新する
- サーバーは、デフォルトで
build/server
ディレクトリにコンパイルされるようになりました。 - クライアントは、デフォルトで
build/client
ディレクトリにコンパイルされるようになりました。
例えば、Blues StackのDockerfileを更新するには、以下のようにします。
blues-stack: (Blues Stackへのリンクをここに挿入)
パスエイリアスの設定
Remixコンパイラは、パスエイリアスの解決にtsconfig.json
のpaths
オプションを利用します。Remixコミュニティでは一般的に、~
をapp
ディレクトリのエイリアスとして定義するために使用されます。
Viteはデフォルトではパスエイリアスを提供しません。この機能に依存していた場合、vite-tsconfig-pathsプラグインをインストールして、Remixコンパイラの動作に合わせて、tsconfig.json
からのパスエイリアスをViteで自動的に解決することができます。
👉 vite-tsconfig-paths
のインストール
👉 Vite設定へのvite-tsconfig-paths
の追加
@remix-run/css-bundle
の削除
Viteは、CSSの副作用インポート、PostCSS、CSS Modulesなどを含む、CSSバンドル機能を組み込みでサポートしています。Remix Viteプラグインは、バンドルされたCSSを関連するルートに自動的にアタッチします。
@remix-run/css-bundle
cssBundleHref
エクスポートは常にundefined
になるため、冗長です。
👉 @remix-run/css-bundle
をアンインストールする
👉 cssBundleHref
への参照を削除する
ルートのlinks
関数がcssBundleHref
を接続するためだけに使用されている場合、完全に削除できます。
links
で参照されている CSS インポートを修正する
links
関数で CSS を参照している場合、対応する CSS インポートを Vite の明示的な ?url
インポート構文を使用するように更新する必要があります。
👉 links
で使用されている CSS インポートに ?url
を追加する
.css?url
インポートには、Vite v5.1 以降が必要です。
css-bundling: (CSS バンドリングへのリンク) regular-css: (通常のCSS参照へのリンク) vite-url-imports: (Viteの?urlインポートへのリンク)
PostCSS を介して Tailwind を有効化
プロジェクトで Tailwind CSS を使用している場合、まず、Vite によって自動的に検出される PostCSS 設定ファイルがあることを確認する必要があります。
これは、Remix の tailwind
オプションが有効になっている場合、Remix コンパイラでは PostCSS 設定ファイルが不要だったためです。
👉 PostCSS 設定ファイルが存在しない場合は追加し、tailwindcss
プラグインを含めます
プロジェクトに既に PostCSS 設定ファイルがある場合は、tailwindcss
プラグインがまだ存在しない場合は追加する必要があります。
これは、Remix コンパイラが Remix の tailwind
設定オプション が有効になっている場合、このプラグインを自動的に含めていたためです。
👉 tailwindcss
プラグインが不足している場合は、PostCSS 設定ファイルに追加します
👉 Tailwind CSS のインポートを移行します
links
関数で Tailwind CSS ファイルを参照している場合、Tailwind CSS のインポート文を移行する必要があります。
tailwind: (Tailwind CSSへのリンク) postcss: (PostCSSへのリンク) tailwind-config-option: (Remixのtailwind設定オプションへのリンク) regular-css: (通常のCSS参照方法へのリンク) fix-up-css-imports-referenced-in-links: (CSSインポート文の修正方法へのリンク)
Vanilla Extract プラグインの追加
Vanilla Extract を使用している場合は、Viteプラグインを設定する必要があります。
👉 公式の Vanilla Extract Viteプラグイン をインストールします
👉 Vite設定にVanilla Extractプラグインを追加します
MDXプラグインの追加
MDXを使用している場合、ViteのプラグインAPIはRollupプラグインAPIの拡張であるため、公式のMDX Rollupプラグインを使用する必要があります。
👉 MDX Rollupプラグインのインストール
RemixプラグインはJavaScriptまたはTypeScriptファイルを処理することを想定しているため、MDXなどの他の言語からのトランスパイルは先に実行する必要があります。 この場合、MDXプラグインをRemixプラグインの前に配置する必要があります。
👉 Vite設定へのMDX Rollupプラグインの追加
mdx: https://mdxjs.com/ rollup: https://rollupjs.org/ mdx-rollup-plugin: https://github.com/mdx-js/mdx/tree/main/packages/rollup
MDXフロントマターサポートの追加
Remixコンパイラでは、MDXのフロントマターを定義できました。この機能を使用していた場合、Viteではremark-mdx-frontmatterを使用して実現できます。
👉 必要なRemarkフロントマタープラグインをインストールする
👉 RemarkフロントマタープラグインをMDX Rollupプラグインに渡す
Remixコンパイラでは、フロントマターのエクスポート名はattributes
でした。これは、フロントマタープラグインのデフォルトのエクスポート名frontmatter
とは異なります。フロントマターのエクスポート名を構成することもできますが、代わりにデフォルトのエクスポート名を使用するようにアプリコードを更新することをお勧めします。
👉 MDXファイル内でMDXのattributes
エクスポート名をfrontmatter
に名前変更する
👉 コンシューマー向けにMDXのattributes
エクスポート名をfrontmatter
に名前変更する
MDXファイルの型定義
👉 env.d.ts
に*.mdx
ファイルの型を追加する
Map MDX frontmatter to route exports
Remixコンパイラでは、frontmatterにheaders
、meta
、handle
ルートエクスポートを定義することができました。このRemix固有の機能は、remark-mdx-frontmatter
プラグインでは明らかにサポートされていません。この機能を使用していた場合は、frontmatterをルートエクスポートに手動でマッピングする必要があります。
👉 MDXルートのfrontmatterをルートエクスポートにマッピングする
MDXルートエクスポートを明示的にマッピングしているので、好きなfrontmatter構造を使用できます。
MDX ファイル名の使用方法の更新
Remix コンパイラは、すべての MDX ファイルから filename
エクスポートも提供していました。これは主に、MDX ルートのコレクションへのリンクを有効にするために設計されていました。この機能を使用していた場合は、glob インポート を介して Vite で実現できます。これにより、ファイル名とモジュールをマッピングする便利なデータ構造が得られます。これにより、各ファイルを個別にインポートする必要がなくなるため、MDX ファイルのリストを維持することがはるかに容易になります。
たとえば、posts
ディレクトリ内のすべての MDX ファイルをインポートするには、次のようにします。
これは、手動で次のように記述することと同じです。
必要に応じて、すべての MDX ファイルを事前にインポートすることもできます。
glob-imports: (glob インポートへのリンクをここに挿入してください)
デバッグ
NODE_OPTIONS
環境変数 を使用してデバッグセッションを開始できます。
その後、ブラウザからデバッガを接続できます。
たとえば、Chromeではchrome://inspect
を開くか、開発ツールのNodeJSアイコンをクリックしてデバッガを接続できます。
node-options: (This needs a URL to be added if available. For example: https://nodejs.org/api/cli.html#cli_node_options)
vite-plugin-inspect
vite-plugin-inspect
は、各Viteプラグインがどのようにコードを変換し、各プラグインにかかる時間を表示します。
パフォーマンス
Remixには、パフォーマンスプロファイリングのための--profile
フラグが含まれています。
--profile
を付けて実行すると、.cpuprofile
ファイルが生成されます。これは共有したり、speedscope.appにアップロードして分析したりできます。
開発中にプロファイリングを行うには、開発サーバーの実行中にp + enter
を押して、新しいプロファイリングセッションを開始するか、現在のセッションを停止することもできます。
開発サーバーの起動をプロファイリングする必要がある場合は、--profile
フラグを使用して起動時にプロファイリングセッションを初期化することもできます。
Vite パフォーマンスドキュメントでさらにヒントを確認することもできます!
vite-perf: (Vite パフォーマンスドキュメントへのリンクをここに挿入してください)
バンドル分析
バンドルを視覚化および分析するには、rollup-plugin-visualizer プラグインを使用できます。
その後、remix vite:build
を実行すると、各バンドルに stats.html
ファイルが生成されます。
build
├── client
│ ├── assets/
│ ├── favicon.ico
│ └── stats.html 👈
└── server
├── index.js
└── stats.html 👈
ブラウザで stats.html
を開いて、バンドルを分析してください。
トラブルシューティング
一般的なトラブルシューティングのヒントについては、デバッグ セクションとパフォーマンス セクションを確認してください。 また、GitHub の remix vite プラグインの既知の問題 を調べて、他に同じ問題を抱えている人がいないか確認してください。
issues-vite: (GitHub の issues ページへのリンクをここに挿入)
HMR
ホットアップデートを期待しているのに、ページ全体が再読み込みされる場合は、ホットモジュール置換に関する議論 を参照して、React Fast Refreshの制限と一般的な問題の回避策について詳しく学んでください。
ESM / CJS
ViteはESMとCJSの両方の依存関係をサポートしていますが、ESM/CJSの相互運用で問題が発生することがあります。 通常、これは依存関係がESMを適切にサポートするように構成されていないことが原因です。 そして、彼らを責めるわけではありません。ESMとCJSの両方を適切にサポートするのは非常に難しいです。
例のバグを修正する手順については、🎥 How to Fix CJS/ESM Bugs in Remixをご覧ください。
依存関係のいずれかが誤って構成されているかどうかを診断するには、publintまたはAre The Types Wrongを確認してください。
さらに、vite-plugin-cjs-interopプラグインを使用して、外部CJS依存関係のdefault
エクスポートに関する問題を解決できます。
最後に、Viteのssr.noExternal
オプションを使用して、サーバーバンドルにバンドルする依存関係を明示的に構成し、RemixコンパイラのserverDependenciesToBundle
(Remix Viteプラグインを使用)をエミュレートすることもできます。
modernizing-packages-to-esm: ここにリンクを挿入 how-fix-cjs-esm: ここにリンクを挿入 publint: ここにリンクを挿入 arethetypeswrong: ここにリンクを挿入 vite-plugin-cjs-interop: ここにリンクを挿入 ssr-no-external: ここにリンクを挿入 server-dependencies-to-bundle: ここにリンクを挿入
開発中のブラウザにおけるサーバーコードエラー
開発中にブラウザコンソールにサーバーコードを指し示すエラーが表示される場合、サーバー専用コードを明示的に分離する必要がある可能性があります。
例えば、次のようなものが見られる場合:
process
のようなサーバー専用グローバル変数を期待する依存関係を取り込んでいるモジュールを突き止め、別の.server
モジュール内、またはvite-env-only
を使用してコードを分離する必要があります。Viteは本番環境でコードをツリーシェイクするためにRollupを使用するため、これらのエラーは開発時のみ発生します。
その他のViteベースツール(例:Vitest、Storybook)でのプラグインの使用
Remix Viteプラグインは、アプリケーションの開発サーバーと本番ビルドでの使用のみを目的としています。VitestやStorybookなど、Viteの設定ファイルを使用する他のViteベースのツールもありますが、Remix Viteプラグインはこれらのツールでの使用を想定して設計されていません。現在、他のViteベースのツールで使用する場合には、プラグインを除外することをお勧めします。
Vitestの場合:
Storybookの場合:
あるいは、各ツールに個別のVite設定ファイルを使用することもできます。たとえば、Remixに特化したVite設定を使用するには:
Remix Viteプラグインを提供しない場合、設定でVite Plugin Reactを提供する必要がある場合もあります。たとえば、Vitestを使用する場合:
開発中にドキュメントが再マウントされるとスタイルが消える
Reactがドキュメント全体をレンダリングする場合(Remixが行うように)、head
要素に動的に要素が挿入されると問題が発生する可能性があります。ドキュメントが再マウントされると、既存のhead
要素は削除され、完全に新しい要素に置き換えられ、Viteが開発中に挿入したstyle
要素が削除されます。
これは既知のReactの問題であり、カナリアリリースチャンネルで修正されています。リスクを理解している場合は、アプリを特定のReactバージョンに固定し、パッケージオーバーライドを使用して、プロジェクト全体でこれが唯一のReactバージョンであることを確認できます。例:
Viteによって挿入されたスタイルに関するこの問題は、開発中のみ発生することに注意することが重要です。本番ビルドでは、静的CSSファイルが生成されるため、この問題は発生しません。
Remixでは、この問題は、ルートルートのデフォルトコンポーネントエクスポートとそのErrorBoundaryおよび/またはHydrateFallbackエクスポート間でレンダリングが切り替わる場合に発生する可能性があります。これは、新しいドキュメントレベルのコンポーネントがマウントされるためです。
ハイドレーションエラーが原因で発生することもあります。これは、Reactがページ全体を最初から再レンダリングするためです。ハイドレーションエラーはアプリコードによって発生する可能性がありますが、ドキュメントを操作するブラウザ拡張機能によって発生する可能性もあります。
これはViteにとって重要です。なぜなら、開発中はViteがCSSインポートをJSファイルに変換し、副作用としてドキュメントにスタイルを挿入するためです。Viteは、静的CSSファイルの遅延読み込みとHMRをサポートするためにこれを行います。
たとえば、アプリに次のCSSファイルがあるとします。
開発中は、このCSSファイルは、副作用としてインポートされると、次のJavaScriptコードに変換されます。
この変換は本番コードには適用されないため、このスタイルの問題は開発のみに影響します。
開発中のWranglerエラー
Cloudflare Pagesを使用している場合、wrangler pages dev
から次のエラーが発生することがあります。
これはWranglerの既知の問題です。
##謝辞
Viteは素晴らしいプロジェクトであり、Viteチームの尽力に感謝しています。 ViteチームのMatias Capeletto、Arnaud Barré、Bjorn Luには特に感謝しています。
RemixコミュニティはViteサポートの調査を迅速に進めてくれ、その貢献に感謝しています。
最後に、他のフレームワークがViteサポートを実装した方法からインスピレーションを受けました。