Webpack to Vite
Migrate a Webpack-based project to Vite for faster development builds and HMR
You are an expert in migrating JavaScript/TypeScript projects from Webpack to Vite for dramatically faster dev server startup and hot module replacement. ## Key Points 1. **Audit Webpack Config** — catalog all loaders, plugins, aliases, and environment variable patterns. 2. **Install Vite** — add Vite and corresponding framework plugin alongside Webpack. 3. **Create vite.config.ts** — translate Webpack settings to Vite equivalents. 4. **Update Entry Points** — move to `index.html` as the entry point (Vite requires this). 5. **Fix Imports** — resolve any non-ESM import patterns, require() calls, and asset handling differences. 6. **Remove Webpack** — delete Webpack config, loaders, and dev dependencies once Vite is verified. - Run Webpack and Vite in parallel during migration so you can compare behavior before fully switching. - Replace `process.env.REACT_APP_*` references project-wide using a codemod or find-and-replace. - Use `vite-plugin-checker` for TypeScript type checking in dev (Vite skips type checking by default for speed). - For libraries that rely on Node.js built-ins (`path`, `fs`, `crypto`), install the browser polyfill packages and configure `resolve.alias`. - Test the production build (`vite build && vite preview`) early — dev and production use different pipelines in Vite. - **Missing `index.html` at root** — Vite requires `index.html` as the entry point at the project root, not generated by a plugin. ## Quick Example ```bash npm install --save-dev vite @vitejs/plugin-react npm uninstall webpack webpack-cli webpack-dev-server babel-loader css-loader style-loader html-webpack-plugin ``` ```typescript // Before (Webpack / CRA) const apiUrl = process.env.REACT_APP_API_URL; // After (Vite) const apiUrl = import.meta.env.VITE_API_URL; ```
skilldb get migration-patterns-skills/Webpack to ViteFull skill: 195 linesWebpack to Vite — Migration Patterns
You are an expert in migrating JavaScript/TypeScript projects from Webpack to Vite for dramatically faster dev server startup and hot module replacement.
Core Philosophy
Overview
Vite leverages native ES modules in development, eliminating the bundling step that makes Webpack dev servers slow on large projects. The migration involves replacing Webpack configuration with Vite equivalents, updating import patterns, and swapping plugins. Production builds use Rollup under the hood and produce optimized output comparable to Webpack.
Migration Strategy
- Audit Webpack Config — catalog all loaders, plugins, aliases, and environment variable patterns.
- Install Vite — add Vite and corresponding framework plugin alongside Webpack.
- Create vite.config.ts — translate Webpack settings to Vite equivalents.
- Update Entry Points — move to
index.htmlas the entry point (Vite requires this). - Fix Imports — resolve any non-ESM import patterns, require() calls, and asset handling differences.
- Remove Webpack — delete Webpack config, loaders, and dev dependencies once Vite is verified.
Step-by-Step Guide
1. Audit existing Webpack configuration
Common Webpack features that need Vite equivalents:
| Webpack | Vite Equivalent |
|---|---|
webpack-dev-server | vite (built-in) |
babel-loader | esbuild (built-in) |
ts-loader | esbuild (built-in) |
css-loader / style-loader | Built-in CSS support |
file-loader / url-loader | Built-in asset handling |
html-webpack-plugin | index.html at project root |
DefinePlugin | define in config or .env files |
resolve.alias | resolve.alias in config |
MiniCssExtractPlugin | Built-in CSS code splitting |
2. Install Vite and plugins
npm install --save-dev vite @vitejs/plugin-react
npm uninstall webpack webpack-cli webpack-dev-server babel-loader css-loader style-loader html-webpack-plugin
3. Move index.html to project root
Vite uses index.html as the entry point (not a Webpack-generated file):
<!-- index.html (project root) -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>My App</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
4. Create vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import path from 'path';
export default defineConfig({
plugins: [react()],
resolve: {
alias: {
// Translate Webpack aliases
'@': path.resolve(__dirname, 'src'),
'@components': path.resolve(__dirname, 'src/components'),
'@utils': path.resolve(__dirname, 'src/utils'),
},
},
// Environment variables: Vite uses VITE_ prefix instead of REACT_APP_
// Access via import.meta.env.VITE_API_URL instead of process.env.REACT_APP_API_URL
define: {
// Bridge for libraries that check process.env.NODE_ENV
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
},
server: {
port: 3000,
proxy: {
// Translate devServer.proxy from Webpack
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
},
},
},
build: {
outDir: 'dist',
sourcemap: true,
},
});
5. Update environment variable references
// Before (Webpack / CRA)
const apiUrl = process.env.REACT_APP_API_URL;
// After (Vite)
const apiUrl = import.meta.env.VITE_API_URL;
Rename .env variable prefixes:
# Before
REACT_APP_API_URL=https://api.example.com
# After
VITE_API_URL=https://api.example.com
6. Fix CommonJS require() calls
Vite dev mode uses native ESM, so require() is not available:
// Before
const logo = require('./assets/logo.png');
// After
import logo from './assets/logo.png';
For dynamic requires:
// Before
const icon = require(`./icons/${name}.svg`);
// After
const modules = import.meta.glob('./icons/*.svg', { eager: true });
const icon = modules[`./icons/${name}.svg`];
7. Update package.json scripts
{
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
}
}
Best Practices
- Run Webpack and Vite in parallel during migration so you can compare behavior before fully switching.
- Replace
process.env.REACT_APP_*references project-wide using a codemod or find-and-replace. - Use
vite-plugin-checkerfor TypeScript type checking in dev (Vite skips type checking by default for speed). - For libraries that rely on Node.js built-ins (
path,fs,crypto), install the browser polyfill packages and configureresolve.alias. - Test the production build (
vite build && vite preview) early — dev and production use different pipelines in Vite.
Common Pitfalls
- Missing
index.htmlat root — Vite requiresindex.htmlas the entry point at the project root, not generated by a plugin. process.envreferences — Vite does not injectprocess.envglobally. Every reference must be migrated toimport.meta.envor explicitly defined.- CommonJS dependencies — some npm packages ship only CommonJS. Vite pre-bundles these automatically via esbuild, but edge cases may require adding them to
optimizeDeps.include. - CSS Modules naming — Vite expects
.module.cssfile naming for CSS Modules. Files without.module.in the name are treated as global CSS. - Glob import differences — Webpack's
require.contextis replaced byimport.meta.glob, which has a different API. This requires manual code changes.
Anti-Patterns
Over-engineering for hypothetical scale. Building for millions of users when you have hundreds adds complexity without value. Solve today's problems first.
Ignoring the existing ecosystem. Reinventing functionality that mature libraries already provide well wastes time and introduces unnecessary risk.
Premature abstraction. Creating elaborate frameworks and utilities before you have enough concrete cases to know what the abstraction should look like produces the wrong abstraction.
Neglecting error handling at boundaries. Internal code can trust its inputs, but system boundaries (user input, APIs, file I/O) require defensive validation.
Skipping documentation for obvious code. What is obvious to you today will not be obvious to your colleague next month or to you next year.
Install this skill directly: skilldb add migration-patterns-skills
Related Skills
Class to Functional React
Convert React class components to functional components with hooks
Cra to Nextjs
Migrate a Create React App project to Next.js for server-side rendering and file-based routing
Javascript to Typescript
Migrate a JavaScript codebase to TypeScript incrementally with minimal disruption
Jest to Vitest
Migrate a test suite from Jest to Vitest for faster execution and native ESM support
Monolith to Microservices
Decompose a monolithic application into microservices using the strangler fig pattern
REST to GRAPHQL
Migrate a REST API to GraphQL while maintaining backward compatibility