Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Cannot use import statement outside a module" error in dev server with react-error-boundary #982

Closed
rmarscher opened this issue Oct 24, 2024 · 10 comments · Fixed by #998
Closed
Assignees
Labels
bug Something isn't working

Comments

@rmarscher
Copy link
Contributor

I tried adding react-error-boundary to my app and it gives an error with the dev server. I think it works with the production build. I recreated my own ErrorBoundary class component with a "use client" directive by copying from that library and it works in dev mode.

Related to #423. The react-error-boundary package is still recommended in the React 19 docs at the bottom of this section and in some other code examples https://19.react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary

To reproduce, create a waku app, add react-error-boundary dependency, import and use it somewhere (like App.tsx)

import { ErrorBoundary } from 'react-error-boundary';
<ErrorBoundary fallback={<div>Something went wrong!</div>}>
  <ComponentsThatMightFail />
</ErrorBoundary>

Here is the error:

node_modules/react-error-boundary/dist/react-error-boundary.development.esm.js:2
import { createContext, Component, createElement, isValidElement, useContext, useState, useMemo, forwardRef } from 'react';
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at wrapSafe (node:internal/modules/cjs/loader:1383:18)
    at Module._compile (node:internal/modules/cjs/loader:1412:20)
    at Module._extensions..js (node:internal/modules/cjs/loader:1551:10)
    at Module.load (node:internal/modules/cjs/loader:1282:32)
    at Module._load (node:internal/modules/cjs/loader:1098:12)
    at TracingChannel.traceSync (node:diagnostics_channel:315:14)
    at wrapModuleLoad (node:internal/modules/cjs/loader:215:24)
    at cjsLoader (node:internal/modules/esm/translators:318:5)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/translators:258:7)
    at ModuleJob.run (node:internal/modules/esm/module_job:262:25)
    at async onImport.tracePromise.__proto__ (node:internal/modules/esm/loader:485:26)
@rmarscher rmarscher changed the title "Cannot use import statement outside a module" error with dev server "Cannot use import statement outside a module" error in dev server with react-error-boundary Oct 24, 2024
@rmarscher
Copy link
Contributor Author

The component I am using as a workaround is here - https://gist.github.com/rmarscher/70aa76af4e5f8db26473bf50e220fb99

@rmarscher
Copy link
Contributor Author

I've been re-reading https://vite.dev/guide/dep-pre-bundling. It seems to be an error with ESM loaded in a CommonJS context. I thought

optimizeDeps: {
  exclude: ['react-error-boundary'],
}

might be the fix... but that doesn't seem to work.

@dai-shi
Copy link
Owner

dai-shi commented Oct 26, 2024

Isn't it include: ['react-error-boundary'] instead?

@rmarscher
Copy link
Contributor Author

Isn't it include: ['react-error-boundary'] instead?

I tried that and also tried ssr external / noExternal but haven't found a configuration that works.

@dai-shi
Copy link
Owner

dai-shi commented Nov 4, 2024

(I'll try it later...)

@dai-shi
Copy link
Owner

dai-shi commented Nov 8, 2024

Okay, one technical hurdle is that we can't configure vite config for two vite processes separately. This will be addressed in v0.22.0.

But, even if I configure it manually in the waku source code, it doesn't seem to work:

diff --git a/packages/waku/src/lib/middleware/dev-server-impl.ts b/packages/waku/src/lib/middleware/dev-server-impl.ts
index 7ce7d139..07225476 100644
--- a/packages/waku/src/lib/middleware/dev-server-impl.ts
+++ b/packages/waku/src/lib/middleware/dev-server-impl.ts
@@ -124,6 +124,9 @@ const createMainViteServer = (
       },
       ssr: {
         external: ['waku'],
+        optimizeDeps: {
+          include: ['react-error-boundary'],
+        },
       },
       appType: 'mpa',
       server: { middlewareMode: true },

It still errors with "SyntaxError: Cannot use import statement outside a module".

I'm not sure what's wrong. We need some help from vite experts.

Note that this error comes from SSR only. For RSC, it works because of "use client".

@dai-shi dai-shi added bug Something isn't working help wanted Extra attention is needed labels Nov 8, 2024
@dai-shi
Copy link
Owner

dai-shi commented Nov 8, 2024

The component I am using as a workaround is here - https://gist.github.com/rmarscher/70aa76af4e5f8db26473bf50e220fb99

Another workaround would be simply wrap (re-export) react-error-boundary. I haven't tried it though.

@dai-shi
Copy link
Owner

dai-shi commented Nov 10, 2024

I'm not sure what's wrong. We need some help from vite experts.

I looked into it a little deeper. It's actually a Waku-related issue.

To prove it, this patch fixes the issue:

diff --git a/packages/waku/src/lib/middleware/dev-server-impl.ts b/packages/waku/src/lib/middleware/dev-server-impl.ts
index 7ce7d139..d9be9ee2 100644
--- a/packages/waku/src/lib/middleware/dev-server-impl.ts
+++ b/packages/waku/src/lib/middleware/dev-server-impl.ts
@@ -135,6 +135,12 @@ const createMainViteServer = (
 
   const loadServerModuleMain = async (idOrFileURL: string) => {
     const vite = await vitePromise;
+    if (
+      idOrFileURL ===
+      'file://node_modules/react-error-boundary/dist/react-error-boundary.development.esm.js'
+    ) {
+      return vite.ssrLoadModule('react-error-boundary');
+    }
     if (idOrFileURL === 'waku' || idOrFileURL.startsWith('waku/')) {
       // HACK `external: ['waku']` doesn't do the same
       return import(/* @vite-ignore */ idOrFileURL);

So, the issue is file resolving issue with "use client".

@dai-shi
Copy link
Owner

dai-shi commented Nov 10, 2024

Another way is this:

diff --git a/packages/waku/src/lib/middleware/dev-server-impl.ts b/packages/waku/src/lib/middleware/dev-server-impl.ts
index 7ce7d139..f87e370b 100644
--- a/packages/waku/src/lib/middleware/dev-server-impl.ts
+++ b/packages/waku/src/lib/middleware/dev-server-impl.ts
@@ -286,6 +286,10 @@ const createRscViteServer = (
     config: { rootDir: string; basePath: string },
     initialModules: ClonableModuleNode[],
   ) => {
+    id = id.replace(
+      '/node_modules/react-error-boundary/dist/react-error-boundary.development.esm.js',
+      '/node_modules/.vite/waku-dev-server-main/deps/react-error-boundary.js',
+    );
     let file = id.startsWith('file://')
       ? decodeFilePathFromAbsolute(fileURLToFilePath(id))
       : id;

This is related with initialModules, so @Aslemammad might have some ideas.

@dai-shi
Copy link
Owner

dai-shi commented Nov 11, 2024

The issue can actually be in rscTransform plugin. I'm working on it.

@dai-shi dai-shi self-assigned this Nov 11, 2024
@dai-shi dai-shi removed the help wanted Extra attention is needed label Nov 11, 2024
dai-shi added a commit that referenced this issue Nov 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants