preactjs / signals

Manage state with style in every framework
https://preactjs.com/blog/introducing-signals/
MIT License
3.72k stars 91 forks source link

signals/react: 'default' is not exported by react/jsx-runtime #269

Open cafreeman opened 1 year ago

cafreeman commented 1 year ago

When trying to generate a production build in a Vite react app, we get the following error:

'default' is not exported by react/jsx-runtime, imported by node_modules/@preact/signals-react/dist/signals.module.js

It appears this error originates from these lines https://github.com/preactjs/signals/blob/main/packages/react/src/index.ts#L9-L10, where it's using default imports for the two runtimes, while the jsx-runtime package appears to only provide named exports?

govindg312 commented 1 year ago

Running into the same issue while building a Vite TypeScript React application.

Edit: @cafreeman - I changed the version to 1.1.1 on my package.json and it has fixed the issue with the build. Although, probably need to take a deeper look to fix in future.

gregorip02 commented 1 year ago

I have the same problem, it happens only with the version ^1.2.1, i'm also building a vite typescript react app. i'll go back to 1.1.1 temporarily.

cafreeman commented 1 year ago

Update on this, it looks like there is an issue with how @preact/signals-react incorporates with the JSX runtime. You can circumvent this by updating vite react plugin to use the classic jsxRuntime, though I'm unsure what the tradeoffs are there, e.g.:

export default defineConfig({
  plugins: [
    react({
      jsxRuntime: "classic",
    }),
  ],
});
MMolieleng commented 1 year ago

Update on this, it looks like there is an issue with how @preact/signals-react incorporates with the JSX runtime. You can circumvent this by updating vite react plugin to use the classic jsxRuntime, though I'm unsure what the tradeoffs are there, e.g.:

export default defineConfig({
  plugins: [
    react({
      jsxRuntime: "classic",
    }),
  ],
});

@cafreeman thanks for this solution. Where is this file supposed to be created and named? I am using a create-react-app project

cedeber commented 1 year ago

Update on this, it looks like there is an issue with how @preact/signals-react incorporates with the JSX runtime. You can circumvent this by updating vite react plugin to use the classic jsxRuntime, though I'm unsure what the tradeoffs are there, e.g.:

export default defineConfig({
  plugins: [
    react({
      jsxRuntime: "classic",
    }),
  ],
});

It doesn't help me to fix the issue, unfortunately.

queckezz commented 1 year ago

@eddyw maybe you can quickly chime in here? You created #219 which introduced importing the jsx runtime. Could we import import { jsx } from 'react/jsx-runtime' and call the WrapJsx on that?

If you need a solution right now there are two possibilities:

Also try rebuilding with the above using vite --force to bypass build cache.

maybe this is also related to microbundle https://github.com/developit/microbundle/pull/988? not too familiar.

rschristian commented 1 year ago

maybe this is also related to microbundle developit/microbundle#988? not too familiar.

That PR and the options it fixes are only for TS's transformation of JSX, which these packages do not contain. It's unrelated.

MrCookiez commented 1 year ago

Any updates?

josantana commented 10 months ago

I have the same problem, it happens only with the version ^1.2.1, i'm also building a vite typescript react app. i'll go back to 1.1.1 temporarily.

That worked for me. Still getting this error on 1.3.6 (for my use case at least, @storybook/react-vite + @preact/signals-react).

thure commented 9 months ago

In case anyone else is struggling with this when they go to build Storybook v7.6 with Vite, here’s our viteFinal:

  viteFinal: async (config, { configType }) => {
    return mergeConfig(
      configType === 'PRODUCTION'
        ? {
            ...config,
            // TODO(thure): build fails for @preact/signals-react: https://github.com/preactjs/signals/issues/269
            plugins: flatten(config.plugins).map((plugin: any) => {
              return plugin.name === 'vite:react-babel'
                ? ReactPlugin({
                    jsxRuntime: 'classic',
                  })
                : plugin.name === 'vite:react-jsx'
                ? undefined
                : plugin;
            }),
          }
        : config,
      {
        // When `jsxRuntime` is set to 'classic', top-level awaits are rejected unless build.target is 'esnext'
        ...(configType === 'PRODUCTION' && { build: { target: 'esnext' } }),
        plugins: [
          ThemePlugin({
            root: __dirname,
            content: [resolve(__dirname, '../../../packages/*/*/src') + '/**/*.{ts,tsx,js,jsx}'],
          }),
          turbosnap({ rootDir: config.root ?? __dirname }),
        ],
      },
    );
  },

Looking forward to not needing all this special logic, will watch this issue. Please let me know if a PR would be welcome, maybe we can arrange some bandwidth to help out.

jnicklas commented 9 months ago

Thank you SO MUCH @thure for sharing your Storybook config. I was tearing my hair out with this issue, and with the config you posted I finally made it work. I ended up with a slightly different config in the end, sharing it here as well in case it helps anyone:

import { mergeConfig } from "vite";
import type { StorybookConfig } from "@storybook/react-vite";
import _ from "lodash";
import ReactPlugin from "@vitejs/plugin-react";

const config = {
  // ...
  async viteFinal({ plugins, ...config }, { configType }) {
    // Replace the react plugin with the classic runtime, otherwise we get build errors due to @preact/signals-react
    // see: build fails for @preact/signals-react: https://github.com/preactjs/signals/issues/269
    let baseConfig = {
      ...config,
      plugins:
        configType === "PRODUCTION"
          ? _.flatten(plugins).map((plugin: any) => {
              return plugin.name === "vite:react-babel"
                ? ReactPlugin({
                    jsxRuntime: "classic",
                  })
                : plugin.name === "vite:react-jsx"
                ? undefined
                : plugin;
            })
          : plugins,
    };
    return mergeConfig(baseConfig, {
      ...(configType === "PRODUCTION"
        ? {
            esbuild: {
              jsxInject: `import * as React from 'react'`,
            },
          }
        : {}),
    });
  },

} satisfies StorybookConfig;
export default config;