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のインポートを修正してください。