Create React App (CRA) has played a pivotal role in the development of React’s strong community and ecosystem. When it comes to constructing a local React development environment on a whim, Create React App is the tool of choice for developers of all skill sets.
CRA boasts several standout features that make it hard to overlook, the most prominent ones being its local development server, hot module replacement (HMR), and production bundling. However, Create React App does have a significant drawback, which is progressive speed and performance deterioration.
As an application grows in size and complexity, Create React App’s performance tends to dip. The time it takes to start a development server increases significantly, making Create React App unfit for production.
In this guide, we’ll introduce Vite, a build tool built on esbuild. We’ll cover everything you need to know to start building React applications with Vite, reviewing the differences between Vite and CRA and demonstrating how to migrate from Create React App to Vite. Finally, we’ll mention a few noteworthy competitors to both CRA and Vite. Let’s get started!
To follow along with this tutorial, you’ll need the following:
Vite is a build tool that bridges the gap between current and next-generation web development, providing a faster and more performant experience for developers and modern web projects.
Vite is built on top of esbuild, a JavaScript bundler written in Go that bundles dependencies 10 to 100 times faster than JavaScript-based bundlers.
Created by Evan You, the creator of Vue, Vite is platform-agnostic, meaning you can use it to develop JavaScript and TypeScript applications with support for popular libraries like React, Svelte, Preact, and even vanilla JavaScript.
Vite leverages the browser’s native ESM to parse and compile your code as the browser requests it. It then serves the source file using a plugin like Koa, a lightweight Node.js web server. It creates a dev server with support for hot module replacement to update served modules and Rollup for production builds.
Vite and Create React App are not as different as you might think. At their core, both tools do pretty much the same thing, serving a local development server and bundling codes for production. The major difference lies in how code is served in development and which modules are supported.
Create React App is a development environment that helps to speed up the development process by letting developers focus on their code instead of configuring build tools. Under the hood, Create React App uses a third-party build tool called webpack to handle its core functionalities. Really, this is what Vite is up against.
So, what is webpack? webpack is a JavaScript module bundler just like Vite. But, unlike Vite, webpack supports more than one module out of the box:
webpack uses any of these JavaScript module systems to combine assets and modules into one or more static assets. Then, it uses the Express web server and webpack-dev-server to serve content from the bundled asset with support for HMR.
To put things into perspective, we’ll break down how both tools handle these functionalities in development.
When you start Create React App development for the first time, webpack uses the app’s entry point, the index.js
file, to create a tree of dependencies from all the modules in the project.
Then, it transpiles the code with Babel, bundles the code together, and serves it with the Express web server. Lastly, it sets up sockets that will handle hot module replacement.
Although this approach is faster and lets you focus on your code, it has a significant drawback. webpack repeats the bundling process every time there is a change in the code. As a result, as your source code grows larger, everything becomes sluggish, and the time it takes to serve a dev server and build your projects increases significantly.
Below is a visual depiction of the CRA development process:
On the other hand, Vite only pre-bundles your dependencies using esbuild the first time you start development, before it begins serving your app.
Before starting a dev server, Vite doesn’t need to bundle the entire app or transpile the modules and code; transpiling is done on-demand, making it significantly faster than CRA.
After serving the app, instead of rebuilding and reloading the entire page like CRA, Vite uses route-based code-splitting to determine which part of the code needs to be loaded. Then, it uses the browser to parse the native ES modules from the app’s entry point.
The browser will read the import
and export
statements in your code and make HTTP requests back to the server for each import. Then, the dev server intercepts the requests and performs code transformation where necessary.
Modules without any changes will return a 304 not modified
status code, so the browser ignores them. Therefore, the browser doesn’t have to reload, and the application keeps its state.
Below is a visual depiction of the Vite development process:
Previously, we reviewed a few advantages of using Vite for React app development. Now, let’s take a closer look at Vite’s benefits.
During the pre-bundling process, Vite converts dependencies that are shipped as CommonJS or UMD into ESM. This conversion occurs because Vite only supports ESM and serves native ESM codes by default.
To improve page load performance, Vite can convert dependencies with many internal modules into a single module. These modules tend to fire hundreds of requests at the same time, which could create congestion in the browser and negatively impact load time. But, by pre-bundling these dependencies into a single file, they only need to send one request, thereby increasing overall performance.
Vite leverages the Rollup plugin interface to improve a developer’s experience; in other words, Vite is compatible with most Rollup plugins out of the box.
We previously explained how in a bundled-based server, HMR speed deteriorates significantly as the size of the application increases.
In Vite, HMR is performed over native ESM. When changes occur in a module that accepts hot updates, Vite only needs to precisely invalidate the module. This results in a faster HMR update time, regardless of the size of the application.
To build apps for production, Vite uses preconfigured Rollup, a more efficient bundler than webpack. Therefore, Vite’s build time tends to be quicker than that of CRA, and its output is smaller in size.
To create a Vite app, go to your machine’s terminal, cd
to a preferred folder, and run the following command:
npm create vite@latest
After running the command, the CLI will prompt you to choose a project name. In our case, we’ll use the default name vite-project
. Then, we’ll select react from the list of available templates. This usually takes 10s or less:
Alternatively, you can specify your template of choice in the command and avoid going through the prompt.
You can do so by adding a --template
flag, followed by the framework’s name:
npm init vite@latest vite-project --template react
Next, cd
into the project folder, install the necessary dependencies, and start the dev server with the following commands:
cd vite-project npm install npm run dev
After these commands run, a development server will be up and running on port 5173
. It usually takes Vite just 1325ms to serve an application:
Now, open your browser and enter localhost:5173
. You’ll see a page similar to the one below with the quintessential count button:
That’s it! We’ve successfully set up a Vite React development environment! Next, we’ll look at how to migrate a Create React App project to Vite.
If you have an existing CRA project, it’s pretty simple to migrate it to Vite. First, open the package.json
file in your project folder and delete react-scripts
from the list of dependencies:
"dependencies": { ... "react-scripts": "5.0.1", ... },
Next, add "devDependencies"
with the following code:
"devDependencies": { "@vitejs/plugin-react": "^2.0.1", "vite": "^3.0.7" },
Now, replace the scripts below with the following code snippet, respectively:
"scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject" },
"scripts": { "start": "vite", "build": "vite build", },
Go to the index.html
file inside the Public
folder and remove every %PUBLIC_URL%/
prefix in the link paths:
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" /> <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" /> <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
Replace the removed prefix with the following:
<link rel="icon" href="./public/favicon.ico" /> ... <link rel="apple-touch-icon" href="./public/logo192.png" /> ... <link rel="manifest" href="./public/manifest.json" />
Then, add an entry point script inside the body
element, just below the root
div:
<script type="module" src="/src/index.jsx"></script>
Before you do this, rename every .js
file that contains React codes to a .jsx
file. For example, you’d rename the index.js
file to index.jsx
.
Then, move the index.html
file to the root folder:
Next, we’ll create a Vite config file, delete the node modules folder, and reinstall the dependencies. Start by creating a vite.config.js
file inside the root folder and add the following code:
import { defineConfig } from "vite"; import react from "@vitejs/plugin-react"; export default defineConfig({ plugins: [react()], })
Next, go to the root folder and delete the node_modules
folder. Then, run the following command to reinstall the dependencies and start the development server:
npm install npm start
Now, if you open your browser and go to localhost:5173
, the development server should successfully boot up:
We’ve looked at how CRA and Vite work, and we’ve reviewed some of the benefits of using Vite over CRA. Now, let’s take a look at some differences between these tools.
When you start developing with Vite, the first thing you’ll probably notice is the difference in path resolving. Unlike CRA, Vite doesn’t have an inbuilt src
path. So, instead of importing files and components in your React app with the following code:
import Cards from "components/cards";
You’ll need to import them as follows:
import Cards from “/src/components/cards.jsx”
Fortunately, there’s a fix for this path resolving. Go to the project’s root folder, open the vite.config.js
file, and replace the existing code with the following respective code blocks:
import { defineConfig } from "vite"; import react from "@vitejs/plugin-react"; export default defineConfig({ plugins: [react()], });
import { defineConfig } from "vite"; import react from "@vitejs/plugin-react"; export default defineConfig({ resolve: { alias: [ { find: "common", replacement: resolve(__dirname, "src/common"), }, ], }, plugins: [react()], });
Save the code, and you should now be able to use absolute paths in your project.
Another difference between Create React App and Vite is the environment variable naming convention. If you’re using environment variables in your project, you’ll want to replace the REACT_APP_
prefix with VITE_
:
//Instead of this REACT_APP_ API_KEY = 1234567890.. //Use this VITE_API_KEY = 1234567890..
Changing the variables one by one can be a pain, especially if you have a lot of variables present in the .env
file. Fortunately, the vite-plugin-env-compatible package lets us use environment variables without changing their names.
Use the following command to install the vite-plugin-env-compatible package:
npm i vite-plugin-env-compatible
Next, go to the vite.config.js
file in the root folder of the project and add the following code:
import envCompatible from 'vite-plugin-env-compatible'; export default defineConfig({ ... envPrefix: 'REACT_APP_', plugins: [ react(), envCompatible ], });
The envPrefix
property will tell Vite to use variables with a REACT_APP_
prefix. Now, you can use environment variables in your project without changing names. However, you’ll still have to replace process.env
with import.meta.env
in your code.
You can use the search feature in your IDE to quickly find and replace every process.env
in your codebase.
Create React App and Vite aren’t the only options available when you need to quickly set up an app. Let’s quickly review a few, comparing their internal processes to how CRA and Vite work.
react-boilerplate is a preconfigured template for building scalable and maintainable React applications. It provides a prebuilt set of tools and best practices that are ready to use, making it one of the best choices for developers to quickly get started without having to set up and configure the development environment from scratch.
Like the former, react-starter-kit is a preconfigured set of boilerplate code. Typically, it provides a basic file and folder structure, commonly used libraries and tools, and initial code to aid developers in starting their projects.
create-next-app is a command line tool for quickly setting up a Next.js application. create-next-app is similar to Create React App, but it is specifically designed for Next.js.
Gatsby is an open source framework based on React that allows developers to build fast and performant websites and web applications. It uses a static site generator (SSG) approach, which pre-builds a site’s HTML, CSS, and JavaScript at build time, instead of generating it on the fly when a user requests a page.
This approach makes Gatsby sites extremely fast and highly performant, as well as easily scalable. Gatsby also provides a rich set of features and plugins, making it easy to add functionality like images and videos, offline support, and analytics.
The T3 stack is a combination of web development technologies utilized in the creation of full-stack, type-safe React applications. Its core components are Next.js and TypeScript, with Tailwind CSS and tRPC being incorporated often as well. The stack is modular in design, making individual components interchangeable based on project requirements.
Before selecting a React starter kit for your project, you should compare the features of all the available alternatives to make the best decision:
In this article, we introduced Vite, compared its core concepts to those of Create React App, and learned how both tools work in development. We also examined the benefits of using Vite and demonstrated how to migrate a Create React App project to Vite.
Hopefully, this article has given you a better sense of what tool to use for your individual project. Leave a comment if you learned something or have a question.
Install LogRocket via npm or script tag. LogRocket.init()
must be called client-side, not
server-side
$ npm i --save logrocket // Code: import LogRocket from 'logrocket'; LogRocket.init('app/id');
// Add to your HTML: <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script> <script>window.LogRocket && window.LogRocket.init('app/id');</script>
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowSOLID principles help us keep code flexible. In this article, we’ll examine all of those principles and their implementation using JavaScript.
JavaScript’s Date API has many limitations. Explore alternative libraries like Moment.js, date-fns, and the new Temporal API.
Explore use cases for using npm vs. npx such as long-term dependency management or temporary tasks and running packages on the fly.
Validating and auditing AI-generated code reduces code errors and ensures that code is compliant.
2 Replies to "Vite 3.0 vs. Create React App: Comparison and migration guide"
Very helpful article, thanks for this.
You should add a “Common Q’s” section, like off the top of my head, CSS module support? SCSS/SASS support? WIll it handle SVG imports like CRA?