Documentation Index
Fetch the complete documentation index at: https://mintlify.com/TanStack/router/llms.txt
Use this file to discover all available pages before exploring further.
TanStack Start uses Vite’s environment API to build separate client and server bundles. This guide covers build-specific configuration options.
Build Architecture
TanStack Start creates two separate build environments:
- Client Environment: Browser-side code with optimized assets
- Server Environment: Node.js code for SSR and server functions
Each environment can be configured independently through Vite’s environments configuration.
Output Directories
By default, TanStack Start outputs builds to:
dist/
client/ # Client assets
server/ # Server bundle
You can customize output directories:
import { defineConfig } from 'vite'
import { tanstackStart } from '@tanstack/react-start/plugin/vite'
export default defineConfig({
build: {
outDir: 'build', // Base output directory (default: 'dist')
},
environments: {
client: {
build: {
outDir: 'build/public', // Custom client output
},
},
ssr: {
build: {
outDir: 'build/server', // Custom server output
},
},
},
plugins: [tanstackStart()],
})
Client Build Options
Configure the client environment build:
export default defineConfig({
environments: {
client: {
build: {
// Rollup options for client bundle
rollupOptions: {
input: {
main: 'virtual:tanstack-start-client-entry',
},
output: {
manualChunks: {
vendor: ['react', 'react-dom'],
},
},
},
// Minification
minify: 'esbuild', // 'esbuild' | 'terser' | false
// Source maps
sourcemap: true,
// Target browsers
target: 'es2020',
// CSS code splitting
cssCodeSplit: true,
// Asset inlining threshold
assetsInlineLimit: 4096,
},
},
},
plugins: [tanstackStart()],
})
Client Asset Base Path
Control where client assets are served from:
tanstackStart({
client: {
base: '/_build', // Default: '/_build'
},
})
// Or use Vite's base option
export default defineConfig({
base: '/my-app/', // Affects all assets
})
Server Build Options
Configure the server environment build:
export default defineConfig({
environments: {
ssr: {
build: {
ssr: true, // Required for server builds
// Rollup options for server bundle
rollupOptions: {
input: 'virtual:tanstack-start-server-entry',
output: {
format: 'esm', // or 'cjs'
},
},
// Don't minify server code (easier debugging)
minify: false,
// Source maps for server
sourcemap: true,
// Target Node.js version
target: 'node18',
// Don't copy public directory in server build
copyPublicDir: false,
},
},
},
plugins: [tanstackStart()],
})
Static NODE_ENV Replacement
Replace process.env.NODE_ENV at build time for dead code elimination:
tanstackStart({
server: {
build: {
staticNodeEnv: true, // default: true
},
},
})
When enabled, process.env.NODE_ENV is replaced with the actual value during build, allowing bundlers to eliminate dead code:
// Before build
if (process.env.NODE_ENV === 'development') {
console.log('Debug info')
}
// After production build
// (code is eliminated)
Dependency Optimization
Configure how dependencies are bundled:
export default defineConfig({
environments: {
client: {
optimizeDeps: {
// Dependencies to exclude from pre-bundling
exclude: ['@tanstack/react-start', '@tanstack/react-router'],
// Dependencies to include (CJS to ESM conversion)
include: ['react', 'react-dom', 'react-dom/client'],
// Force optimization on these
force: false,
},
},
ssr: {
optimizeDeps: {
// Disable server-side optimization by default
noDiscovery: true,
},
},
},
resolve: {
// Don't externalize these packages
noExternal: ['@tanstack/start**', '@tanstack/react-start**'],
},
plugins: [tanstackStart()],
})
Code Splitting
Control code splitting behavior:
export default defineConfig({
environments: {
client: {
build: {
rollupOptions: {
output: {
// Manual chunks for better caching
manualChunks: (id) => {
if (id.includes('node_modules')) {
if (id.includes('react') || id.includes('react-dom')) {
return 'vendor-react'
}
return 'vendor'
}
},
// Chunk file naming
chunkFileNames: 'assets/[name]-[hash].js',
entryFileNames: 'assets/[name]-[hash].js',
assetFileNames: 'assets/[name]-[hash][extname]',
},
},
},
},
},
plugins: [tanstackStart()],
})
Build Targets
Specify target environments:
export default defineConfig({
environments: {
client: {
build: {
target: [
'es2020',
'edge88',
'firefox78',
'chrome87',
'safari14',
],
},
},
ssr: {
build: {
target: 'node18', // Match your deployment Node.js version
},
},
},
plugins: [tanstackStart()],
})
Production Optimizations
Minification
export default defineConfig({
environments: {
client: {
build: {
minify: 'esbuild', // Fast, default
// Or use Terser for better compression
minify: 'terser',
terserOptions: {
compress: {
drop_console: true, // Remove console.log in production
},
},
},
},
},
plugins: [tanstackStart()],
})
Tree Shaking
Vite automatically tree-shakes unused code. Ensure your dependencies support ES modules:
// package.json
{
"type": "module"
}
Compression
Use a Vite plugin to compress assets:
import viteCompression from 'vite-plugin-compression'
export default defineConfig({
plugins: [
tanstackStart(),
viteCompression({
algorithm: 'gzip',
ext: '.gz',
}),
viteCompression({
algorithm: 'brotliCompress',
ext: '.br',
}),
],
})
Custom Build Process
The build process can be customized using Vite’s builder API:
export default defineConfig({
builder: {
sharedPlugins: true, // Share plugins between environments
async buildApp(builder) {
// Custom build logic
const client = builder.environments['client']
const server = builder.environments['ssr']
// Build in custom order
await builder.build(client)
await builder.build(server)
// Post-build processing
console.log('Build complete!')
},
},
plugins: [tanstackStart()],
})
Environment-Specific Configuration
Use different settings per environment:
export default defineConfig(({ mode }) => {
const isDev = mode === 'development'
return {
environments: {
client: {
build: {
sourcemap: isDev, // Source maps only in dev
minify: !isDev, // Minify only in production
},
},
},
plugins: [
tanstackStart({
server: {
build: {
staticNodeEnv: !isDev, // Replace NODE_ENV in production
},
},
}),
],
}
})
Build Analysis
Analyze your bundle size:
import { visualizer } from 'rollup-plugin-visualizer'
export default defineConfig({
plugins: [
tanstackStart(),
visualizer({
open: true,
gzipSize: true,
brotliSize: true,
}),
],
})
Run build and open the generated stats.html file.
Common Build Patterns
Library Mode
If building a library on top of TanStack Start:
export default defineConfig({
build: {
lib: {
entry: 'src/index.ts',
formats: ['es', 'cjs'],
},
rollupOptions: {
external: [
'react',
'react-dom',
'@tanstack/react-start',
'@tanstack/react-router',
],
},
},
})
Multi-Page Application
Build multiple entry points:
export default defineConfig({
environments: {
client: {
build: {
rollupOptions: {
input: {
main: 'src/client.tsx',
admin: 'src/admin/client.tsx',
},
},
},
},
},
plugins: [tanstackStart()],
})
Parallel Builds
Vite builds environments in parallel by default. Control concurrency:
export default defineConfig({
builder: {
async buildApp(builder) {
// Build environments in parallel
await Promise.all([
builder.build(builder.environments.client),
builder.build(builder.environments.ssr),
])
},
},
plugins: [tanstackStart()],
})
Cache Configuration
Configure Rollup cache:
export default defineConfig({
environments: {
client: {
build: {
rollupOptions: {
cache: true, // Enable Rollup cache
},
},
},
},
plugins: [tanstackStart()],
})
Troubleshooting
Debugging Build Issues
Enable verbose logging:
DEBUG=vite:* npm run build
CommonJS Issues
If you encounter CommonJS dependency issues:
export default defineConfig({
environments: {
ssr: {
build: {
commonjsOptions: {
include: [/node_modules/], // Convert CJS to ESM
transformMixedEsModules: true,
},
},
},
},
plugins: [tanstackStart()],
})
Next Steps
Server Options
Configure server-side rendering options
Deployment
Deploy your TanStack Start application