CRA to Vite.js migration guide
Dictionary#
| Name | 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 steps#
These are all the steps one must take to migrate from CRA to Vite.js
- Start with installing
vite,vite-preset-reactandvite-plugin-svgr
npm install vite vite-preset-react vite-plugin-svgr --save-dev- Continue by replacing
react-scriptswithvitein 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.tsfile if you have it in your project - Remove the
node_modulesfolder - 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.tsfile 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-svgrif you've used svg imports in your app. Instead of@vitejs/plugin-react-refreshwe use the wrapper projectvite-preset-reactbecause 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
.eslintignorefile 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.jsonYou must set the tsconfig.json. to useesnextas 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 thetypessection. This tells TypeScript about the special Vite.js browser functionality that it provides for us. Finally don’t forget to setisolatedModulesto 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 setskipLibChecktotrue.
{ "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
.envvariables 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.htmltoindex.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_URLcan be remove from Netlify toml file (netlify.toml) Instead we will set thebaseproperty 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-saverSo Rollup.js doesn't play nice with default
Reactimport intsxfiles. You either choose not to import React anywhere in yourtsxfiles, or you choose to import it everywhere by default. If you choose the latter one, you need to specify in Rollup pluginplugin-react-refreshplugin:plugin: [ reactRefresh({ // injectReact: false, }),]