How do I get HMR (Hot Module Replacement) working with a TypeScript React Monorepo in Vite

1.2k Views Asked by At

I've got a React monorepo (build in TypeScript) and I've recently been switching over from Webpack to Vite. However I'm having real difficult in getting HMR working correctly within Vite (I believe because we separately build our packages).

I'm open to options to get this working (although I think I still need to be able to build my packages, for Jest/ESLint performance).

Project Structure

\apps
  \main
\packages
  \domainA
    \foo
      \package.json
      \build
      \src

At the moment each package gets build using tsc "tsc --project tsconfig.lib.json" into the build directory. The package.json defines the following:

"name": "@ig/foo",
"main": "./build/index.js",
"types": "./build/index.d.ts",
"files": [
    "/build"
],

I can spin up the main application and if I make a change in /packages/domainA/foo/src/index.ts then it'll build (currently using a watcher) and I get a full page reload.

I'd like to eliminate the page reload and instead use HMR. I don't think changing the entry point to "main": "./src/index.ts" will work for my use-case due to the slowness in the other tools unfortunately. However I'm happy to try and bypass this and re-point Vite to the source files if necessary.

I've tried all sorts of permutations, having looked at a few sample repos. But not managed to get anything working, e.g.

resolve: {
  alias: [{
    find: '@ig/foo',
    replacement: '../packages/domainA/foo/src/index.ts',
  },
}

Here is my current Vite config:

import react from '@vitejs/plugin-react';
import fs from 'fs';
import path, { resolve } from 'path';
import { defineConfig } from 'vite';
import mkcert from 'vite-plugin-mkcert';
import svgrPlugin from 'vite-plugin-svgr';

export default defineConfig({
    // optimizeDeps: {
    //     include: ['@infogrid/solution-views-occupancy'],
    // },
    build: {
        outDir: 'build/public',
        sourcemap: true,
        rollupOptions: {
            input: {
                main: resolve(__dirname, 'index.html'),
                base: resolve(__dirname, 'index_base.html'),
            },
         }
     },
     server: {
        port: Number(process.env.PORT),
        // setting to true allows external ip
        host: true,
     },
     plugins: [
        react({ fastRefresh: true }), // Primarily used for HMR
        svgrPlugin({ svgrOptions: { icon: true } }), // Turns svgs into react components
        mkcert(), // Allows for HTTPS during local development
     ]
}
0

There are 0 best solutions below