Why You Should Consider Switching From Webpack to Vite


Build
Webpack
Vite

As developers, we all value two things: performance and control over our code. This is why we often debate whether to use Webpack or Vite. Webpack, with over a decade of history, offers a highly customizable solution and has a strong community support. Vite is simpler to use, provides an almost zero-config solution in many cases, and is also highly performant.

I have experience working with both Webpack and Vite on various projects, and I’ve found that in many cases, Vite may be the best choice.

But first, let’s see how they compare.

Webpack

Configuration

You can find a simple Webpack configuration example generated by createapp.dev on GitHub. I used a bit of AI to create this configuration because, let’s face it, if you don’t use AI these days, are you even a developer (pun intended)? However, I’m also a bit lazy, so this example is simple but sufficient for our proof of concept.

Below are the package.json and webpack.config.js files that set up Webpack:

package.json
{
"name": "webpack-config",
"version": "1.0.0",
"description": "",
"main": "index.js",
"keywords": [],
"author": "",
"license": "ISC",
"scripts": {
"clean": "rm dist/bundle.js",
"build-dev": "webpack --mode development",
"build-prod": "webpack --mode production"
},
"dependencies": {
"tailwindcss": "^3.4.7"
},
"devDependencies": {
"@babel/core": "^7.25.2",
"@babel/preset-env": "^7.25.3",
"autoprefixer": "^10.4.20",
"babel-loader": "^9.1.3",
"css-loader": "^7.1.2",
"file-loader": "^6.2.0",
"html-webpack-plugin": "^5.6.0",
"mini-css-extract-plugin": "^2.9.0",
"postcss-loader": "^8.1.1",
"prettier": "^3.3.3",
"sass": "^1.77.8",
"sass-loader": "^16.0.0",
"style-loader": "^4.0.0",
"ts-loader": "^9.5.1",
"typescript": "^5.5.4",
"url-loader": "^4.1.1",
"webpack": "^5.93.0",
"webpack-cli": "^5.1.4"
}
}

As we can see, this setup requires 19 dependencies and 90 lines of code in the Webpack config file.

Size and Performance

Running npm run build-prod on my machine (a MacBook Pro with an Apple M1 Pro chip) produced these results:

Terminal window
assets by chunk 11.7 KiB (name: main)
asset main.css 11.1 KiB [emitted] (name: main)
asset main.ad88b4ed4a59346d5aa1.js 606 bytes [emitted] [immutable] [minimized] (name: main)
asset runtime.84fe7964e40459f6d228.js 912 bytes [emitted] [immutable] [minimized] (name: runtime)
asset index.html 296 bytes [emitted]
Entrypoint main 12.6 KiB = runtime.84fe7964e40459f6d228.js 912 bytes main.css 11.1 KiB main.ad88b4ed4a59346d5aa1.js 606 bytes
orphan modules 14.6 KiB (javascript) 1.83 KiB (runtime) [orphan] 14 modules
runtime modules 2.48 KiB 3 modules
cacheable modules 569 bytes (javascript) 11.1 KiB (css/mini-extract)
./src/index.ts 569 bytes [built] [code generated]
css ./node_modules/.pnpm/css-loader@7.1.2_webpack@5.93.0/node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[1].use[1]!./node_modules/.pnpm/postcss-loader@8.1.1_postcss@8.4.40_typescript@5.5.4_webpack@5.93.0/node_modules/postcss-loader/dist/cjs.js!./src/styles.css 10.1 KiB [built] [code generated]
css ./node_modules/.pnpm/css-loader@7.1.2_webpack@5.93.0/node_modules/css-loader/dist/cjs.js!./node_modules/.pnpm/sass-loader@16.0.0_sass@1.77.8_webpack@5.93.0/node_modules/sass-loader/dist/cjs.js!./src/styles.scss 1.02 KiB [built] [code generated]
webpack 5.93.0 compiled successfully in 1038 ms

Webpack compiles in about 1 second, producing a CSS bundle of 11 KiB and a JavaScript bundle of 606 bytes.

Vite

Configuration

Now, let’s compare this with a similar Vite configuration.

You can find a simple Vite configuration example on GitHub. Yes, it was also generated by AI. AI is everywhere these days, it may even steal our jobs one day. Has anyone said that yet?

Here are the package.json and vite.config.js files for Vite:

package.json
{
"name": "vite-config",
"version": "1.0.0",
"description": "",
"main": "index.js",
"keywords": [],
"author": "",
"license": "ISC",
"scripts": {
"dev": "vite",
"build": "vite build",
"serve": "vite preview"
},
"dependencies": {
"tailwindcss": "^3.4.7"
},
"devDependencies": {
"@vitejs/plugin-legacy": "^5.4.1",
"autoprefixer": "^10.4.20",
"postcss": "^8.4.40",
"sass": "^1.77.8",
"typescript": "^5.5.4",
"vite": "^5.3.5"
}
}

With Vite, we only need 7 dependencies and 18 lines of code in the configuration file. This represents a reduction of over half the dependencies and nearly 80% fewer lines of code compared to Webpack.

Size and Performance

Running npm run build produced these results:

Terminal window
5 modules transformed.
dist/index.html 0.39 kB gzip: 0.27 kB
dist/assets/index-B2adr4Ei.css 6.15 kB gzip: 1.88 kB
dist/assets/index-CnDDn-85.js 1.18 kB gzip: 0.55 kB
built in 303ms

Vite compiles in 0.3 seconds, generating a CSS bundle of 6.15 KiB and a JavaScript bundle of 1.18 KiB. This means that Vite is more than 3 times faster than Webpack and produces significantly smaller bundles.

Real-World Example

The above comparison is based on a simple proof of concept, but let’s consider a real-world scenario. At DEside, we migrated from Webpack to Vite in one of our WordPress projects. For confidentiality reasons, we can’t share the exact code, but we can discuss the results.

Webpack Size and Performance

Terminal window
assets by path images/ 345 KiB
assets by path images/*.svg 34.6 KiB 4 assets
assets by path images/*.jpeg 275 KiB 2 assets
asset images/214309fe3a452007cc0f.png 36 KiB [emitted] [immutable] [from: images/favicon-admin.png] (auxiliary name: wp-admin-css)
assets by path *.js 128 KiB
asset main.js 128 KiB [emitted] [minimized] (name: main)
asset wp-admin-css.js 0 bytes [emitted] [minimized] (name: wp-admin-css)
asset wp-admin-palette.js 0 bytes [emitted] [minimized] (name: wp-admin-palette)
asset wp-login-css.js 0 bytes [emitted] [minimized] (name: wp-login-css)
assets by path *.css 136 KiB
asset main.css 111 KiB [emitted] (name: main)
asset wp-admin-palette.css 12.6 KiB [emitted] (name: wp-admin-palette)
asset wp-login-css.css 7.21 KiB [emitted] (name: wp-login-css)
asset wp-admin-css.css 5.21 KiB [emitted] (name: wp-admin-css)
Entrypoint main 239 KiB = main.css 111 KiB main.js 128 KiB
Entrypoint wp-login-css 7.21 KiB (9.63 KiB) = wp-login-css.css 7.21 KiB wp-login-css.js 0 bytes 1 auxiliary asset
Entrypoint wp-admin-css 5.21 KiB (36 KiB) = wp-admin-css.css 5.21 KiB wp-admin-css.js 0 bytes 1 auxiliary asset
Entrypoint wp-admin-palette 12.6 KiB = wp-admin-palette.css 12.6 KiB wp-admin-palette.js 0 bytes
orphan modules 532 KiB (javascript) 345 KiB (asset) 5.07 KiB (runtime) [orphan] 155 modules
cacheable modules 136 KiB (css/mini-extract) 421 KiB (javascript)
modules by path ./src/scss/*.scss 130 KiB (css/mini-extract) 150 bytes (javascript)
css modules 130 KiB
css ./node_modules/.pnpm/css-loader@6.11.0_webpack@5.93.0/node_modules/css-loader/dist/cjs.js!./node_modules/.pnpm/postcss-loader@7.3.4_postcss@8.4.41_typescript@5.5.4_webpack@5.93.0/node_modules/postcss-loader/dist/cjs.js!./src/scss/wp-login.scss 7.28 KiB [built] [code generated]
css ./node_modules/.pnpm/css-loader@6.11.0_webpack@5.93.0/node_modules/css-loader/dist/cjs.js!./node_modules/.pnpm/postcss-loader@7.3.4_postcss@8.4.41_typescript@5.5.4_webpack@5.93.0/node_modules/postcss-loader/dist/cjs.js!./src/scss/wp-admin.scss 5.29 KiB [built] [code generated]
css ./node_modules/.pnpm/css-loader@6.11.0_webpack@5.93.0/node_modules/css-loader/dist/cjs.js!./node_modules/.pnpm/postcss-loader@7.3.4_postcss@8.4.41_typescript@5.5.4_webpack@5.93.0/node_modules/postcss-loader/dist/cjs.js!./src/scss/wp-admin-palette.scss 12.6 KiB [built] [code generated]
css ./node_modules/.pnpm/css-loader@6.11.0_webpack@5.93.0/node_modules/css-loader/dist/cjs.js!./node_modules/.pnpm/postcss-loader@7.3.4_postcss@8.4.41_typescript@5.5.4_webpack@5.93.0/node_modules/postcss-loader/dist/cjs.js!./src/scss/main.scss 105 KiB [built] [code generated]
javascript modules 150 bytes
./src/scss/wp-login.scss 50 bytes [built] [code generated]
./src/scss/wp-admin.scss 50 bytes [built] [code generated]
./src/scss/wp-admin-palette.scss 50 bytes [built] [code generated]
./src/ts/main.ts + 94 modules 421 KiB [built] [code generated]
css ./node_modules/.pnpm/css-loader@6.11.0_webpack@5.93.0/node_modules/css-loader/dist/cjs.js!./node_modules/.pnpm/postcss-loader@7.3.4_postcss@8.4.41_typescript@5.5.4_webpack@5.93.0/node_modules/postcss-loader/dist/cjs.js!./node_modules/.pnpm/swiper@9.4.1/node_modules/swiper/swiper.scss 6.34 KiB [built] [code generated]
webpack 5.93.0 compiled successfully in 4784 ms

Vite Size and Performance

Terminal window
108 modules transformed.
dist/images/B-Nb8i25.svg 5.27 kB gzip: 2.35 kB
dist/images/BsMD5M02.jpeg 9.86 kB
dist/images/VNsNsbZY.svg 13.18 kB gzip: 1.05 kB
dist/images/BTcOzB81.svg 13.21 kB gzip: 0.94 kB
dist/images/DFdp8c8q.png 36.90 kB
dist/images/Dp_QVDBh.jpeg 271.31 kB
dist/wp-admin-css.css 5.32 kB gzip: 1.27 kB
dist/wp-login-css.css 7.37 kB gzip: 1.36 kB
dist/wp-admin-palette.css 13.02 kB gzip: 2.42 kB
dist/main.css 115.67 kB gzip: 19.38 kB
dist/main.js 110.12 kB gzip: 31.59 kB
built in 1.80s

Comparison

Webpack compiles in 4.8 seconds, while Vite compiles in 1.8 seconds - making Vite 2.6 times faster than Webpack. Bundle sizes are quite similar: 349.73 kB for Vite versus 353.28 kB for Webpack, resulting in a slight reduction of 3.55 kB, meaning Vite is 1% more efficient in terms of asset size.

For CSS, Vite generates a total of 141.38 kB, while Webpack generates 139.26 kB. This means that Webpack’s CSS output is 2.12 kB lighter, which is about 1.5% smaller than Vite’s.

For JavaScript, Vite produces 110.12 kB, while Webpack produces 131.07 kB. This makes Webpack’s JS bundle 20.95 kB larger, so Vite is 19% more efficient in this regard.

WebpackViteImprovement
Compilation time4.8s1.8s 260%
Assets size353.28 kB349.73 kB 1%
CSS size141.38 kB139.26 kB 1.5%
JS size131.07 kB110.12 kB 19%

Conclusion

It’s clear that Vite simplifies the build process, requires less configuration, and is more performant in terms of both speed and bundle size. But does this mean we should abandon Webpack altogether and switch to Vite for every project?

The answer isn’t black and white. I don’t believe in a one-size-fits-all solutions, and this is no exception. Vite is an excellent choice for small to medium-sized projects, or where performance is critical and you don’t need complex configurations. It’s also ideal if you’re looking for a (almost) zero-config solution.

However, for large and complex projects, it may still be worth the time to configure Webpack properly. Webpack’s extensive customization options can be advantageous for managing large codebases and complicated build processes.

So, I guess the title was a little clickbait, huh?

Other articles