developit / microbundle

📦 Zero-configuration bundler for tiny modules.
https://npm.im/microbundle
MIT License
8k stars 361 forks source link

Using Microbundle package in create-react-app: Webpack errors #1023

Closed sandtreader closed 1 year ago

sandtreader commented 1 year ago

Hi,

I'm having trouble using my microbundle-built package in a standard create-react-app project.

I've created @sandtreader/rafiki using microbundle, and it builds and publishes to npm fine (thanks!).

However when I come to use it in an internal create-react-app, it installs fine but then fails with lots of webpack errors on build / start:

ERROR in ./node_modules/@sandtreader/rafiki/dist/rafiki.modern.js 14:0-37
Module not found: Error: Can't resolve '@mui/material/Button' in '/local/prc/world.management/bridge3/node_modules/@sandtreader/rafiki/dist'
Did you mean 'index.js'?
BREAKING CHANGE: The request '@mui/material/Button' failed to resolve only because it was resolved as fully specified
(probably because the origin is strict EcmaScript Module, e. g. a module with javascript mimetype, a '*.mjs' file, or a '*.js' file where the package.json contains '"type": "module"').
The extension in the request is mandatory for it to be fully specified.
Add the extension to the request.

Now (as through a glass, darkly) I take this to mean that webpack is using the '.modern.js' file but that the imports don't have extensions on them. Here is the import from the published .modern.js:

import v from"@mui/material/Button"

There are quite a few issues around CRA reporting this - it seems to come from a recent webpack update - but their response seems to be it's the package provider's problem - in this case, me :-)

https://github.com/facebook/create-react-app/issues/11865 https://github.com/webpack/webpack/issues/11467#issuecomment-691702706

I have no idea if they are right or not, but if so, could microbundle fully specify the import?

Thanks!

sandtreader commented 1 year ago

Followup - reverting react-scripts to 4.0.3 and hacking round the corresponding OpenSSL error makes this work, so the "webpack got fussier about imports" theory seems to hold water. But I don't want to expose my users to this pain, obviously... :-)

rschristian commented 1 year ago

You have three real options:

but if so, could microbundle fully specify the import?

I'd lean towards no, as it's not really correct usage.

@mui/material ships with nested package.json files in their components, which was the old way to support subpath exports. So import ... from '@mui/material/List' would look to @mui/material/List/package.json for guidance on which file to import, getting a fully resolved path.

However, this is what "exports" replaces, and what modern tooling uses, but @mui/material doesn't ship with it yet (if they ever will). Therefore, your paths are more of a @mui/material + /List sort of thing, which Webpack is telling you isn't a module. If @mui/material had an exports map, stating what @mui/material/List should resolve to, this wouldn't be an issue, but seeing as how they don't, you'll need to make a correction on your side.

Edit: BTW, you should set --jsx + --jsxFragment or --jsxImportSource, no need for both. If you set --jsxImportSource, then --jsx and --jsxFragment are ignored. Should simplify your build command a bit.

sandtreader commented 1 year ago

Thanks great, many thanks for such a fast and accurate response! Using the 'barrel' does indeed work and makes the code a lot neater too!

On the --jsx in the build, I had actually already realised I don't need any of them, although I am still getting errors like:

rpt2: options error TS5089: Option 'jsxFactory' cannot be specified when option 'jsx' is 'react-jsx'.

rschristian commented 1 year ago

Ah, yeah sorry, #988 exists to fix that