/ Docs

Vite Guide

Run a Vite dev server in the browser with React, JSX/TSX support, npm packages, and hot module replacement.

Setup

The Vite dev server works like the Next.js server — VirtualFS for files, ViteDevServer for request processing, and ServerBridge for serving.

import { VirtualFS, getServerBridge } from 'almostnode';
import { ViteDevServer } from 'almostnode/vite';

const vfs = new VirtualFS();
const server = new ViteDevServer(vfs);
const bridge = getServerBridge();

await bridge.initServiceWorker();
bridge.registerServer(server, 5173);

React App

Create a basic React app with Vite. You need an index.html entry point and a root component:

// Entry HTML
vfs.writeFileSync('/index.html', `
  <!DOCTYPE html>
  <html>
    <body>
      <div id="root"></div>
      <script type="module" src="/src/main.tsx"></script>
    </body>
  </html>
`);

// Main entry point
vfs.writeFileSync('/src/main.tsx', `
  import React from 'react';
  import ReactDOM from 'react-dom/client';
  import App from './App';

  ReactDOM.createRoot(
    document.getElementById('root')
  ).render(<App />);
`);

// App component
vfs.writeFileSync('/src/App.tsx', `
  import { useState } from 'react';

  export default function App() {
    const [count, setCount] = useState(0);
    return (
      <div>
        <h1>Vite + React</h1>
        <button onClick={() => setCount(c => c + 1)}>
          Count: {count}
        </button>
      </div>
    );
  }
`);

npm Packages

Install npm packages and use them in your Vite app. The dev server resolves bare imports from node_modules/:

import { VirtualFS, PackageManager } from 'almostnode';

const vfs = new VirtualFS();
const npm = new PackageManager(vfs);

// Install React
await npm.install('react');
await npm.install('react-dom');

// Now your Vite app can import them
// import React from 'react';

Hot Module Replacement

The Vite dev server supports HMR with React Refresh. When you update a component in the VFS, only that component re-renders — state is preserved:

// Update a component — HMR kicks in
vfs.writeFileSync('/src/App.tsx', `
  import { useState } from 'react';

  export default function App() {
    const [count, setCount] = useState(0);
    return (
      <div>
        <h1>Updated App!</h1>
        <button onClick={() => setCount(c => c + 1)}>
          Clicked {count} times
        </button>
      </div>
    );
  }
`);
// The heading updates but the count state is preserved
Note

React Refresh preserves state for function components. If you change the component's structure significantly (like adding or removing hooks), a full remount may occur.