KyleJune
KyleJune2mo ago

react-helmet-async missing HelmetProvider export

I'm on the canary version testing out jsxImportSourceTypes and ran into an issue when switching to using npm specifiers for react@18.0.2. I have the following entry in my deno.jsonc imports.
"react-helmet-async": "npm:react-helmet-async@2",
"react-helmet-async": "npm:react-helmet-async@2",
My editor has no issue showing that it recognizes the HelmetProvider. You can see in the attached screenshots that it is recognizing that I'm importing the class. However, when my code runs, I get the following error.
error: Uncaught SyntaxError: The requested module 'react-helmet-async' does not provide an export named 'HelmetProvider'
import { HelmetProvider } from "react-helmet-async";
^
at <anonymous> (file:///home/kyle/Projects/deno/react_app/server.tsx:4:10)
error: Uncaught SyntaxError: The requested module 'react-helmet-async' does not provide an export named 'HelmetProvider'
import { HelmetProvider } from "react-helmet-async";
^
at <anonymous> (file:///home/kyle/Projects/deno/react_app/server.tsx:4:10)
I tried setting nodeModulesDir to true in my deno.jsonc so that it would create a node_modules directory so I could verify it is exported, and it is. It's present in the index.js, index.esm.js, and index.d.ts. Yet when I run deno, it seems to think it isn't.
No description
No description
No description
No description
No description
6 Replies
Deno AI Helper
Deno AI Helper2mo ago
I wasn't able to find the answer to your question in the official Deno documentation. However, based on the information you've provided, it seems like there might be an issue with how the react-helmet-async package exports HelmetProvider or how Deno is resolving the module. One thing to check is whether the version of react-helmet-async you are using is fully compatible with Deno and whether it exports HelmetProvider in a way that Deno can understand. Since you are using a canary version of Deno, there might be changes or regressions that affect module resolution. Also, ensure that your deno.jsonc configuration is correct and that you have enabled the necessary flags to support npm specifiers. Here's a basic example of what your deno.jsonc might look like with jsxImportSourceTypes and nodeModulesDir:
{
"compilerOptions": {
"jsxImportSourceTypes": {
"react": "npm"
}
},
"nodeModulesDir": true,
"imports": {
"react-helmet-async": "npm:react-helmet-async@2"
}
}
{
"compilerOptions": {
"jsxImportSourceTypes": {
"react": "npm"
}
},
"nodeModulesDir": true,
"imports": {
"react-helmet-async": "npm:react-helmet-async@2"
}
}
Please note that the advice provided here is not based on the Deno documentation, and I advise you to double-check the accuracy of the advice given. If the issue persists, you may want to reach out to the maintainers of react-helmet-async or seek assistance from the Deno community for further troubleshooting.
dsherret
dsherret2mo ago
FWIW, I get the same error 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:
> 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 that the cjs exports are not statically analyzable in that package in order to create named exports:
var src_exports = {};
__export(src_exports, {
Helmet: () => Helmet,
HelmetData: () => HelmetData,
HelmetProvider: () => HelmetProvider
});
module.exports = __toCommonJS(src_exports);
var src_exports = {};
__export(src_exports, {
Helmet: () => Helmet,
HelmetData: () => HelmetData,
HelmetProvider: () => HelmetProvider
});
module.exports = __toCommonJS(src_exports);
The following works in both node and deno:
import reactHelmentAsync from "react-helmet-async"

console.log(reactHelmentAsync.HelmetProvider);
import reactHelmentAsync from "react-helmet-async"

console.log(reactHelmentAsync.HelmetProvider);
> node asdf.mjs
[class _HelmetProvider extends Component] { canUseDOM: false }
V:\scratch
> deno run -A asdf.mjs
[class _HelmetProvider extends Component] { canUseDOM: false }
> node asdf.mjs
[class _HelmetProvider extends Component] { canUseDOM: false }
V:\scratch
> deno run -A asdf.mjs
[class _HelmetProvider extends Component] { canUseDOM: false }
KyleJune
KyleJune2mo ago
It's strange that it's not working in node either, their own documentation example shows importing HelmetProvider the way I was.
import { Helmet, HelmetProvider } from 'react-helmet-async';
import { Helmet, HelmetProvider } from 'react-helmet-async';
You can see that import in the first example they have on their npm package. https://www.npmjs.com/package/react-helmet-async#usage Oh I see why it might not work when you tried it in node, it's because you are using mjs extension, which their documentation probably assumes someone is importing it using CommonJS. I'll change my code to import it the way you describe since the exports are not supported in ESM.
dsherret
dsherret2mo ago
yeah, it would work for cjs importing it because it all gets transpiled to cjs. There seems to be people running into a similar issue here: https://github.com/staylor/react-helmet-async/issues/208
GitHub
Vite SSG: The requested module 'react-helmet-async' does not provi...
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 w...
KyleJune
KyleJune2mo ago
Been a while but I returned to this. I was having an issue still after switching to using import reactHelmetAsync from "react-helmet-async"; When I'm using esbuild, I end up getting an error about there not being a default export. I included a screenshot of how I'm building my app using esbuild with the platform being "browser" and the format being "esm". Before when I had it working with esm.sh, I had platform as "neutral" but that doesn't work with npm specifiers. The only way I could get it to work both in my build and on the server was to do this.
import * as reactHelmetAsync from "react-helmet-async";
const { HelmetProvider, Helmet } = reactHelmetAsync.default ?? reactHelmetAsync;
import * as reactHelmetAsync from "react-helmet-async";
const { HelmetProvider, Helmet } = reactHelmetAsync.default ?? reactHelmetAsync;
But I get a build warning about how default isn't exported.
No description
No description
No description
KyleJune
KyleJune2mo ago
discord shows screenshots poorly, but if you click on them you can see the full screenshots. Basically if I build for the browser with esm, default is undefined. If I do a neutral build, npm specifiers don't work. Seems like I won't be able to workaround this warning. I found a workaround for the esbuild warning.
import * as reactHelmetAsync from "react-helmet-async";
const reactHelmetAsyncFixed = reactHelmetAsync;
const { HelmetProvider, Helmet } = reactHelmetAsyncFixed.default ??
reactHelmetAsync;
import * as reactHelmetAsync from "react-helmet-async";
const reactHelmetAsyncFixed = reactHelmetAsync;
const { HelmetProvider, Helmet } = reactHelmetAsyncFixed.default ??
reactHelmetAsync;
esbuild warns if I do reactHelmetAsync.default, doesn't if I do reactHelmetAsyncFixed.default. I'll just tell users to import Helmet from my module that will re-export it so that it's easier for them to use in their builds.