Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rollup + React 17 with new JSX Transform - "React is not defined"

I'm trying to prototype a microfrontend architecture with Rollup and a couple of create-react-app applications. However when I locally yarn link my external app with the container app, I run into the following error:

ReferenceError: React is not defined

23500 | return /#PURE/React.createElement("div", { | ^ 23501 | id: "container", 23502 | className: "flex flex-col h-screen" 23503 | }, /#PURE/React.createElement(BrowserRouter, null, /#PURE/React.createElement(Header, {

I think it's because we're not importing React at the top of every component/file because of React 17's new JSX Transform allowing you to not have to do that. I'd really like to be able to build our micro frontend package without having to import React in every file, is there a way to do this?

Here is the rollup.config.js:

import babel from 'rollup-plugin-babel';
import commonjs from '@rollup/plugin-commonjs';
import external from 'rollup-plugin-peer-deps-external';
import postcss from 'rollup-plugin-postcss';
import resolve from '@rollup/plugin-node-resolve';
import image from '@rollup/plugin-image';
import visualizer from 'rollup-plugin-visualizer';
import includePaths from 'rollup-plugin-includepaths';
import replace from '@rollup/plugin-replace';
import pkg from './package.json';

const extensions = ['.js', '.jsx', '.ts', '.tsx'];

export default {
  input: './src/App.jsx',
  output: [
    {
      file: pkg.main,
      format: 'cjs',
    },
    {
      file: pkg.module,
      format: 'esm',
    },
  ],
  plugins: [
    external(),
    postcss(),
    resolve({
      mainFields: ['module', 'main', 'jsnext:main', 'browser'],
      extensions,
    }),
    image(),
    visualizer(),
    includePaths({ paths: ['./'] }),
    replace({
      'process.env.NODE_ENV': JSON.stringify('development'),
    }),
    babel({
      exclude: 'node_modules/**',
      plugins: [
        [
          'module-resolver',
          {
            root: ['src'],
          },
        ],
      ],
      presets: ['@babel/preset-react'],
    }),
    commonjs(),
  ],
};
like image 402
Noah Peden Avatar asked Jun 02 '21 19:06

Noah Peden


2 Answers

Fixed this by adding { runtime: "automatic" } to the @babel/preset-react preset.

From the preset-react runtime docs:

automatic auto imports the functions that JSX transpiles to. classic does not automatic import anything.

Also mentioned in the React post about the new JSX transform:

Currently, the old transform {"runtime": "classic"} is the default option. To enable the new transform, you can pass {"runtime": "automatic"} as an option to @babel/plugin-transform-react-jsx or @babel/preset-react

Here's a sample:

{
    // ...
    plugins: [
        // ...
        babel({
            // ...
            presets: [
                // ...
                ["@babel/preset-react", { runtime: "automatic" }],
            ]
        })
    ]
}
like image 93
Henry Woody Avatar answered Oct 20 '22 15:10

Henry Woody


In tsconfig.json, add the following code

{
  "compilerOptions": {
    "jsx": "react-jsx",
  }
}


like image 45
Fagner Schwalm Avatar answered Oct 20 '22 15:10

Fagner Schwalm