Migrating from create-react-app to Vite
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:
$ npm install vite
Updated my npm scripts:
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 --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:
$ npm install vite-tsconfig-paths
Once installed, we add it to our vite.config.ts
:
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
:
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"
tomoduleDirectories
, because it would not understand absolute imports that look up paths insidetsconfig.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:
$ npm uninstall react-scripts customize-cra react-app-rewired babel-plugin-import