Migrating from create-react-app to Vite: A Quick and Easy Guide
Tags: vite, react, tutorial, javascript
Published: 2023-07-20 20:21:53

In recent times, React has shifted its recommendation from using create-react-app (CRA) as the starting point for new projects. Instead, it now encourages developers to [use a framework for most projects](https://react.dev/learn/start-a-new-react-project). However, for smaller projects, a full-fledged framework might not be necessary. In such cases, [Vite](https://vitejs.dev/)) emerges as a promising option. Vite is not a framework like Next.js or Remix, but it offers several features that make it an excellent choice for small projects, such as personal portfolios, [like my portfolio](https://github.com/henriquejensen/henriquejensen.github.io). In this blog post, we will walk you through the steps to migrate from create-react-app to Vite for your next project.


## Migration steps
These migration steps assume that we have a CRA project with Typescript.

1. Removing CRA
2. Installing Vite dependencies
3. Moving index.html
4. Adding vite.config.ts
5. Adding vite-env.d.ts
6. Adding vite scripts
7. Fixing tsconfig.json
8. Migrating from Jest to Vitest
9. Extra

### Step 1 - Removing CRA
The first step is to uninstall create-react-app from your project.

```bash
npm uninstall react-scripts
```

### Step 2 - Installing Vite dependencies
Next, install the required dependencies for Vite.

```bash
npm install vite @vitejs/plugin-react-swc vite-tsconfig-paths vite-plugin-svgr
```
_Note: Depending on your specific needs, you can choose a different plugin from the official Vite plugins [documentation.](https://main.vitejs.dev/plugins/)_

### Step 3 - Moving index.html

create-react-app uses public/index.html as the default entry point, while Vite looks for index.html at the root level. To make the transition, move your index.html to the root directory and update the script tag accordingly.

```html
<!-- index.html -->
<body>
  <noscript>You need to enable JavaScript to run this app.</noscript>
  <div id="root"></div>

  <script type="module" src="/src/index.tsx"></script>
</body>
```

### Step 4 - Adding vite.config.ts

Create a vite.config.ts file at the root of your project with the following content:

```typescript
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'

// https://vitejs.dev/config/
export default defineConfig({
  base: '/',
  plugins: [react()]
})
```

### Step 5 - Adding vite-env.d.ts

Create a vite-env.d.ts file inside the src folder with the following content:

```typescript
/// <reference types="vite/client" />

```

### Step 6 - Adding vite scripts

Replace the existing CRA scripts in package.json with Vite scripts.

```json
 "scripts": {
    "start": "vite",
    "build": "tsc && vite build",
    "serve": "vite preview"
}
```

### Step 7 - Fixing tsconfig.json

Update your tsconfig.json to its final version.

```json
{
  "compilerOptions": {
    "target": "ESNext",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": false,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "noFallthroughCasesInSwitch": true,
    "jsx": "react-jsx",
    "types": ["vite/client", "vite-plugin-svgr/client"]
  },
  "include": ["src"]
}
```

### Step 8 - Migrating from Jest to Vitest
As we are moving to Vite, another good idea is to consider migrating from Jest to [Vitest](https://vitest.dev/) as well. Here are the steps:

#### 8.1 - Install Vitest dependencies:

```bash
npm i -D jsdom vitest @vitest/coverage-v8
```

#### 8.2 - Update vite.config.ts to include Vitest configurations:

```typescript
import { defineConfig } from 'vitest/config'
import react from '@vitejs/plugin-react-swc'

// https://vitejs.dev/config/
export default defineConfig({
  base: '/',
  plugins: [react()],
  test: {
    globals: true,
    environment: 'jsdom',
    setupFiles: './src/setupTests.ts',
    css: true,
    reporters: ['verbose'],
    coverage: {
      reporter: ['text', 'json', 'html'],
      include: ['src/**/*'],
      exclude: [],
    }
  },
})
```

#### 8.3 - Update package.json with Vitest scripts:

```json
  "scripts": {
    "start": "vite",
    "build": "tsc && vite build",
    "serve": "vite preview",
    "test": "vitest",
    "test:coverage": "vitest run --coverage --watch=false"
  },
```

### Step 9 - Extras

If you use GitHub Actions to push your code to GitHub Pages, you'll need to update the workflow file as Vite generates a **`dist`** folder when we run `npm run build`.

```yml
name: GitHub Pages

on:
  push:
    branches:
      - master
  pull_request:

jobs:
  deploy:
    runs-on: ubuntu-22.04
    permissions:
      contents: write
    concurrency:
      group: ${{ github.workflow }}-${{ github.ref }}
    steps:
      - uses: actions/checkout@v3

      - name: Setup Node
        uses: actions/setup-node@v3
        with:
          node-version: "16"

      - name: Cache dependencies
        uses: actions/cache@v3
        with:
          path: ~/.npm
          key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node-

      - run: npm ci
      - run: npm run build

      - name: Deploy
        uses: peaceiris/actions-gh-pages@v3
        if: github.ref == 'refs/heads/master'
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./dist

```

With these steps, you should now have successfully migrated your create-react-app project to Vite, enjoying its benefits and optimizing your development process for smaller projects. Happy coding!