integrationsEdit this page

Vite

@lazarv/react-server is not just compatible with Vite, but it's also built on top of the Vite Environment API. This means that you can use all the features of Vite and many Vite plugins with @lazarv/react-server without any issues.

You can keep all the Vite configuration in the vite.config.js, vite.config.ts, vite.config.mjs or vite.config.cjs file. You can follow the Vite configuration guide to configure Vite.

You can use all the Vite plugins in your project. You can follow the Vite plugins guide to learn more about Vite plugins.

When using Vite plugins, expect three environments:

If you are migrating from Vite to @lazarv/react-server, you can follow this guide to migrate your project.

Getting started

Starting a new Vite + React app is easy:

pnpm create vite my-react-app --template react

Then you just need to change directory, install dependencies and start your app:

cd my-react-app
pnpm install
pnpm dev

It just works!

React Server Components

As we want to use RSCs, let's move everything from the index.html into src/main.jsx and instead of rendering App on the client-side, just use it as a component in this RSC layout:

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>
  );
}

Beware that you need to fix charSet as it has a different casing when used in JSX than in HTML!

For now, just add a "use client"; directive to App.jsx to make it work instantly as the App component includes a useState React hook.

Now let's uninstall react and react-dom as we will not need them, both were just React 18. Now we need to install @lazarv/react-server:

pnpm add @lazarv/react-server@latest 

Update npm scripts on how to start our app:

"scripts": {
  "dev": "react-server ./src/main.jsx",
  "build": "react-server build ./src/main.jsx",
  "lint": "eslint .",
  "start": "react-server start"
}

Let's start our app using pnpm dev --open!

Optimizing client components

In the current state of our app, the whole App component is a client component. This is not ideal, as only the counter part is interactive in it. We also attached some CSS to this client component which will only be loaded when the client component loads in the browser at runtime. This is causing a glitch for a blink of an eye at page load.

Let's create a new Counter component in a new file at src/Counter.jsx and move the counter button into this new component:

"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;

Now let's get back to the App component, remove the "use client"; directive, remove the App.css import and the code which was only part of the Counter component, but import it instead:

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;

The easiest resolution of the CSS issue is to import App.css in main.jsx:

import App from "./App.jsx";
import "./index.css";
import "./App.css";

export default function Html() {
  // we don't need to do any change here
}

Now both CSS files will be loaded instantly on page load and there will be no flickering. The counter button will still work as before as we refactored it to be a new client component. Every other part of the App component was static, which is best to be included in RSCs. You can also combine the 2 CSS files as there's no reason why we have two, just fix the CSS imports in the main.jsx after that.