Read More
🎉Celebrating 25 Years of Tech Excellence and Trust - Learn More
Quick Overview: Build tools play a crucial role in bundling and optimizing web assets, enabling developers to streamline their workflow and enhance performance. Understanding the differences between Webpack and ViteJS can help you make an informed decision when choosing the right tool for your web development projects. Let's dive into the key features and highlights of both tools in this blog – Webpack vs ViteJS.
In the Vite JS introduction series, we have covered the basics of Vite Js in the first article and Vite JS installation in the second article.
So, now moving forward, we have come up with a new and exciting topic in this last article of the series, which is all about how ViteJS works and the key difference between this framework and Webpack.
As we know, Vite JS is a new generation bundler. And this gives us the experience of entering a new era of web tooling.
Therefore, the recently emerged front-end framework, TezJS, uses Vite to deliver the best digital experience on any website.
So, now the question is – how does Vite work?
Here, I am going to compare how Vite works to the standard webpack config using webpack-dev-server, which all major Vue frameworks are using.
We will also go through how Vite no-bundling works, how it differs from webpack bundling, and why Vite JS could be the next best thing in frontend tooling for your project.
Vite JS is a front-end dev tool that supports React, Vue, and Preact. It's an innovative approach to understanding how build tools interact with a greenfield environment.
The core functionality of Vite is similar to webpack
+ webpack-dev-server
with some new improvements and functionalities on developer experience, such as:
Regardless of app size, you'll spend less time waiting for your app to start.
HMR (Hot module Reloading) is an instant, irrespective of the size of the app.
On-demand compilation.
Zero configuration for numerous pre-processors out of the box.
typescript / jsx powered by Esbuild (super quick).
Let me tell you, having a large JavaScript project today often entails working in slow development and production environment. It's easy to find elements for these slowdowns, whether it's due to the use of tools that don't fully exploit parallelization or memory optimization or repetitive activities that don't take advantage of caching.
Build Fast-track Frontend Solutions with The Power of Vite.js
Hire our experts
The primary aim of Vite is to integrate two tools for two different purposes to optimize the build for faster speed. Esbuild and Rollup are the two tools that make up Vite.
But why does it have two bundling tools?
Basically, there are two reasons for this:
Since our dependencies don't change frequently, it's not required to re-evaluate their module tree at each build. With an optimized tool like esbuild, we can construct our vendor's bundle. This bundler is extremely fast, allowing the server to start up quickly.
Unlike the dependencies, the modules in our source code are subject to many modifications. As a result, Vite employs an ESM-based solution that works natively in modern browsers.
Vite uses modern web browsers that allow native ESM modules to drastically reduce startup and rebuild times. Vite is essentially a web server in development, providing files to the browser as needed. These files may contain both source code modules and precompiled dependencies that are compiled with esbuild
during the first run.
This method of not bundling is a departure from contemporary web development practices. The recent past has relied significantly on bundling up dependencies for a good reason!
Allow me to show you how faster Vite is than Vue CLI, which uses a webpack. The larger your app is, the more noticeable the speed difference will be.
The primary difference between Vite and webpack is how code is served in development and which modules are supported.
Calm down! We are going to explain further – ViteJS vs webpack.
Supported Modules: ES Modules, CommonJS and AMD Modules
Dev Server: Bundled modules served via webpack-dev-server
using Express.js web server
Production Build: webpack
Supported Modules: ES Modules
Dev Server: Native-ES-Modules
, served via Vite using a Koa web server
Production Build: Rollup
If you are keen to understand how Vite JS works, it’s first necessary to know how webpack works. Understanding webpack, despite its popularity, might be frightening, so I'll try to keep it simple.
You can perform plenty of things using webpack, but at its core, it will:
Create a dependency tree by starting with an entry file: all the imports, exports, requires from your files or code.
Transform/compile modules: Consider transpiling JavaScript for outdated browsers or converting SCSS to CSS.
Sort, modify and concatenate code using algorithms.
Optimize.
Let me assume that you are using the Vue framework. So, you just have to follow some processes while starting your app in development.
Bundle all your code.
Start the webpack-dev-server – the Express.js web server, which will serve the bundled code.
Configure sockets to handle Hot Module Reloading.
As you may have noticed with your own apps, the larger they become, the longer you must wait before beginning to code.
As we can see, the Nuxt logo is almost burnt into my monitor at this point.
Bundling is faster in development since you don't have to deal with code, but it will become very slow as your app grows, especially on older machines.
Here, let’s create a default Vue 3 CLI project, which has an entry App.vue
file using the HelloWorld.vue
component.
Let’s understand how this component gets to my browser.
HelloWorld.vue component:
<template>
<div class="hello">
<h1>{{ msg }}</h1>
</div>
</template>
<script>
export default {
props: {
msg: String
}
}
</script>
<style scoped>
h1 {
color: green;
}
</style>
Well, here I get the following HTML from the Express.js server while starting the app and visiting localhost.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
</head>
<body>
<div id="app"></div>
<script type="text/javascript" src="/js/chunk-vendors.js"></script>
<script type="text/javascript" src="/js/app.js"></script>
</body>
</html>
Did you notice that there are two script files here: chunk-vendor.js and app.js.
If you see in inspect element, you’d observe many gibberish-looking codes. It enables to use of webpack-bundle-analyzer
to see how it works visually.
These third-party modules are derived from node_modules
. Moreover, it contains two main libraries: Vue and sock.js for HMR.
This code of an application contains assets, components, and many other things. Moreover, it splits into various modules for an SFC.
Here, my app contains two components: App.vue
and HelloWorld.vue
.
Here, there’s a HelloWorld component code in the app.js file. As you can see, every module in SFC is separated: the wrapper, CSS, template, JavaScript.
Here, the wrapper module defines and imports other models.
/***/ "./src/components/HelloWorld.vue":
/*!***************************************!*\
!*** ./src/components/HelloWorld.vue ***!
\***************************************/
/*! exports provided: default */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
Explore full-code here
Actually, every module is in the app.js file for my app. Webpack allows you to chunk bundles whatever you want, while Nuxt.js chunks route separately. However, the more chunks you have, the more requests you'll have and the more possible blocking scripts you'll have.
Want to Install Vite.js in Your System?
Read this Guide
Vite has no intention of becoming a new bundler. Rather, it's a pre-configured build environment for local development that uses the Rollup bundler.
Vite assumes that developers will be using the most recent browser versions, so it can securely rely on the most up-to-date JavaScript features right from the browser - no babel transpiling required!
When you first start Vite, pre-optimizations are performed on your node_modules
, and then Koa, a lightweight node web server, begins serving your app.
The dev server doesn't require any bundling or compilation; thus, it's lightning-fast (< 300ms).
When you launch your Vite app, the server will provide you with index.html. The browser will parse the Native-ES-Module code after reading the index.html
file.
<script type="module">import "/vite/client"</script>
<div id="app"></div>
<script type="module" src="/@app/index.js"></script>
The Native-ES-Module will parse your code and read the export
and import
lines. It'll convert those lines into HTTP requests and send them back to the server, where it'll read the export
and import
lines again and send new requests.
It will continue in this manner, recursively resolving your dependencies in a waterfall approach until everything is resolved.
Let’s understand how these requests work in the browser. After opening my app at localhost, the browser has fetched the following index.js file from the webserver:
import '/@theme/styles/main.scss?import';
import Layout from '/@theme/Layout.vue';
import NotFound from '/@theme/NotFound.vue';
import CardPost from '/@theme/components/CardPost.vue';
const theme = {
Layout,
NotFound,
enhanceApp({ app, }) {
app.component('CardPost', CardPost)
}
};
export default theme;
Let's take a closer look at the highlighted line that requests the CardPost SFC. That import will be converted by the browser into a request for http://localhost:3000/@theme/components/CardPost.vue
This is the CardPost.vue
component in my code.
<template>
<div class="card-post">
...
</div>
</template>
<script>
import posts from '../../posts'
export default {
props: {
postIndex: {
type: Number,
required: true,
}
},
computed: {
post () {
return posts[this.postIndex]
}
}
}
</script>
<style lang="scss" scoped>
.card-post {
...
}
</style>
Once the request is received by the web server, it will need to compile the CardPost.vue file to JS and send it back. Vite offers many optimizations options around the Vue compiling, which gets done quickly.
Let's see what is there to look for:
import posts from '/.vitepress/posts.ts'
const __script = {
props: {
postIndex: {
type: Number,
required: true,
}
},
computed: {
post() {
return posts[this.postIndex]
}
}
}
import "/@theme/components/CardPost.vue?type=style&index=0"
__script.__scopeId = "data-v-287b4794"
import {render as __render} from "/@theme/components/CardPost.vue?type=template"
__script.render = __render
__script.__hmrId = "/@theme/components/CardPost.vue"
typeof __VUE_HMR_RUNTIME__ !== 'undefined' && __VUE_HMR_RUNTIME__.createRecord(__script.__hmrId, __script)
__script.__file = "/home/harlan/sites/new.harlanzw.com/app/.vitepress/theme/components/CardPost.vue"
export default __script
Explore full-code here
The most important thing to notice here is how the SFC has been divided into multiple modules, each of which will require separate fetch requests. These imports haven't been packed into the SFC or any other monolith file.
Dependencies: /.vitepress/posts.ts
Template: /@theme/components/CardPost.vue?type=template
Stylesheet: /@theme/components/CardPost.vue?type=style&index=0
import {updateStyle} from "/vite/client"
const css = ".card-post[data-v-287b4794] {\n position: relative;\n}\n.card-post .prose[data-v-287b4794] {\n max-width: 100% !important;\n}\n.card-post__link[data-v-287b4794] {\n position: absolute;\n left: 0;\n top: 0;\n width: 100%;\n height: 100%;\n content: \" \";\n z-index: 1;\n}\n.card-post__content[data-v-287b4794] {\n background-color: white;\n z-index: 1;\n}\n.card-post__effect[data-v-287b4794] {\n z-index: -1;\n content: \" \";\n height: 30px;\n width: 100%;\n position: absolute;\n background-color: #059669;\n transition: 0.2s;\n opacity: 0;\n top: 30px;\n}\n.card-post:hover .card-post__effect[data-v-287b4794] {\n top: -5px;\n opacity: 1;\n transform: rotate(0.25deg);\n}"
updateStyle("287b4794-0", css)
export default css
You can see how the Hot Module Replacement works effectively.
Instead of reloading the entire component tree, only the style module needs to be reloaded when a module is modified if you choose styles within a component.
You may also imagine Vite slowing down as a result of the above.
Consider hundreds of HTTP requests that recursively rely on nested HTTP requests.
Fortunately, after the first load, there are optimizations to avoid this issue.
For modules that haven't changed, the server will return a 304 Unmodified HTTP Status code, indicating that they will use the browser's cached version of the file.
Since Vite only has to request the modules for the path you're on, it scales nicely for any app size.
Build future-ready front-end solutions that deliver a stunning user experience
Let's Begin
We can say that Vite offers many functionalities and features. Besides, it's amazing speed feature has already attracted developers for further development use. Vite significantly surmounts Webpack in terms of development server speed. Vite's development server generally starts up 2–3 times faster than Webpack; all credit goes to native ES Module imports.
Vite is not to be surpassed when it comes to style management. It manages CSS @imports
, preprocessors like SASS and LESS, CSS modules, and even the postprocessor PostCSS without the need for any plugins or settings.
More anecdotally, Vite knows how to handle your .env
file to control your environment variables.
But it was the SSR's relatively straightforward setup that truly blew us away.
After giving you a brief introduction to webpack vs ViteJS, you should not forget a simple rule.
Everything that a tool does for you mysteriously becomes more difficult to customize.
Vite's numerous possibilities to enhance the developer experience makes me a little concerned. I'm concerned that the Vite teams will find it difficult to keep all of this default configuration.
On the other hand, using Vite as a dev tool, TezJS has become a developer’s favorite due to its various features, functionalities, and unmatched developer experience.
In contrast to esbuild, which has the motto "I want to deliver a tool that does a few things but does them really well," we have a tool that offers a lot of promises.
On the other hand, Vite allows us to use and define plugins to extend its functionality without making them native to the main tool.
It's also worth noting that Vite is built on Rollup, a second-generation bundler. However, the Rollup configuration is really difficult to edit and maintain, so I hope you won't have to use it if you're tempted to try Vite on your applications.
On the brighter side, some tool like VuePress is an alternative option to Vitepress, which uses Vite as a bundler.
Should We Choose Vite or Webpack?Deciding between Vite and Webpack completely depends on your project requirements. Webpack is suitable for larger, complex projects, offering a mature ecosystem and extensive configurability. In contrast, Vite is suitable for medium-sized projects due to instant server startup and hot module replacement.While I haven't covered all of the complexities of ViteJS and webpack, I have attempted to demonstrate the essential differences, such as how bundling and no-bundling work.You can consider Vite a viable option. There is a lot of promise in the ecosystem right now; keep an eye on it. in the next 12 months, we could witness an explosion of Vite-related enterprises.If you are also planning to develop a Vue or React app using Vite JS, then consult with experienced front end development company like Radixweb.
Akash Kareliya is a proficient Application Evaluator known for his expertise in Python, Django, Flask, FastAPI, AWS Services, Docker, Kubernetes, and other emerging technologies. His ability to leverage cloud technologies and containerization frameworks allows him to build robust and efficient applications. Akash's dedication to continuous learning and his knack for finding innovative solutions makes him a valuable asset in driving technological advancements at Radixweb.
Ready to brush up on something new? We've got more to read right this way.