vite
This guide provides definitive best practices for developing high-performance, maintainable applications with Vite, focusing on optimal configuration, code structure, and testing.
La skill
# 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`
```javascript
// 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' }),
// ... many more plugins
],
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`
```javascript
// vite.config.js
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
// Only add resolve.alias if absolutely needed for complex paths.
// Avoid resolve.extensions unless you have specific non-standard file types.
// Vite's defaults are usually sufficient.
});
```
### 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
```javascript
// src/components/MyComponent.jsx
import { util } from '../utils'; // Vite has to guess .js, .ts, .jsx etc.
```
✅ **GOOD** - Explicit import
```javascript
// src/components/MyComponent.jsx
import { util } from '../utils/index.js'; // Or .ts, .jsx, etc.
```
### 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`)
```javascript
// src/utils/index.js
export * from './color.js';
export * from './dom.js';
export * from './slash.js';
// src/app.js
import { slash } from './utils'; // Loads color.js, dom.js, and slash.js
```
✅ **GOOD** - Direct imports
```javascript
// src/app.js
import { slash } from './utils/slash.js'; // Only loads 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
```javascript
// main.js
const myModule = require('./my-module'); // Will fail in browser
```
✅ **GOOD** - Native ES Modules
```javascript
// main.js
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
```javascript
// app.js
console.log(process.env.VITE_API_URL); // `process` is not defined in browser
```
✅ **GOOD** - Using `import.meta.env`
```javascript
// app.js
console.log(import.meta.env.VITE_API_URL); // Correctly accesses Vite env vars
```
### 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
```javascript
// App.jsx
import LargeComponent from './LargeComponent'; // Always bundled
function App() {
return <LargeComponent />;
}
```
✅ **GOOD** - Dynamically importing
```javascript
// App.jsx (React example)
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
```javascript
// vite.config.js
import { defineConfig } from 'vite';
import someHeavyPlugin from 'some-heavy-plugin'; // No profiling done
export default defineConfig({
plugins: [someHeavyPlugin()],
});
```
✅ **GOOD** - Profiling plugins
```bash
# Run Vite with debug flags to identify slow 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.
```javascript
// No explicit warmup configured
```
✅ **GOOD** - Use `server.warmup` in `vite.config.js`
```javascript
// vite.config.js
import { defineConfig } from 'vite';
export default defineConfig({
server: {
warmup: {
clientFiles: ['./src/main.js', './src/App.jsx'],
// Or use patterns: ['**/*.vue', '**/*.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`
```javascript
// vite.config.js
// Default base: '/'
// Assets might break when deployed to a sub-path
```
✅ **GOOD** - Configure `base` for sub-path deployments
```javascript
// vite.config.js
import { defineConfig } from 'vite';
export default defineConfig({
base: '/my-app/', // For deploying to https://yourdomain.com/my-app/
// Or use './' for relative paths if the base is unknown at build time
// base: './',
});
```
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`
```javascript
// script.js
process.env.NODE_ENV = 'production';
await createServer(); // Might behave unexpectedly
```
✅ **GOOD** - Explicitly set `mode` or spawn child processes
```javascript
// script.js
import { createServer } from 'vite';
// Option 1: Explicitly set mode
const devServer = await createServer({ mode: 'development' });
await devServer.listen();
// Option 2: Spawn child processes for separate contexts
// (e.g., one for dev server, one for build)
```
## 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.
```json
// package.json
"scripts": {
"test": "jest" // Requires separate Babel/Webpack config
}
```
✅ **GOOD** - Integrate Vitest directly into `vite.config.ts`
```typescript
// vite.config.ts
/// <reference types="vitest/config" />
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
test: {
globals: true, // For global APIs like `describe`, `it`, `expect`
environment: 'jsdom', // Or 'node'
setupFiles: './src/setupTests.js', // Global setup for tests
},
});
```
Cómo instalarla
1. Open the tool and start a new conversation, project or template. 2. Paste the text below wherever the tool keeps standing instructions — usually called system prompt, instructions, or persona. 3. Save it so it applies to every run rather than a single message.