Problem
I have a project let's call it root (based on Preact) that relies on a components package (based on React):
Building it using rollup works fine. When I switch components to use vitejs to build, root fails at runtime with this error:
index.es.js? [sm]:770 Uncaught TypeError: Cannot read properties of undefined (reading 'current')
at jsxDEV (index.es.js? [sm]:770:64)
at jsxWithValidation (index.es.js? [sm]:954:17)
at jsxWithValidationDynamic (index.es.js? [sm]:992:13)
at d.RecipesExplorer [as constructor] (index.es.js? [sm]:1915:33)
at d.O [as render] (index.js:532:14)
at j (index.js:190:14)
at w (children.js:137:3)
at L (index.js:418:4)
at j (index.js:246:20)
at w (children.js:137:3)
I'm not changing anything in root or how it's run. It's built using vitejs as well (in both scenarios).
Rollup config
Here's the rollup.config.js for components (this is the build scenario that works without issue):
// rollup.config.js for components
import { defineConfig } from 'rollup'
import typescript from 'rollup-plugin-typescript2'
import json from '@rollup/plugin-json'
import styles from 'rollup-plugin-styles'
export default defineConfig([
{
input: 'src/index.ts',
output: [
// I don't think we need both of these. Keeping them since we had them for now in webpack
{
dir: 'dist/esm',
format: 'es',
},
{
dir: 'dist/cjs',
format: 'cjs',
},
],
plugins: [typescript({}), json()],
external: ['react', 'react-dom', 'styled-components'],
}
])
Vitejs config
When I switch to using vitejs, this is the vite config:
// vite.config.js for components
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { resolve } from 'path'
export default defineConfig({
mode: 'development',
server: {
port: 3000,
open: false,
},
plugins: [react()],
build: {
minify: false,
target: 'modules',
outDir: './dist',
rollupOptions: {
external: ['react', 'react-dom', 'styled-components'],
},
lib: {
entry: resolve(__dirname, './src/index.ts'),
formats: ['cjs', 'es'],
fileName: format => `index.${format}.js`,
},
emptyOutDir: true,
},
})
Package.json snippet
Since vitejs and rollup place files in different directories, I change package.json as well.
For vitejs:
// package.json when configured for vitejs
"name": "components",
...
"exports": {
".": {
"import": "./dist/index.es.js",
"require": "./dist/index.cjs.js"
}
},
"scripts": {
"build": "vite build",
"build:rollup": "rollup -c",
},
...
For rollup:
// package.json when configured for rollup
"name": "components",
...
"exports": {
".": {
"import": "./dist/esm/index.js",
"require": "./dist/cjs/index.js"
}
},
"scripts": {
"build": "vite build",
"build:rollup": "rollup -c",
},
...
Command I'm running & conclusion
When I build components using npm run build (with vite), I get the above error. When I build with npm run build:rollup I get no error.
What am I doing wrong?
Appendix: Root config and package.json
My vitejs config file for root in case that's helpful. Root uses preact and components are built in React.
// vite.config.js for root
import { defineConfig } from 'vite';
import preact from '@preact/preset-vite';
import { resolve } from 'path';
const config = {
RecipeExplorer: {
entry: resolve(__dirname, './src/recipe-explorer.ts'),
fileName: 'recipe-explorer',
},
RecipeList: {
entry: resolve(__dirname, './src/recipe-list.ts'),
fileName: 'recipe-list',
},
RecipeDetailsLegacy: {
entry: resolve(__dirname, './src/recipe-details.ts'),
fileName: 'recipe-details',
},
};
/** IMPORTANT:
* We're using this LIB_NAME env variable so we can create multiple input and output files at build time.
* At the moment this is a work around. Issue is here: https://github.com/vitejs/vite/issues/4530
* Once the above issue gets resolved, we can do away with this workaround.
*/
const currentConfig = config[process.env.LIB_NAME];
if (currentConfig === undefined) {
console.warn(
'LIB_NAME is not defined or is not valid. If you are running a build command LIB_NAME must be specified.',
);
}
// https://vitejs.dev/config/
export default defineConfig({
resolve: {
alias: {
react: 'preact/compat',
'react-dom': 'preact/compat',
'react-dom/test-utils': 'preact/test-utils',
'react/jsx-runtime': 'preact/jsx-runtime',
},
},
plugins: [preact()],
server: {
port: 3010,
host: '0.0.0.0',
},
build: {
outDir: './dist',
lib: {
...currentConfig,
formats: ['cjs', 'es'],
},
emptyOutDir: false,
},
});
I run root using npm run dev which is defined as vite:
// package.json for root
"name": "root",
"scripts": {
"lint": "eslint 'src/**/*.{ts,tsx}'",
"test": "jest",
"dev": "vite",
...
}
...