paint-brush
Navigating the Transition from CRA to Vite – A Developer's Journeyby@smakss
284 reads

Navigating the Transition from CRA to Vite – A Developer's Journey

by SMAKSSDecember 27th, 2023
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

This article delves into the technical journey of migrating a web project from Create React App (CRA) to Vite. It covers the initial setup changes, resolving JSX file extensions, SVG import adjustments, path alias configurations, environment variable updates, and testing transitions. The piece also discusses the migration of an NPM module to Vite, emphasizing key configurations for handling CSS and external dependencies. Practical insights are provided throughout to assist developers in navigating this transition smoothly.
featured image - Navigating the Transition from CRA to Vite – A Developer's Journey
SMAKSS HackerNoon profile picture

While we were busy using tools like Create React App (CRA) on a day-to-day basis, Vite just popped up as an efficient tool that brought innovation and gained a lot of attention in the community.


NPM trends over the past 5 years


However, migrating an existing project from Create React App (CRA) to Vite can be a journey filled with unexpected challenges. Here, I share our experience, shedding light on the intricacies of such a migration and providing insights that might ease your transition.

Initial Setup and Configuration

Our odyssey began with the addition of @vitejs/plugin-react and vite to our project, which necessitated the removal of react-scripts and react-app-rewired. Our reliance on react-app-rewired had left us with custom configurations that didn't translate directly to Vite. This was particularly evident when addressing our JSX files, traditionally with .js extensions, which we resolved by crafting a custom plugin to enforce .jsx extensions for JSX-containing files.


// vite.config.js snippet
optimizeDeps: {
    esbuildOptions: {
        plugins: [
            {
                name: 'load-js-files-as-jsx',
                setup(build) {
                    build.onLoad(
                        {filter: /src\/.*\.js$/},
                        async (args) => ({
                            loader: 'jsx',
                            contents: await fs.readFile(args.path, 'utf8'),
                        })
                    )
                },
            },
        ],
    },
},

Troubleshooting the Setup

Even with configurations seemingly in place, our application was initially unresponsive, offering no clues beyond a This site can’t be reached message. It was only after comparing our structure with a Vite skeleton project did we realised that index.html needed relocation from the public directory to the root. This simple move was the key to our breakthrough.

SVG Usage

The initial application run surfaced a plethora of errors, especially with SVG imports. We swiftly adopted vite-plugin-svgr, modifying our import statements to accommodate Vite's module resolution.


// vite.config.js snippet
plugins: [
    react(),
    svgr({
        svgrOptions: {},
        include: '**/*.svg?react',
    }),
],

Path Aliases and Environment Variables

Migrating custom paths and environment variables was another hurdle. The Vite configuration syntax differed significantly from CRA, but we mapped our aliases and adopted the import.meta.env pattern, prefixing our variables with VITE_ to align with Vite's conventions.


// vite.config.js snippet
resolve: {
    alias: {
        // Aliases
    },
},

Testing and Linting Adjustments

With Vite, we transitioned from Jest to Vitest, necessitating a renaming of our test files and an addition to our ESLint configuration to recognize Vitest's global variables.


// .eslintrc snippet
"globals": {
    "vi": true
}

Build and Development Configuration

Vite's default build directory is dist, a departure from CRA's build. This necessitated script updates in our package.json. Moreover, to maintain our development workflow, we customized the development server's startup to land on a specific admin page.


// package.json snippet
"dev": "vite --port 3000 --open custom-url",

Migrating an NPM Module to Vite

The transition of an NPM module from CRA to Vite introduced unique considerations. We disabled the public directory and defined the main entry file for the library. The package's main entry point was also specified in package.json.


// vite.config.js snippet for NPM module
publicDir: false,
build: {
    lib: {
        entry: path.resolve(__dirname, 'src/main.jsx'),
        formats: ['es'],
        fileName: 'main',
    },
    rollupOptions: {
        external: ['react', 'react-dom', 'react/jsx-runtime'],
    },
},


For CSS management, we leveraged vite-plugin-lib-inject-css, which efficiently chunked CSS files corresponding to their JavaScript counterparts.


// vite.config.js snippet
plugins: [
    // Other plugins...
    libInjectCss(),
    // ...
],

Conclusion

The migration from CRA to Vite was far from trivial; it was a testament to the complexity hidden behind the simplicity of modern tooling. Every step revealed a new aspect of the build and deployment process that we took for granted with CRA. However, the improved build times, reduced configuration overhead, and the promise of a more streamlined development experience provided by Vite were compelling reasons to undertake this journey.


Through trial and error and a fair bit of Googling, we emerged on the other side with a functional setup, a deeper understanding of our toolchain, and a newfound appreciation for the craft of web development.

References

1. DEV Community: A guide detailing the migration process from CRA to Vite, including GitHub Actions workflow updates and optimization tips for development processes.

2. FreeCodeCamp: Offers insights into updating environment variables and troubleshooting common issues when migrating from CRA to Vite, such as global is not defined errors.

3. Robin Wieruch's Blog: Provides a comprehensive guide on migrating to Vite, including creating a `vite.config.js` file and updating `index.html`, with additional steps for using ESLint and TypeScript with Vite.

4. KingsCoder: A step-by-step tutorial on converting a CRA application to Vite, with additional instructions for TypeScript templates and solutions for potential NPM installation errors.

5. Patrick Desjardins' Blog: Shares personal migration experiences to ViteJS with TypeScript and absolute path capability, including configuring the `vite.config.ts` file and handling environment variables.

6. HackerNoon: Discusses why Vite is considered better than CRA, emphasizing its faster speed and bundling efficiency with Rollup.

7. HackerNoon: Describes the obsolescence of CRA and presents Vite among other alternatives, noting its performance benefits and fast development time.

8. HackerNoon: A case study on improving speed and performance by migrating from Webpack to Vite, including practical experiences and lessons learned.