This article was last updated on July 30, 2024, to add sections for Custom Vite Configurations and Performance Optimization.
Introduction
We'll talk about the history of vite and the importance of using Vite, we'll also deep dive into developer experience with Vite and why you want to start using Vite.
In this section, we'll be talking about ES modules and the evolution of bundling Javascript code. In the ever-evolving landscape of web development, speed and efficiency are crucial factors that can make or break a project. As developers, we constantly seek tools that can streamline our workflow and deliver optimal performance.
The problem of bundling has been as old as developers finding a way to organize their code in a modular fashion. ES modules which became a solution to the problem, allowed developers to have a better developer experience by allowing code to be grouped by modules and allowing module variables to be accessible to other modules if need be.
Using ES module specifications or webpack, which allowed ESM for unsupported browsers, soon began to pose a problem. As developers build large-scale applications, there are thousands of modules these large applications depend on, making the building process extremely slow and a pain for developers.
It is this very problem that has brought about the creation of Vite!. Vite.js was created by Evan You the creator of Vue.js, a very popular Javascript framework. Vite was created as a way to both simplify and speed up the frontend development build cycle.
Steps we'll cover:
- What is Vite.js?
- Key Features of Vite
- Vite vs Webpack
- Migrating from Webpack to Vite
- Using Vite.js in practice
- Custom Vite Configurations
- Performance Optimization in Vite
What is Vite.js?
Javascript build tools can be a pain to developers, especially when all you want to do is focus on development. Developers want a simplified way of building and developing their applications and Vite.js is one of the popular tools that solves this problem. We'll be talking about Vite.js and its key features in this tutorial.
We'll talk about how Vite was built fundamentally and how it addresses performance challenges in web development. Fundamentally, at the core, Vite.js does two main things, and does it really well:
- Serve code locally during development
- Bundle all your frontend assets (HTML, CSS, JS etc.) for production.
Vite leverages native ES modules in the browser. This will help to load your code instantly, no matter how large your module dependencies are or how large the application code has become. Vite also uses Hot Module Replacement (HMR). HMR accounts for the fast and effective part of Vite, as it watches for state changes in the application and adds and/or removes modules while the application is running without prompting a full reload of the application. What this means for the developers is you can see the changes you make to your code instantly right in your browser as you're coding. Cool right?!.
How does Vite.js Address Performance Challenges?
In this section, let's take a look at how Vite addresses some of the performance challenges in front-end web development.
- Native ES Modules Support: Vite.js fully embraces native ES modules. Native ES modules are supported in modern browsers. Instead of bundling modules during development, Vite.js leverages the native capabilities of browsers to directly load ES modules as separate files. This adoption eliminates the need for bundling and enables faster startup times and better cacheability. It also ensures that the browser results in improved overall performance.
- Blazing-Fast Build Process: Vite.js leverages the "esbuild" bundler, known for its exceptional speed. During the production build process, Vite.js uses "esbuild" to generate optimized and minified code bundles. The "esbuild" rapid bundling capabilities significantly reduces build times compared to traditional bundlers. This leads to improved and faster deployment and developer productivity.
- Code Splitting and Lazy Loading: Vite.js supports code splitting and lazy loading out of the box. By breaking down the codebase into smaller chunks, Vite.js enables more efficient loading and execution of JavaScript. Only the necessary modules are loaded when required, reducing initial load times and improving performance. Lazy loading allows developers to load specific parts of an application on-demand, further optimizing the loading process and improving the user experience.
Key Features of Vite
In this section, we'll be talking about the key features Vite has to offer and why you should get started using it. Vite.js, being a modern front-end development build tool, offers several key features that differentiate it from traditional bundlers. Here are some of the features:
- Lightning-Fast Development Server: Vite.js introduces a highly optimized development server that leverages native ES module imports in modern browsers. It employs an on-demand compilation approach, allowing for near-instantaneous hot module replacement (HMR) and rapid page reloads. This significantly speeds up the development workflow, providing faster feedback loops and enhancing developer productivity.
- Native ES Modules Support: Vite.js fully embraces native ES modules, which are natively supported in modern browsers. During development, Vite.js leverages the browser's ability to load ES modules as separate files without the need for bundling. This approach eliminates the overhead of bundling during development, resulting in faster startup times and better cacheability. It also allows the browser to parallelize module loading, leading to improved overall performance.
- Blazing-Fast Production Builds: Vite.js utilizes the "esbuild" bundler, known for its exceptional speed, during the production build process. "esbuild" generates optimized and minified code bundles, resulting in significantly reduced build times compared to traditional bundlers. This swift bundling process enhances developer efficiency and allows for faster deployment cycles.
- Zero Configuration: Vite.js follows a zero-configuration philosophy, providing a seamless out-of-the-box experience. By minimizing the need for manual configuration, developers can quickly set up new projects without spending time on complex configuration setups. However, Vite.js also offers a flexible configuration file (vite.config.js) for advanced customization when needed.
- Devtool Integration: Vite.js seamlessly integrates with popular browser developer tools. It provides an enhanced debugging experience by mapping original source code to the browser, enabling developers to directly debug their code without any additional setup or tooling.
- Plugin Ecosystem: Vite.js has a growing ecosystem of plugins that extend its functionality and integrate with popular frontend frameworks like Vue.js, React, and Preact. These plugins enhance the development experience and offer additional features, optimizations, and integrations with tools and libraries.
Vite vs Webpack
In this section, we'll be doing a comparison between Vite and Webpack. There are similar bundling tools like webpack for example Rollup and Parcel. The major difference between these tools is Vite uses a native ES module dev server, while webpack uses a bundle based dev server. Below is a picture of how modules are bundled with native ESM:
With this setup, unnecessary bundling during development is avoided and build time is greatly reduced and significantly faster
Here is an image of a typical webpack dev server:
Vite.js follows a simplified and opinionated configuration approach. The configuration file is minimal, making it easier to set up and get started quickly. Vite.js has a growing ecosystem of plugins that integrate seamlessly with popular frontend frameworks such as Vue.js, React, and Preact, while webpack is known for its extensive configuration options, allowing developers to fine-tune every aspect of the bundling process. Its vast ecosystem provides a wide range of plugins and loaders, making it highly versatile and adaptable to different project requirements.
Here is an image of a time benchmark test between webpack and Vite:
From the image we can see how fast Vite is in comparison to webpack.
Migrating from Webpack to Vite
In this section we'll look at how we can migrate our application using webpack to Vite. Here are some steps and things to note:
- First install Vite and all its plugins. You can check the getting started guide here
- Make sure your project is using ES modules. You can do that by going to your
package.json
file and pasting
"type": "module",
- Remove all webpack configuration files, like
webpack.config.js
, and replace it with avite.config.js
file. Also in your scripts, you'll need to update with this:
"build": "vite build",
"dev": "vite serve",
- Make sure to remove webpack loaders and plugins that are no longer in use and test your application, so everything is working as it should
Using Vite.js in practice
In this section, we will talk about how we can get started using Vite in practice and also demonstrate with some example code.
To scaffold a react project with vite, paste:
# npm 6.x
npm create vite@latest my-react-app --template react
# npm 7+, extra double-dash is needed:
npm create vite@latest my-react-app -- --template react
You can now change into the project directory, run npm install
and start our development server.
cd react-vite
npm install
npm run dev
In the scripts file we have our commands for building for production and creating a local preview.
{
"scripts": {
"dev": "vite", // start dev server, aliases: `vite dev`, `vite serve`
"build": "vite build", // build for production
"preview": "vite preview"// locally preview production build
}
}
Custom Vite Configurations
Let me share some insights on how we can make Vite configurations more customized and more oriented to our project's needs. Vite is pretty flexible, and with some tweaks in the configuration, it can be fully optimized to your setup and workflow.
Basic Setup
First of all, we will have to create the vite.config.js
located in the root of our project. This file is going to enable us to set a few configurations.
// vite.config.js
import { defineConfig } from "vite";
export default defineConfig({
// configuration options
});
Server Customization
In this option, we can configure development server settings like port, open behavior, and proxy settings.
// vite.config.js
import { defineConfig } from "vite";
export default defineConfig({
server: {
port: 3000, // Change the port
open: true, // Open the browser automatically
proxy: {
"/api": {
target: "http://localhost:5000",
changeOrigin: true,
},
},
},
});
Alias Configuration
Giving aliases shortens the import paths and might help in creating our code with increased readability.
// vite.config.js
import { defineConfig } from "vite";
import path from "path";
export default defineConfig({
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
},
},
});
Plugins
Vite supports many types of plugins to extend it. For instance, we could add a plugin to handle Vue files.
// vite.config.js
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
export default defineConfig({
plugins: [vue()],
});
Environment Variables
We define environment variables by using .env
files for different stages such as development, production etc.
// .env
VITE_API_URL=http://localhost:5000
We then apply them in our project as below:
// example.js
console.log(import.meta.env.VITE_API_URL);
Build Options
Customization of build provides possibilities to improve the performance and output of our application.
// vite.config.js
import { defineConfig } from "vite";
export default defineConfig({
build: {
outDir: "dist",
sourcemap: true,
rollupOptions: {
output: {
manualChunks: {
vendor: ["react", "react-dom"],
},
},
},
},
});
Performance Optimization in Vite
I wanted to share with you some tips about optimizing performance in use with Vite. With these configurations, our development process will be faster and build performance improved.
Quick builds with esbuild
Vite uses Esbuild under the hood. It is known to be very fast, so try to configure it to take full advantage of this fact.
// vite.config.js
import { defineConfig } from "vite";
export default defineConfig({
esbuild: {
minify: true,
},
});
Code Splitting
By default, Vite will automatically split your code into separate chunks for better caching and loading. You can fine-tune the output even further by using rollupOptions
.
// vite.config.js
import { defineConfig } from "vite";
export default defineConfig({
build: {
rollupOptions: {
output: {
manualChunks(id) {
if (id.includes("node_modules")) {
return "vendor";
}
},
},
},
},
});
Tree Shaking
Enable tree shaking so that dead code can be deleted.
// vite.config.js
import { defineConfig } from "vite";
export default defineConfig({
build: {
treeshake: true,
},
});
Lazy Loading
Lazy load modules using dynamic imports when required.
// example.js
import("path/to/module").then((module) => {
// use module
});
OptimizeDeps
Pre-bundle the dependencies in order to make the start time of the development server slightly faster.
// vite.config.js
import { defineConfig } from "vite";
export default defineConfig({
optimizeDeps: {
include: ["react", "react-dom"],
},
});
Minification
Ensure that your JavaScript and CSS files are minified in the production environment.
// vite.config.js
import { defineConfig } from "vite";
import cssnano from "cssnano";
export default defineConfig({
css: {
postcss: {
plugins: [cssnano()],
},
},
build: {
minify: "esbuild",
},
});
Using CDN for Libraries
Offload big libraries to a content delivery network to reduce the bundle size.
// vite.config.js
import { defineConfig } from "vite";
export default defineConfig({
resolve: {
alias: {
vue: "https://cdn.jsdelivr.net/npm/vue@3.2.31/dist/vue.esm-browser.js",
},
},
});
Cache Busting
Activate the cache busting feature to ensure your users receive the latest files.
// vite.config.js
import { defineConfig } from "vite";
export default defineConfig({
build: {
manifest: true,
rollupOptions: {
output: {
entryFileNames: "assets/[name].[hash].js",
chunkFileNames: "assets/[name].[hash].js",
assetFileNames: "assets/[name].[hash].[ext]",
},
},
},
});
Conclusion
Finally, we have come to the end of the tutorial, and we have been able to learn how Vite.js revolutionizes frontend development with its lightning-fast development server, native ES modules support, and blazing-fast production builds. You can check it out for yourself. Happy coding!.