Search code examples
reactjstypescriptviterollup

Why is Vite/TS bundling both production and development versions of react-jsx-runtime?


I am using "jsx": "react-jsx", in my tsconfig file and using Vite/rollup for bundling. For some reason my module is always bundling with both react-jsx-runtime.production.min.js and react-jsx-runtime.development.js, even when NODE_ENV is set to production. I only expect the production code to be included.

I can remove both by setting 'react/jsx-runtime' to external in rollup options, but this is also not what I want for the prod bundle. I can't find docs that explain this. Does anyone know how I can stop the bundler from including the development runtime?

vite.config.ts

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

export default defineConfig({
  build: {
    lib: {
      entry: './src/index.tsx',
      formats: ['es'],
      name: `button`,
      fileName: `button`,
    },
    rollupOptions: {
      external:  ['react'],
    },
  },
  plugins: [react()],
})

tsconfig.json

{
  "compilerOptions": {
    "target": "ESNext",
    "useDefineForClassFields": true,
    "lib": ["DOM", "DOM.Iterable", "ESNext"],
    "allowJs": false,
    "skipLibCheck": true,
    "esModuleInterop": false,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "ESNext",
    "moduleResolution": "Node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx"
  },
  "include": ["src"],
  "references": [{ "path": "./tsconfig.node.json" }]
}

tsconfig.node.json

{
  "compilerOptions": {
    "composite": true,
    "module": "ESNext",
    "moduleResolution": "Node",
    "allowSyntheticDefaultImports": true
  },
  "include": ["vite.config.ts"]
}

package.json

{
  "name": "button",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "build": "cross-env NODE_ENV=production vite build && npx tsc"
  },
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-is": "^18.2.0"
  },
  "devDependencies": {
    "cross-env": "^7.0.3",
    "@types/react": "^18.0.26",
    "@types/react-dom": "^18.0.9",
    "@vitejs/plugin-react": "^3.0.0",
    "typescript": "^4.9.3",
    "vite": "^4.0.0"
  }
}

src/index.tsx

import React, { FC } from 'react'

export const Button: FC<any> = ({
  children
}) => (
  <button>{children}</button>
)

export default Button

Solution

  • This will strip out the development runtime, but it's all academic as this is probably not the correct way to bundle a library.

    export default defineConfig((env) => ({
      define: env.command === 'build' ? { "process.env.NODE_ENV":  "'production'" } : undefined,
    ...
    

    On reflection, it makes more sense to add react/jsx-runtime to the external rollup options, or use the opt out as suggested by @Danielo Velasquez