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

Vite SSG: The requested module 'react-helmet-async' does not provide an export named 'HelmetProvider' #208

Open
HHogg opened this issue Dec 3, 2023 · 12 comments

Comments

@HHogg
Copy link

HHogg commented Dec 3, 2023

I'm using the SSG approach that the Vite docs link to, which produces an ESNext build that is then reimported for pre-rendering routes. After adding in react-helmet-async, this approach fails with

import { HelmetProvider } from "react-helmet-async";
         ^^^^^^^^^^^^^^
SyntaxError: Named export 'HelmetProvider' not found. The requested module 'react-helmet-async' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:

import pkg from 'react-helmet-async';
const { HelmetProvider } = pkg;

I tried all the variations of defining the import (default, * as) and none of these had any effect.

Workaround
Vite has a ssr.noexternal config, which fixed it for me.

export default defineConfig({
  plugins: [react()],
  ssr: {
    noExternal: ['react-helmet-async'],
  },
});

I also played about with react-helment-async's package.json locally to point the main at the esm build this resolved the issue for me. I also separately defined this package as "type": "module" and specified the "exports" field and this also worked. So I think there's a referencing config that isn't playing nicely with the vite ssg approach.

The vite config is fine for me now so I'm not going to look into this further, but hopefully this issue helps someone else looking in the future.

@AvalonCV
Copy link

AvalonCV commented Dec 6, 2023

Same effect here and thanks for providing the ssr.noExternal workaround (which works for me as well).

@alexturpin
Copy link

Same problem if this gets imported into something being ran through tsx

@dsherret
Copy link

dsherret commented May 1, 2024

Note that this same issue occurs when importing via an ESM file in Node.

> node asdf.mjs
file:///V:/scratch/asdf.mjs:1
import { HelmentProvider } from "react-helmet-async"
         ^^^^^^^^^^^^^^^
SyntaxError: Named export 'HelmentProvider' not found. The requested module 'react-helmet-async' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:

The issue is the CJS exports are not statically analyzable:

var src_exports = {};
__export(src_exports, {
  Helmet: () => Helmet,
  HelmetData: () => HelmetData,
  HelmetProvider: () => HelmetProvider
});
module.exports = __toCommonJS(src_exports);

@gajus
Copy link

gajus commented May 3, 2024

We fixed it by patching package.json.

diff --git a/package.json b/package.json
index bc9cb36d157e5db2a7614d028a5a59262c8711f6..d9271fd0f0c7489f91ad6ada3fb130a6ddc0a051 100644
--- a/package.json
+++ b/package.json
@@ -3,8 +3,7 @@
   "version": "2.0.3",
   "description": "Thread-safe Helmet for React 16+ and friends",
   "sideEffects": false,
-  "main": "./lib/index.js",
-  "module": "./lib/index.esm.js",
+  "main": "./lib/index.esm.js",
   "typings": "./lib/index.d.ts",
   "repository": "http://github.com/staylor/react-helmet-async",
   "author": "Scott Taylor <[email protected]>",
@@ -12,6 +11,7 @@
   "files": [
     "lib/"
   ],
+  "type": "module",
   "dependencies": {
     "invariant": "^2.2.4",
     "react-fast-compare": "^3.2.2",

@geyang
Copy link

geyang commented Aug 10, 2024

@gajus thanks for your pointer! I have submitted a PR #230 to address this issue. There is some module resolution issue that caused the CI to fail, maybe you could take a look?

@daniel-ac-martin
Copy link

daniel-ac-martin commented Aug 30, 2024

I've run into a similar issue when running under Jest. (It's fine under webpack.)

One simple workaround appears to be to replace:

import { HelmetProvider } from 'react-helmet-async';

with:

import reactHelmet from 'react-helmet-async';

const { HelmetProvider } = reactHelmet;

Edit: Unfortunately, that then breaks the webpack build.

daniel-ac-martin added a commit to daniel-ac-martin/NotGovUK that referenced this issue Aug 30, 2024
There appears to be a bug in which named imports do not work. This bug
only appears for us when running under Jest, but not when bundling with
webpack.

If this issue is fixed upstream, then this commit can be reverted.

See: staylor/react-helmet-async#208
daniel-ac-martin added a commit to daniel-ac-martin/NotGovUK that referenced this issue Aug 30, 2024
There appears to be a bug in which named imports do not work. This bug
only appears for us when running under Jest, but not when bundling with
webpack.

If this issue is fixed upstream, then this commit can be reverted.

See: staylor/react-helmet-async#208
@daniel-ac-martin
Copy link

Patching the CJS module as such seems to fix the issue:

exports.Helmet = Helmet;
exports.HelmetData = HelmetData;
exports.HelmetProvider = HelmetProvider;

(This seems to be what other modules do in their CJS builds.)

i.e. I suspect the solution is to improve the CJS build rather than to switch to the MJS build. (Which is what the PR does.)

I'm not sure why esbuild doesn't do this already though...
react-helmet-async isn't using the most recent version of esbuild; perhaps it's fixed in a new version?

@daniel-ac-martin
Copy link

Seems related to this: evanw/esbuild#3029

PS: Updating esbuild makes no difference.

BTW, @staylor, what is the reason for using esbuild? - Could you not just build with tsc?

daniel-ac-martin added a commit to daniel-ac-martin/NotGovUK that referenced this issue Aug 30, 2024
There appears to be a bug in which named imports do not work. This bug
only appears for us when running under Jest, but not when bundling with
webpack.

This workaround allows us to import react-helmet-async in different
contexts.

If this issue is fixed upstream, then this commit can be reverted.

See: staylor/react-helmet-async#208
@daniel-ac-martin
Copy link

Here's a more robust (but dirtier) workaround for the calling code:

import reactHelmetDefault, * as reactHelmetNamed from 'react-helmet-async';
const reactHelmet = reactHelmetDefault || reactHelmetNamed;
const { HelmetProvider } = reactHelmet;

@draro
Copy link

draro commented Sep 13, 2024

Hi,
I've try all the solution/workaround mentioned but can't get off the error.
Did someone has other suggestions/fix?

@zhjrcc
Copy link

zhjrcc commented Nov 22, 2024

I also encountered this issue when building React SSR with Vite, but now I can only use version 1.3

@tylerhuyser
Copy link

Experiencing the same issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants