Migrating from Webpack5 to Vite
LAST UPDATED AT: Mar 20, 2025
Recently, while experimenting with Vite on a side project, I was genuinely impressed by its lightning-fast dev server and near-instant HMR. So, I decided to migrate an existing Webpack project to Vite — and here's how it went.
In this blog, I will show on how to migrate from Webpack (v5) to Vite .
Results:
Tool | Cold Start Time | HMR Speed | Bundle Time |
---|---|---|---|
Webpack | ~550 ms | ~60 ms | ~1000 ms (1second) |
Vite | ~100 ms | ~40 ms | ~383 ms |
⚠️ Disclaimer: These values are average estimates based on current project setup. Actual times will vary depending on your machine, dependencies, and project size.
This is the repo ↗️ which I will be using to demo.
The branch main
contains the original code which uses Webpack.
The branch vite-migration
contains the Vite migrated code.
🔄 Migration Steps at a Glance
- Install vite and required plugins
- Create a
vite.config.js
- Move and update index.html
- Package.json changes
- Remove Webpack/Babel specific config files
Install vite and required plugins
Vite can act as both a bundler and dev server , so we replace webpack
, webpack-cli
and webpack-dev-server
all with a single package.
@vitejs/plugin-react
is a plugin to bind react with vite.It internally takes care of babel configuration.
npm i --save-dev vite @vitejs/plugin-react
Create a vite.config.js
Now, in the project root create a file named vite.config.js
.
import { defineConfig, transformWithEsbuild } from 'vite' import react from '@vitejs/plugin-react' export default defineConfig({ plugins:[ { name: 'load+transform-js-files-as-jsx', async transform(code, id) { if (!id.match(/src\/.*\.js$/)) { return null; } // Use the exposed transform from vite, instead of directly // transforming with esbuild return transformWithEsbuild(code, id, { loader: 'jsx', jsx: 'automatic', }); }, }, react()], optimizeDeps: { esbuildOptions: { loader: { '.js': 'jsx', }, }, }, })
Here, we have to add a two plugins: first is our custom plugin to understand a js file containing jsx code to be understood by esbuild ↗️ (which is used by Vite).
Note: If your codebase has proper .jsx extension then you can omit this plugin.
Second, is the react plugin . We can also pass babel related configuration as a parameter to this , but the default one is sufficient.
Also, we have to add the optimizeDeps.esbuildOptions
to allow the esbuild to use the jsx loader (for dev builds).
Move and update index.html
Move the index.html from "src" folder to project root (if you have) and update the file path to index.js
<script type="module" src="/src/index.js"></script>
and remove any .css file ref from .html file
Package.json changes
Add type:module
and update the script commands to use vite
"serve": "vite", "build": "vite build" "preview": "vite preview" <-- locally preview production build
Remove Webpack/Babel specific config files
Atlast, you can remove the webpack.config.js
and .babelrc
files
🚀 Final Thoughts
The migration from Webpack to Vite was straightforward. For most React projects, Vite offers faster builds and simpler setup. Webpack still works well for complex setups, but Vite is a solid choice for most use cases today.
Feel free to check out the migration diff in this GitHub repo ↗️ and try it out on your own project!
chao 👋