Closed amitpareek49 closed 3 years ago
Can you provide your package's package.json
file, or at least the portions that refer to the module exports please? It seems you have provided an export that Next tries to consume (that export being /dist/index.modern.js
) but you haven't uploaded that file to NPM.
What are you referring to as "react js projects"? Do you mean Create-React-App?
Hi @rschristian - Thank you for looking into the issue. Yes, for "react js project" I mean any app react based app which is not server side rendered. It could also be a Create-React-App. I have not provided /dist/index.modern.js
. Nextjs is trying to locate the /dist/index.modern.js
file which is not present in the npm module's dist folder. Below are the package json
file contents:
"source": "src/index.ts",
"main": "dist/index.umd.js",
"exports": "./dist/index.modern.js",
"module": "dist/index.module.js",
"unpkg": "dist/index.umd.js",
"scripts": {
"build": "microbundle --sourcemap false && npm run microbundle-standalone",
"microbundle-standalone": "microbundle -o dist/index.min.js --external none --format umd --sourcemap false",
},
"files": [
"dist/index.umd.js"
]
When the below config in package.json
the npm module works for nextjs but not for "Create React App" -
"source": "src/index.ts",
"main": "dist/index.js",
"exports": "./dist/index.modern.js",
"module": "dist/index.module.js",
"unpkg": "dist/index.umd.js",
"scripts": {
"build": "microbundle --sourcemap false && npm run microbundle-standalone",
"microbundle-standalone": "microbundle -o dist/index.min.js --external none --format umd --sourcemap false",
}
"files": [
"dist/index.umd.js",
"dist/index.modern.js",
"dist/index.module.js",
],
It is a strange behaviour as the main file points to index.js
but it is not present in the published dist folder. When I publish the npm module with dist/index.js
file it I get the following error -
<path-to-dist>/dist/index.modern.js:1
SyntaxError: Cannot use import statement outside a module
at wrapSafe (internal/modules/cjs/loader.js:979:16)
at Module._compile (internal/modules/cjs/loader.js:1027:27)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
at Module.load (internal/modules/cjs/loader.js:928:32)
at Function.Module._load (internal/modules/cjs/loader.js:769:14)
What I am basically looking for is that is there a way where just one UMD file would work for nextjs app and create react app (any app not using server side rendering).
Let me know if this information is enough. I can share more info if you need. Thanks in advance.
Well, from build tool to build tool, how package exports are consumed will change. There's a good half-dozen popular tools that use React, all of which can (and do!) consume exports differently. This isn't a client-side React vs server-side React issue. It has nothing to do with React at all, actually. Just the build tool in question.
I have not provided /dist/index.modern.js. Nextjs is trying to locate the /dist/index.modern.js file which is not present in the npm module's dist folder.
Well that'd be an issue. Why do you have exports
set to that path if you're not uploading that file?
<path-to-dist>/dist/index.modern.js:1 SyntaxError: Cannot use import statement outside a module at wrapSafe (internal/modules/cjs/loader.js:979:16) at Module._compile (internal/modules/cjs/loader.js:1027:27) at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10) at Module.load (internal/modules/cjs/loader.js:928:32) at Function.Module._load (internal/modules/cjs/loader.js:769:14)
Is this coming from CRA? The issue is that /dist/index.modern.js
is ESM, but tools will expect it to be CJS by default as you have not set "type": "module"
or the file extension to .mjs
. Without this, CJS is assumed. So CRA tries to load it as if it was CJS, but finds an import statement, which, like the message says, cannot be used outside of a module.
What I am basically looking for is that is there a way where just one UMD file would work for nextjs app and create react app
Why UMD? Neither of these tools at the moment are touching the UMD, if you didn't realize this. Nor should UMD really be the go-to these days.
Include your whole /dist
folder, and then rename index.modern.js
-> index.modern.mjs
. Make sure to update the file path in your pkg.json too. .mjs
specifies that this is a module, so it shouldn't be loaded as if it was CJS
Thank you @rschristian for your prompt reply. I agree that the it is the issue with the build tool not with react at all. I mentioned the details to explain the exact issue that I am seeing right now. So basically you are suggesting the below steps -
exports
from package.json
file.index.modern.js
-> index.modern.mjs
and update main
in package.json to dist/index.modern.mjs
Is this the right understanding? I will try to make changes as per your suggestions.
<path-to-dist>/dist/index.modern.js:1
SyntaxError: Cannot use import statement outside a module
at wrapSafe (internal/modules/cjs/loader.js:979:16)
at Module._compile (internal/modules/cjs/loader.js:1027:27)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
at Module.load (internal/modules/cjs/loader.js:928:32)
at Function.Module._load (internal/modules/cjs/loader.js:769:14)
is coming from nextjs app not from CRA. CRA works fine when dist
folder only exposing the UMD file. Why is the nextjs app expecting the dist/index.modern.js
file but CRA is not.
The reason why I used the UMD file was that same file could be used in both script tag (CDN hosted file) and the npm module.
Thank you for the help :)
So basically you are suggesting the below steps -
No, don't remove "exports"
, just ensure the path it points to exists in your published module and ensure it's a module.
Basically, the way this works is that your export is assumed to be CJS by default with the .js
file extension. You can either set your module type with "type": "module"
so that now the .js
is assumed to be ESM OR you can use the .mjs
extension which is explicitly ESM, regardless of the overall module type. Your index.modern.js
is ESM, but because you've done neither of those two things, NextJS assumes it's CJS and tries to import it as such, but gets confused.
CRA works fine when dist folder only exposing the UMD file. Why is the nextjs app expecting the dist/index.modern.js file but CRA is not.
I'm not a CRA user, so I'd have to check, but what it might be doing is checking to see if the paths exist, otherwise falling back. Don't remove files from being published, that's just not the "workaround" to take away from here, and won't work in most tools. Instead, fix your export paths.
These build tools look at certain keys in your pkg.json to choose which file to read from. Which keys these choose is completely up to them, and there might not be any consistency across any tools. This is just the way it is, though with exports
being standardized, the ecosystem is getting better.
So Next might read "foo"
and CRA could read "bar"
. Point is, they might look for different keys and follow the values you've set for them.
The reason why I used the UMD file was that same file could be used in both script tag (CDN hosted file) and the npm module.
You can use ESM via script tag too, and I'd suggest doing so. Skypack is an ESM CDN, works anywhere you can use <script type="module">
(93% global adoption, according to caniuse)
If your library is open source, if you provide a link I could try to get that working for you.
I get that the CJS + ESM mix along with export maps and various build tool shenanigans isn't a simple thing to jump straight into.
Hopefully this is answered. Let me know if it should be reopened.
Hi Team,
I am trying to build a npm module using microbundle. I have to make it work for both react js (also other front end frameworks) apps and next js apps. However, I am not able to achieve it. Below is the configuration that I am using -
This script generates a "umd" file which is what I am eventually using for npm module in the reactjs based application. The same file doesn't work for nextjs. Issue that I face using using the npm package in nextjs -
When I add the same modern js file in the npm module, it stops working for react js projects.
Is there a generic guidance to make a npm module work for both next js and other standard front end frameworks?