--- name: vite-build-ssr description: Vite library mode and SSR configuration --- # Build and SSR ## Library Mode Build a library for distribution: ```ts // vite.config.ts import { resolve } from 'node:path'; import { defineConfig } from 'vite'; export default defineConfig({ build: { lib: { entry: resolve(import.meta.dirname, 'lib/main.ts'), name: 'MyLib', fileName: 'my-lib', }, rolldownOptions: { external: ['vue', 'react'], output: { globals: { vue: 'Vue', react: 'React', }, }, }, }, }); ``` ### Multiple Entries ```ts build: { lib: { entry: { 'my-lib': resolve(import.meta.dirname, 'lib/main.ts'), secondary: resolve(import.meta.dirname, 'lib/secondary.ts'), }, name: 'MyLib', }, } ``` ### Output Formats - Single entry: `es` and `umd` - Multiple entries: `es` and `cjs` ### Package.json Setup ```json { "name": "my-lib", "type": "module", "files": ["dist"], "main": "./dist/my-lib.umd.cjs", "module": "./dist/my-lib.js", "exports": { ".": { "import": "./dist/my-lib.js", "require": "./dist/my-lib.umd.cjs" }, "./style.css": "./dist/my-lib.css" } } ``` ## Multi-Page App ```ts export default defineConfig({ build: { rolldownOptions: { input: { main: resolve(import.meta.dirname, 'index.html'), nested: resolve(import.meta.dirname, 'nested/index.html'), }, }, }, }); ``` ## SSR Development ### Middleware Mode Use Vite as middleware in a custom server: ```ts import express from 'express'; import { createServer as createViteServer } from 'vite'; const app = express(); const vite = await createViteServer({ server: { middlewareMode: true }, appType: 'custom', }); app.use(vite.middlewares); app.use('*all', async (req, res, next) => { const url = req.originalUrl; // 1. Read and transform index.html let template = await fs.readFile('index.html', 'utf-8'); template = await vite.transformIndexHtml(url, template); // 2. Load server entry const { render } = await vite.ssrLoadModule('/src/entry-server.ts'); // 3. Render app const appHtml = await render(url); // 4. Inject into template const html = template.replace('', appHtml); res.status(200).set({ 'Content-Type': 'text/html' }).end(html); }); app.listen(5173); ``` ### SSR Build ```json { "scripts": { "build:client": "vite build --outDir dist/client", "build:server": "vite build --outDir dist/server --ssr src/entry-server.ts" } } ``` The `--ssr` flag: - Externalizes dependencies by default - Outputs for Node.js consumption ### SSR Manifest Generate asset mapping for preload hints: ```bash vite build --outDir dist/client --ssrManifest ``` Creates `dist/client/.vite/ssr-manifest.json` mapping module IDs to chunks. ### SSR Externals Control which deps get bundled vs externalized: ```ts export default defineConfig({ ssr: { noExternal: ['some-package'], // Bundle this dep external: ['another-package'], // Externalize this dep }, }); ``` ### Conditional Logic ```ts if (import.meta.env.SSR) { // Server-only code (tree-shaken from client) } ``` ## JavaScript API ### createServer ```ts import { createServer } from 'vite'; const server = await createServer({ configFile: false, root: import.meta.dirname, server: { port: 1337 }, }); await server.listen(); server.printUrls(); ``` ### build ```ts import { build } from 'vite'; await build({ root: './project', build: { outDir: 'dist' }, }); ``` ### preview ```ts import { preview } from 'vite'; const previewServer = await preview({ preview: { port: 8080, open: true }, }); previewServer.printUrls(); ``` ### resolveConfig ```ts import { resolveConfig } from 'vite'; const config = await resolveConfig({}, 'build'); ``` ### loadEnv ```ts import { loadEnv } from 'vite'; const env = loadEnv('development', process.cwd(), ''); // Loads all env vars (empty prefix = no filtering) ```