Migrating from create-react-app to Vite - Phelipe Teles

Migrating from create-react-app to Vite

2 min.
View source code

I started to learn React with create-react-app like everyone else, and it really does its job well. I never had to worry too much about tooling but… it is slow to start up.

This never bothered me too much but it’s noticeable and everyone would agree it could be better. Lately, we’re witnessing projects developed to improve on this, more noticeably esbuild and Vite.

I wanted to try this out and thought about migrating a small app of mine, mostly written in Typescript, to Vite. And it was more easy than I expected.

Initial setup

First, I installed Vite:

Bash
$ npm install vite

Updated my npm scripts:

diff
diff --git a/package.json b/package.jsonindex f3307f5..32724e4 100644--- a/package.json+++ b/package.json@@ -31,10 +31,10 @@     "typescript": "^4.1.2"   },   "scripts": {-    "start": "react-app-rewired start",+    "start": "vite",-    "build": "react-app-rewired build",+    "build": "vite build",     "test": "react-scripts test",

Next, I needed to modify my index.html file. The reasons for the following steps are explained in more detail here.

Moved my index.html from the ./public folder to my project’s root folder and added a script tag with my JS entry point as its src attribute.

diff
diff --git a/public/index.html b/index.htmlsimilarity index 88%rename from public/index.htmlrename to index.htmlindex ecb0830..3abb36f 100644--- a/public/index.html+++ b/index.html@@ -12,5 +12,6 @@   <body>     <noscript>You need to enable JavaScript to run this app.</noscript>     <div id="root"></div>+    <script type="module" src="/src/index.jsx"></script>   </body> </html>

I didn’t had to but if you have any %PUBLIC_URL% in your html file, just replace it with /, as explained in the linked article.

TypeScript setup

At this point, I couldn’t get my app to run because my project used tsconfig.json include properties to make absolute imports, which Vite didn’t understand.

The solution was simple: install a Vite plugin called vite-tsconfig-paths which supports, apart from path mapping, include and exclude properties as well:

Bash
$ npm install vite-tsconfig-paths

Once installed, we add it to our vite.config.ts:

TypeScript
import { defineConfig } from "vite";import tsconfigPaths from "vite-tsconfig-paths"; export default defineConfig({  build: {    outDir: "build"  },  plugins: [tsconfigPaths()]});

I also set the output directory to be build, instead of the default dist, because that’s what CRA uses.

After that, I was able to start a server and see my app running.

Jest setup

Because I intended to remove react-scripts from my project, I needed to figure out how to run my Jest tests without react-scripts test.

I needed a way to get Jest to understand/transpile TypeScript and JSX.

Fortunately, there is project to help with that called ts-jest. All we need to do is add it as a jest preset in jest.config.js:

JavaScript
module.exports = {  preset: "ts-jest",  setupFilesAfterEnv: ["<rootDir>src/setupTests.ts"],  testPathIgnorePatterns: ["<rootDir>/cypress/"],  moduleDirectories: ["node_modules", "src"]};

For my specific setup, I also needed to:

  • Ignore *.spec.js files inside ./cypress/integration folder
  • Rename ./src/setupTests.js to ./src/setupTests.ts. Otherwise, types from the @testing-library/jest-dom/extend-expect wouldn’t be imported.
  • Add "src" to moduleDirectories, because it would not understand absolute imports that look up paths inside tsconfig.json include property

Conclusion

This seems to be working fine so far, development environment is much faster to boot, though I haven’t checked how great hot reloading is.

But I’m amazed by that first experience and how straightforward it was.

Finally, I uninstalled my CRA-related dev dependencies:

Bash
$ npm uninstall react-scripts customize-cra react-app-rewired babel-plugin-import