| name | vite |
| description | [Applies to: **/*.{js,jsx}] This guide provides definitive best practices for developing high-performance, maintainable applications with Vite, focusing on optimal configuration, code structure, and testing. |
| source | cursor_mdc |
vite Best Practices
Vite is the modern standard for frontend tooling. Adhere to these principles to leverage its full potential, ensuring blazing-fast development and optimized production builds.
1. Code Organization and Structure
Keep vite.config.js Minimal
Vite's philosophy is a lean core. Avoid over-configuring. Only add plugins or options when absolutely necessary.
❌ BAD - Overly complex vite.config.js
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import legacy from '@vitejs/plugin-legacy';
import { visualizer } from 'rollup-plugin-visualizer';
import { VitePWA } from 'vite-plugin-pwa';
export default defineConfig({
plugins: [
react(),
legacy({ targets: ['defaults', 'not IE 11'] }),
visualizer({ filename: './dist/stats.html' }),
VitePWA({ registerType: 'autoUpdate' }),
],
resolve: {
alias: {
'@': '/src',
'~': '/node_modules',
},
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'],
},
build: {
target: 'es2015',
minify: 'terser',
sourcemap: true,
rollupOptions: {
output: {
manualChunks: {
vendor: ['react', 'react-dom'],
},
},
},
},
server: {
port: 3000,
open: true,
proxy: {
'/api': 'http://localhost:8080',
},
},
});
✅ GOOD - Lean and focused vite.config.js
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
});
Use Explicit File Extensions
Relying on resolve.extensions for implicit imports forces Vite to perform multiple filesystem checks, slowing down resolution. Be explicit.
❌ BAD - Implicit import
import { util } from '../utils';
✅ GOOD - Explicit import
import { util } from '../utils/index.js';
Avoid Barrel Files
Barrel files (e.g., index.js re-exporting many modules) force Vite to fetch and transform all re-exported files, even if only one API is used. This hurts initial page load performance.
❌ BAD - Barrel file (src/utils/index.js)
export * from './color.js';
export * from './dom.js';
export * from './slash.js';
import { slash } from './utils';
✅ GOOD - Direct imports
import { slash } from './utils/slash.js';
2. Common Patterns and Anti-patterns
Embrace Native ES Modules
Vite is built on native ES Modules. Always write your client-side code using import/export syntax.
❌ BAD - CommonJS in client-side code
const myModule = require('./my-module');
✅ GOOD - Native ES Modules
import myModule from './my-module.js';
Use import.meta.env for Environment Variables
Vite injects environment variables via import.meta.env. This is the correct way to access them in client-side code. process.env is for Node.js environments.
❌ BAD - Using process.env in client code
console.log(process.env.VITE_API_URL);
✅ GOOD - Using import.meta.env
console.log(import.meta.env.VITE_API_URL);
Optimize with Dynamic Imports
For large components or libraries, use dynamic imports to load them only when needed, reducing initial bundle size and improving load times.
❌ BAD - Eagerly loading large component
import LargeComponent from './LargeComponent';
function App() {
return <LargeComponent />;
}
✅ GOOD - Dynamically importing
import { lazy, Suspense } from 'react';
const LargeComponent = lazy(() => import('./LargeComponent'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<LargeComponent />
</Suspense>
);
}
3. Performance Considerations
Audit Custom Plugins
Community plugins can introduce performance bottlenecks. Profile them using Vite's debug flags.
❌ BAD - Blindly adding plugins
import { defineConfig } from 'vite';
import someHeavyPlugin from 'some-heavy-plugin';
export default defineConfig({
plugins: [someHeavyPlugin()],
});
✅ GOOD - Profiling plugins
vite --debug plugin-transform
Use vite-plugin-inspect to visualize the transform pipeline.
Optimize Browser Setup
Browser extensions and disabled cache settings can severely impact dev server performance.
❌ BAD - Developing with "Disable Cache" enabled in dev tools.
// Browser Dev Tools -> Network tab -> "Disable Cache" checked
✅ GOOD - Use a clean browser profile or incognito mode.
Ensure "Disable Cache" is unchecked in dev tools.
Warm Up Critical Files
For complex applications, pre-warming frequently used files can prevent request waterfalls.
❌ BAD - Relying solely on on-demand transformation for critical paths.
✅ GOOD - Use server.warmup in vite.config.js
import { defineConfig } from 'vite';
export default defineConfig({
server: {
warmup: {
clientFiles: ['./src/main.js', './src/App.jsx'],
},
},
});
4. Common Pitfalls and Gotchas
Incorrect Base Path for Deployment
When deploying to a sub-path (e.g., yourdomain.com/my-app/), ensure base is correctly configured.
❌ BAD - Hardcoding absolute paths or missing base
✅ GOOD - Configure base for sub-path deployments
import { defineConfig } from 'vite';
export default defineConfig({
base: '/my-app/',
});
Access the base path in your code via import.meta.env.BASE_URL.
Mismanaging NODE_ENV with API Usage
When using Vite's JS API (createServer, build) in the same Node.js process, ensure process.env.NODE_ENV or the mode config option is consistent to prevent conflicts.
❌ BAD - Conflicting NODE_ENV
process.env.NODE_ENV = 'production';
await createServer();
✅ GOOD - Explicitly set mode or spawn child processes
import { createServer } from 'vite';
const devServer = await createServer({ mode: 'development' });
await devServer.listen();
5. Testing Approaches
Standardize on Vitest
Vitest is the official testing framework for Vite projects, offering seamless integration with Vite's configuration and plugin ecosystem.
❌ BAD - Using a separate test runner (e.g., Jest) that requires its own complex configuration.
"scripts": {
"test": "jest"
}
✅ GOOD - Integrate Vitest directly into vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
test: {
globals: true,
environment: 'jsdom',
setupFiles: './src/setupTests.js',
},
});