Skip to main content
rule

vite — Cursor rule: what it does, how to install

Guides code generation for Vite apps by enforcing lean configs, direct imports without barrel files, and native ES modules.

Install into Cursor · Manually: put the files in place All methods and platforms ↓
.cursor/rules/vite.mdc
Open on GitHub

What vite does

This rule targets **/*.{js,jsx} files to keep the Vite development server fast. It insists on keeping vite.config.js minimal, advising against unnecessary plugins and resolve aliases. Import statements must specify exact file extensions so the dev server avoids filesystem lookup overhead.

Client code must not use CommonJS syntax or process.env. The rule instructs the model to generate native ES modules and pull environment variables strictly through import.meta.env. It also promotes dynamic import() calls for heavy modules to trim the initial bundle.

Barrel files degrade cold start performance by forcing Vite to transform unused exports. The rule replaces central index.js re-exports with direct file references.

What it helps with

  • Remove unnecessary plugins and alias bloat from vite.config.js
  • Bypass barrel files to keep dev server transforms fast
  • Migrate client environment variable lookups to import.meta.env
  • Configure critical module pre-warming using server.warmup

Example prompts for the agent

  • Inspect vite.config.js and strip unnecessary settings
  • Refactor utility imports to point directly to source files instead of index.js
  • Convert this large component to load dynamically with lazy

How to install vite

Manually: put the files in place

.cursor/rules/vite.mdc

Frontmatter: description, globs, alwaysApply

Step by step, with commands for each platform: Cursor rules: .mdc files, four modes and what replaced .cursorrules

Questions about vite

How to install the vite rule in Cursor?

Add a new file at .cursor/rules/vite.mdc in your project repository and paste the rule text into it.

Which files activate this rule?

The rule targets files matching the **/*.{js,jsx} pattern, applying to JavaScript and JSX source code.

Why does this rule recommend avoiding barrel files?

Central export files make Vite process every re-exported module during page load. Direct module imports prevent processing unused code.

Source text

vite.mdc · CC0-1.0
---
description: This guide provides definitive best practices for developing high-performance, maintainable applications with Vite, focusing on optimal configuration, code structure, and testing.
globs: **/*.{js,jsx}
---
# 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
  },
});
```

© sanjeed5 · CC0-1.0 · sanjeed5/awesome-cursor-rules-mdc

Similar IDE rules

All IDE rules for Frontend and UI →

From the same set240

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor