963 markdown files reformatted with the repository's pinned prettier so pnpm format:check covers the folded tree like every other repo file. The formatter's embedded-language pass also normalized code fences (TS semicolons, closed HTML tags in examples, lowercased CSS hex colors, one renumbered list that skipped an index). Alphanumeric token deltas vs the fold commit were audited file-by-file; all are formatter-equivalent markup normalizations plus the four sanitized skills.
4.1 KiB
4.1 KiB
name, description
| name | description |
|---|---|
| vite-build-ssr | Vite library mode and SSR configuration |
Build and SSR
Library Mode
Build a library for distribution:
// 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
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:
esandumd - Multiple entries:
esandcjs
Package.json Setup
{
"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
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:
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('<!--ssr-outlet-->', appHtml);
res.status(200).set({ 'Content-Type': 'text/html' }).end(html);
});
app.listen(5173);
SSR Build
{
"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:
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:
export default defineConfig({
ssr: {
noExternal: ['some-package'], // Bundle this dep
external: ['another-package'], // Externalize this dep
},
});
Conditional Logic
if (import.meta.env.SSR) {
// Server-only code (tree-shaken from client)
}
JavaScript API
createServer
import { createServer } from 'vite';
const server = await createServer({
configFile: false,
root: import.meta.dirname,
server: { port: 1337 },
});
await server.listen();
server.printUrls();
build
import { build } from 'vite';
await build({
root: './project',
build: { outDir: 'dist' },
});
preview
import { preview } from 'vite';
const previewServer = await preview({
preview: { port: 8080, open: true },
});
previewServer.printUrls();
resolveConfig
import { resolveConfig } from 'vite';
const config = await resolveConfig({}, 'build');
loadEnv
import { loadEnv } from 'vite';
const env = loadEnv('development', process.cwd(), '');
// Loads all env vars (empty prefix = no filtering)