Vite
@lazarv/react-server
はViteと互換性があるだけでなく、Vite Environment API の上に構築されています。つまり@lazarv/react-server
でViteのすべての機能と多くのViteプラグインを問題なく使用することができます。
Viteのすべての設定はvite.config.js
、vite.config.ts
、vite.config.mjs
、またはvite.config.cjs
ファイルに保存することができます。Viteの設定方法については、公式のVite設定ガイドを参照してください。
すべてのViteプラグインを使用することができます。Viteプラグインの詳細については、Viteプラグインガイドを参照してください。
Viteプラグインを使用する場合、以下の3つの環境を想定しています:
rsc
- プラグインが React Server Components (RSCペイロード) で使用される場合ssr
- プラグインがサーバーサイドレンダリング(HTML出力)で使用される場合client
- プラグインがクライアントコンポーネントで使用される場合
Viteから@lazarv/react-server
に移行する場合、このガイドに従ってプロジェクトを移行することができます。
始める
簡単に新しいVite + Reactのプロジェクトを始められます:
pnpm create vite my-react-app --template react
ディレクトリを移動し、依存関係をインストールすればアプリを起動することができます:
cd my-react-app
pnpm install
pnpm dev
これだけで動作します!
React Server Components
RSCsを使用したい場合は、まずindex.html
内のすべてをsrc/main.jsx
に移動します。そして、クライアントサイドでApp
をレンダリングする代わりに、このRSCレイアウトでコンポーネントとして使用します:
import App from "./App.jsx";
import "./index.css";
export default function Html() {
return (
<html lang="en">
<head>
<meta charSet="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React</title>
</head>
<body>
<div id="root">
<App />
</div>
</body>
</html>
);
}
charSet
はJSXで使われるときとHTMLで使われるときで大文字と小文字が異なるので修正する必要があります!
とりあえず、App.jsx
に"use client";
を追加するだけで、AppコンポーネントがuseState
Reactフックを含んでいるのですぐに動作するようになります。
ここでreact
とreact-dom
をアンインストールしましょう。これらはReact 18だったのでもう必要ありません。代わりに@lazarv/react-server
をインストールする必要があります:
pnpm add @lazarv/react-server@latest
アプリの起動に関するnpmスクリプトを更新します:
"scripts": {
"dev": "react-server ./src/main.jsx",
"build": "react-server build ./src/main.jsx",
"lint": "eslint .",
"start": "react-server start"
}
pnpm dev --open
を使ってアプリを起動してみましょう!
クライアントコンポーネントの最適化
現在の状態ではApp
コンポーネント全体がクライアントコンポーネントになっていますが、これは理想的ではありません。インタラクティブなのはカウンター部分だけだからです。またこのクライアントコンポーネントにCSSをアタッチしており、ブラウザ実行時のみ適用されます。これによりページ読み込み時に一瞬のちらつきが発生してしまいます。
新しいCounter
コンポーネントをsrc/Counter.jsx
に作成し、カウンターボタンを新しいコンポーネントに移動しましょう:
"use client";
import { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount((count) => count + 1)}>
count is {count}
</button>
);
}
export default Counter;
App
コンポーネントから"use client";
を削除し、App.css
のインポートとCounter
コンポーネントの一部だったコードを削除します。その代わりにCounter
コンポーネントをインポートしましょう:
import reactLogo from "./assets/react.svg";
import viteLogo from "/vite.svg";
import Counter from "./Counter.jsx";
function App() {
return (
<>
<div>
<a href="https://vitejs.dev" target="_blank">
<img src={viteLogo} className="logo" alt="Vite logo" />
</a>
<a href="https://react.dev" target="_blank">
<img src={reactLogo} className="logo react" alt="React logo" />
</a>
</div>
<h1>Vite + React</h1>
<div className="card">
<Counter />
<p>
Edit <code>src/App.jsx</code> and save to test HMR
</p>
</div>
<p className="read-the-docs">
Click on the Vite and React logos to learn more
</p>
</>
);
}
export default App;
CSSの問題を解決する最も簡単な方法は、main.jsx
でApp.css
をインポートすることです:
import App from "./App.jsx";
import "./index.css";
import "./App.css";
export default function Html() {
// we don't need to do any change here
}
これで両方のCSSファイルはページ読み込み時にすぐに読み込まれ、ちらつきがなくなります。カウンターボタンは以前と同様に動作し、クライアントコンポーネントとして新しくリファクタリングしたためです。App
コンポーネントの他の部分は静的であり、RSCsに含めるのが最適です。また2つのCSSファイルを1つに統合することもできます。2つある理由はないので、main.jsx
でCSSのインポートを修正してください。