import { defineConfig, type PluginOption } from 'vite'; import type { RollupOptions } from 'rollup'; import react from '@vitejs/plugin-react'; import checker from 'vite-plugin-checker'; import externalGlobals from 'rollup-plugin-external-globals'; import { resolve } from 'path'; export interface ViteConfigOptions { entry?: string; fileName?: string; port?: number; plugins?: PluginOption[]; external?: string[]; rollupOptions?: Partial; enableTypeCheck?: boolean; } /** * Creates a Vite configuration for microfrontend * * @param options Configuration options * @returns Vite configuration object */ export function createViteConfig(options: ViteConfigOptions = {}) { const { entry = 'src/main.tsx', fileName = 'main', port = 3000, plugins = [], external = [], rollupOptions = {}, enableTypeCheck = true } = options; const basePlugins = [ react(), ...(enableTypeCheck ? [checker({ typescript: true })] : []), ...plugins ]; const defaultExternal = ['react', 'react-dom', 'react/jsx-runtime']; const allExternal = [...defaultExternal, ...external]; const globalsMap: Record = { 'react': 'React', 'react-dom': 'ReactDOM', 'react/jsx-runtime': 'ReactJSXRuntime', }; // Vite 8 uses Rolldown which preserves CJS require() calls for external // modules. externalGlobals only converts ESM imports to globals, not CJS // require() calls. This banner provides a require shim that maps external // module names to their corresponding globals so require("react-dom") etc. // resolve correctly in the browser. const requireEntries = Object.entries(globalsMap) .map(([mod, global]) => `"${mod}":typeof ${global}!=="undefined"?${global}:{}`) .join(','); const requireShim = `var require=function(){var m={${requireEntries}};return function(id){if(m[id])return m[id];throw new Error("Cannot find module: "+id)}}();`; return defineConfig({ resolve: { tsconfigPaths: true, }, plugins: basePlugins, server: { port, }, build: { lib: { entry: resolve(process.cwd(), entry), fileName, formats: ['es'], }, rollupOptions: { output: { format: 'es', entryFileNames: `[name].js`, chunkFileNames: `[name].js`, assetFileNames: `[name].[ext]`, banner: requireShim, }, plugins: [ externalGlobals(globalsMap), ], external: allExternal, ...rollupOptions, }, }, }); }