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
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.