CRA to Vite.js migration guide
#
DictionaryName | Description |
---|---|
CTA | Create React App is React's default scaffolding tool to create new React projects. Click here for more information. Initially, it was the default starting point for new Eva Suite modules. |
Vite.js | It's a new popular framework. Vite is 10-20 times faster that CRA because it uses esbuild instead of webpack under the hood. Click here for more information. |
Rollup | Rollup is a module bundler for JavaScript which compiles small pieces of code into something larger and more complex, such as a library or application. It uses the new standardized format for code modules included in the ES6 revision of JavaScript, instead of previous idiosyncratic solutions such as CommonJS and AMD. Click here for more information. |
#
Mandatory stepsThese are all the steps one must take to migrate from CRA to Vite.js
- Start with installing
vite
,vite-preset-react
andvite-plugin-svgr
npm install vite vite-preset-react vite-plugin-svgr --save-dev
- Continue by replacing
react-scripts
withvite
in package.json
"dependencies": {- "react-scripts": "^4.0.3" },+ "devDependencies": {+ "vite-preset-react": "^1.4.2",+ "vite": "^2.5.8"+ }
- Change the scripts section in package.json
"scripts": {- "start": "react-scripts start",- "build": "react-scripts build",- "test": "react-scripts test",- "eject": "react-scripts eject",+ "start": "vite",+ "build": "tsc && vite build",+ "serve": "vite preview",+ "test": "vite test", },
- Remove
react-app-env.d.ts
file if you have it in your project - Remove the
node_modules
folder - Vite requires Node.js version >=12.0.0. If you're not using this version you need to upgrade first.
- Run
npm install
- Add the
vite.config.ts
file to the root of your project. We add some adjustments to make absolute paths working together with Rollup. Other solution would be to rewrite all the imports as relative imports. You needvite-plugin-svgr
if you've used svg imports in your app. Instead of@vitejs/plugin-react-refresh
we use the wrapper projectvite-preset-react
because there we can constrol the default import of React with.
/* eslint-disable import/no-extraneous-dependencies */import { defineConfig } from 'vite';import svgr from 'vite-plugin-svgr';import path from 'path';import presetReact from 'vite-preset-react';import { readdirSync } from 'fs';
const absolutePathAliases: { [key: string]: string } = {};
const srcPath = path.resolve('./src');// Don't forget to adjust the regex here so it can include .vue, .js, .jsx, etc... files from the src/ folder.// In my case, I'm writing React + TypeScript so the regex find files with .ts?(x) extensions only.//const srcRootContent = readdirSync(srcPath, { withFileTypes: true }).map((dirent) => dirent.name.replace(/(\.ts){1}(x?)/, ''),);
srcRootContent.forEach((directory) => { absolutePathAliases[directory] = path.join(srcPath, directory);});
// https://vitejs.dev/config///export default defineConfig({ // This changes the out put dir from dist to build // comment this out if that isn't relevant for your project // base: '/myawesomemodule', build: { outDir: 'build', }, resolve: { alias: { ...absolutePathAliases }, }, plugins: [presetReact(), svgr()],});
- I'll advice you to add an
.eslintignore
file that contains the Vite.js config file (vite.config.ts
) because your editor will throw unwanted eslint errors in that file otherwise. - Update your
tsconfig.json
You must set the tsconfig.json. to useesnext
as a target, lib and module type. This might change in future versions of TypeScript as more esnext functionality is added to the ES standard for a given year so check the Vite site for updated config. Add the Vite.js types to thetypes
section. This tells TypeScript about the special Vite.js browser functionality that it provides for us. Finally don’t forget to setisolatedModules
to true if you don’t have that already. There is some modern Typescript functionally that is not supported by Vite.js yet. If you don't want to get into a world of TypeScript hurt, you should also setskipLibCheck
totrue
.
{ "compilerOptions": { "target": "ESNext", "lib": ["dom", "dom.iterable", "esnext"], "types": ["vite/client", "vite-plugin-svgr/client"], "allowJs": false, "skipLibCheck": true, "esModuleInterop": false, "allowSyntheticDefaultImports": true, "strict": true, "forceConsistentCasingInFileNames": true, "noFallthroughCasesInSwitch": true, "module": "esnext", "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, "jsx": "react-jsx" }, "include": ["./src"]}
- Change your
.env
variables to the 'Vite way' of dealing with variables.
# Define custom env variable (.env file)- REACT_APP_NAME=My App+ VITE_NAME=My App# Access custom env variable (e.g. React component)- process.env.REACT_APP_NAME+ import.meta.env.VITE_NAME
- Move
public/index.html
toindex.html
(project root folder). - Remove
%PUBLIC_URL%
from index.html:
- <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />+ <link rel="icon" href="/favicon.ico" />- <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />+ <link rel="apple-touch-icon" href="/logo192.png" />- <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />+ <link rel="manifest" href="/manifest.json" />
PUBLIC_URL
can be remove from Netlify toml file (netlify.toml
) Instead we will set thebase
property in the Vite configuration (vite.config.ts
) like so
export default defineConfig({ base: '/myawesomemodule', ...});
- Add entry point in index.html:
<noscript>You need to enable JavaScript to run this app.</noscript> <div id="root"></div>+ <script type="module" src="/src/index.tsx"></script>
- Fix TypeScript errors. You're probably going to get new and exciting TypeScript errors when you run
npm run build
. So the next step is to fix all these errors before you proceed. - If you encounter this error:
[vite:css] Preprocessor dependency "sass" not found. Did you install it?
just install sass
globally e.g. npm install sass -g
If you have SCSS imports error from Style Sheets from node modules using the tilde
~
like for example@import '~@springtree/eva-suite-ui/dist/css/index.css';
just remove the tilde~
.Please note that some node modules are not ready to work together will Rollup.js. Take for example this issue with
file-saver
So Rollup.js doesn't play nice with default
React
import intsx
files. You either choose not to import React anywhere in yourtsx
files, or you choose to import it everywhere by default. If you choose the latter one, you need to specify in Rollup pluginplugin-react-refresh
plugin:plugin: [ reactRefresh({ // injectReact: false, }),]