React with Vite and TypeScript and its common challenges

React

For a long time, the Create React App environment was the most popular way of starting new React projects. It does not seem to be maintained anymore, and the new React documentation does not even mention it. Fortunately, there are alternatives.

The documentation mentions solutions such as Next.js. While it is a good solution, it includes a Node.js component that implements Server-Side Rendering. SSR pre-renders pages on the server before sending them to the client. If you want to avoid that and create applications similar to the ones built with the Create React App, another alternative exists.

Introducing Vite

Vite is a build tool that aims to deliver a reliable and fast development experience by giving up on Webpack in favor of Rollup and esbuild. One of the advantages of this solution is a significantly shorter build time.

Starting a React project with TypeScript

To start a new project with Vite, we need to run the following command:

Once we do that, Vite asks us to make a few choices, such as the framework we want to use. Vite works not only with React but also with many other frameworks, such as Svelte and Vue. In fact, Vite is maintained by the Vue team.

The next significant question Vite asks us is whether or not we want to use the Speedy Web Compiler. SWC is a JavaScript and TypeScript compiler written in Rust. It aims to replace Babel and the original TypeScript compiler and can provide a significant speed boost.

SWC only transpiles the TypeScript code. Vite still uses the original TypeScript compiler to perform type checking.

The only thing left to start our project is to install the dependencies using  and run afterward. By default, this makes our application available at http://localhost:5173/

 

Using environment variables

Through environment variables, we can store values that can differ across various environments our application runs in, such as the testing environment and production. Another important advantage of environment variables is that we don’t include them in the source code pushed to our Git repository. Thanks to that, we can keep them secret.

A good example of an environment variable is the URL of our API because it will be different when testing and on production. The most straightforward way of adding an environment variable is through the file.

.env

All environment variables that don’t have the prefix are not available to our frontend application to prevent leaking them accidentally.

Let’s include the file in our to ensure we don’t commit it to the repository by accident.

.gitignore

Vite provides some TypeScript definitions for environment variables under the hood by default.

node_modules/vite/types/importMeta.d.ts

We can improve the above type by modifying the file in our project.

vite-env.d.ts

With the triple slash directive, we are adjusting the types built into Vite and adding the property.

When we look at the code Vite serves to the browser, we can see that the environment variables are available through the object.

You might notice that it is slightly different from Create React App where we need to use the object instead.

Let’s create a simple function that fetches a list of posts using our environment variable.

fetchPosts.tsx

Testing using the React Testing Library and Vitest

Jest is currently the most popular JavaScript testing framework. While it can work with Vite, there is an alternative worth considering.

Vitest is a tool that aims to be a drop-in replacement for Jest. Since Vitest was built with Vite in mind, it was adjusted to its architecture. This allows it to be fast and reliable.

Let’s create a straightforward component that renders a list of posts so that we can test it.

PostsList.tsx

Under the hood, we use the function we wrote before.

usePostsList.tsx

Setting up the testing environment

To be able to write unit tests for our component, we will need a set of libraries.

The first step is to adjust the configuration of Vite.

vite.config.ts

The first thing to notice is that we are using the function from , not . This is because we need to provide the property to our configuration.

By specifying , we are adding to our unit tests. It is a JavaScript implementation of DOM and browser APIs that allows us to test how our React components would interact with a real browser.

We also have to add a script that runs Vitest to our .

package.json

Creating a basic test

Thanks to our setup, we can now create our first simple test.

PostsList.test.tsx

✓ The PostsList component
✓ when the fetchPosts function returns a valid list of posts
✓ should render the posts

If we’re used to writing tests with Jest, we might notice that we have to import functions such as and explicitly. While this is a default behavior or Vitest, we could change that by adding to the testing configuration in the file.

Adding more test cases

Let’s test what happens when fetching the posts fails.

PostsList.test.tsx

The PostsList component
✓ when the fetchPosts function returns a valid list of posts
✓ should render the posts
when the fetchPosts function throw an error
✓ should render the error message
× should not render any posts

Unfortunately, the test that ensures no posts are rendered when there is an error fails. Even worse, it fails only when we run all our tests in the sequence. It passes without problems when we’re running it in isolation.

We are experiencing this problem because we rendered the posts in our previous tests, and they are still present in the DOM tree. We must explicitly configure Vitest to reset the DOM tree after each test. To do that, let’s create a setup file.

tests-setup.tsx

We also have to point to it in our Vite configuration.

vite.config.ts

Thanks to that, we can keep our tests independent of each other when we use the jsdom library and simulate the DOM tree.

Summary

In this article, we’ve reviewed how to set up React with Vite and TypeScript. We started by explaining the basic setup steps but also dealt with some potential challenges. One example was using environment variables while ensuring they were typed with TypeScript. Another important aspect was testing with the Vitest framework. Even though it is meant to be a replacement for Jest, it might require some slight adjustments.

With all that knowledge, we are ready to build projects with Vite. It provides a fast and reliable environment focused on the overall development experience.

Subscribe
Notify of
guest
2 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Shehzad Ahmed
Shehzad Ahmed
11 months ago

i followed you in linkedIn as well. keep it up. I learned a lot from you. i really appreciate your more content.