system-ui / theme-ui

Build consistent, themeable React apps based on constraint-based design principles
https://theme-ui.com
MIT License
5.31k stars 673 forks source link

Theme UI provider import causes an ESM error when mdx-js/react is subsequently required #2023

Closed johno closed 2 years ago

johno commented 2 years ago

Describe the bug

MDX v2 switches to ESM, but Theme UI's cjs file is imported during Next's SSR, which causes an error. I'm not entirely sure if this is a bug in Theme UI or Next, but a direct @mdx-js/react import doesn't cause an error. So, it seems like something to do with the preconstruct build during Next's SSR, maybe? Result of it being a second level dependency?

error - Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /Users/johno-mini/c/repro-mdx-v2-theme-ui/node_modules/@mdx-js/react/index.js
require() of ES modules is not supported.
require() of /Users/johno-mini/c/repro-mdx-v2-theme-ui/node_modules/@mdx-js/react/index.js from /Users/johno-mini/c/repro-mdx-v2-theme-ui/node_modules/@theme-ui/mdx/dist/theme-ui-mdx.cjs.dev.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.
Instead rename index.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from /Users/johno-mini/c/repro-mdx-v2-theme-ui/node_modules/@mdx-js/react/package.json.

To Reproduce

Steps to reproduce the behavior:

  1. Go to https://github.com/johno/repro-mdx-v2-theme-ui
  2. Follow steps in readme

Expected behavior

I'd expect Theme UI's ESM modules to be imported which will ensure no error is caused when the MDX import occurs. And it should be ESM files rather than cjs.

johno commented 2 years ago

I also tried experimental.esmExternals = true in next.config.js which resulted in a slightly different error.

error - Error [ERR_REQUIRE_ESM]: require() of ES Module /Users/johno-mini/c/repro-mdx-v2-theme-ui/node_modules/@mdx-js/react/index.js from /Users/johno-mini/c/repro-mdx-v2-theme-ui/node_modules/@theme-ui/mdx/dist/theme-ui-mdx.cjs.dev.js not supported.
Instead change the require of index.js in /Users/johno-mini/c/repro-mdx-v2-theme-ui/node_modules/@theme-ui/mdx/dist/theme-ui-mdx.cjs.dev.js to a dynamic import() which is available in all CommonJS modules.
Error [ERR_REQUIRE_ESM]: require() of ES Module /Users/johno-mini/c/repro-mdx-v2-theme-ui/node_modules/@mdx-js/react/index.js from /Users/johno-mini/c/repro-mdx-v2-theme-ui/node_modules/@theme-ui/mdx/dist/theme-ui-mdx.cjs.dev.js not supported.
Instead change the require of index.js in /Users/johno-mini/c/repro-mdx-v2-theme-ui/node_modules/@theme-ui/mdx/dist/theme-ui-mdx.cjs.dev.js to a dynamic import() which is available in all CommonJS modules.
    at Object.<anonymous> (/Users/johno-mini/c/repro-mdx-v2-theme-ui/node_modules/@theme-ui/mdx/dist/theme-ui-mdx.cjs.dev.js:9:15)
    at Object.<anonymous> (/Users/johno-mini/c/repro-mdx-v2-theme-ui/node_modules/@theme-ui/mdx/dist/theme-ui-mdx.cjs.js:6:20)
    at Object.<anonymous> (/Users/johno-mini/c/repro-mdx-v2-theme-ui/node_modules/theme-ui/dist/theme-ui.cjs.dev.js:7:11)
    at Object.<anonymous> (/Users/johno-mini/c/repro-mdx-v2-theme-ui/node_modules/theme-ui/dist/theme-ui.cjs.js:6:20)
    at Object.theme-ui (/Users/johno-mini/c/repro-mdx-v2-theme-ui/.next/server/pages/_app.js:42:18)
    at __webpack_require__ (/Users/johno-mini/c/repro-mdx-v2-theme-ui/.next/server/webpack-runtime.js:33:42)
    at eval (webpack-internal:///./pages/_app.js:7:66)
    at Object../pages/_app.js (/Users/johno-mini/c/repro-mdx-v2-theme-ui/.next/server/pages/_app.js:22:1)
    at __webpack_require__ (/Users/johno-mini/c/repro-mdx-v2-theme-ui/.next/server/webpack-runtime.js:33:42)
    at __webpack_exec__ (/Users/johno-mini/c/repro-mdx-v2-theme-ui/.next/server/pages/_app.js:52:39)
    at /Users/johno-mini/c/repro-mdx-v2-theme-ui/.next/server/pages/_app.js:53:28
    at Object.<anonymous> (/Users/johno-mini/c/repro-mdx-v2-theme-ui/.next/server/pages/_app.js:56:3)
    at Object.requirePage (/Users/johno-mini/c/repro-mdx-v2-theme-ui/node_modules/next/dist/server/require.js:48:12)
    at Object.loadComponents (/Users/johno-mini/c/repro-mdx-v2-theme-ui/node_modules/next/dist/server/load-components.js:57:23)
    at DevServer.findPageComponents (/Users/johno-mini/c/repro-mdx-v2-theme-ui/node_modules/next/dist/server/next-server.js:1233:63)
    at DevServer.findPageComponents (/Users/johno-mini/c/repro-mdx-v2-theme-ui/node_modules/next/dist/server/dev/next-dev-server.js:660:26)
    at async DevServer.renderErrorToResponse (/Users/johno-mini/c/repro-mdx-v2-theme-ui/node_modules/next/dist/server/next-server.js:1702:26)
    at async pipe.req.req (/Users/johno-mini/c/repro-mdx-v2-theme-ui/node_modules/next/dist/server/next-server.js:1670:30)
    at async DevServer.pipe (/Users/johno-mini/c/repro-mdx-v2-theme-ui/node_modules/next/dist/server/next-server.js:1148:25)
    at async DevServer.run (/Users/johno-mini/c/repro-mdx-v2-theme-ui/node_modules/next/dist/server/dev/next-dev-server.js:446:24)
    at async DevServer.handleRequest (/Users/johno-mini/c/repro-mdx-v2-theme-ui/node_modules/next/dist/server/next-server.js:320:20) {
  code: 'ERR_REQUIRE_ESM'
}
ckeeney commented 2 years ago

Is there a known workaround for this? I don't use MDX so I tried just not requiring @mdx-js/react in my package.json, but that didn't work, theme-ui complained about the missing module.

ckeeney commented 2 years ago

Downgrading mdx-js to version 1.6 solved this issue for me.

johno commented 2 years ago

I'm inclined to think that Theme UI should go all in on ESM here and use something like tsup to build the packages rather than Preconstruct's faux-ESM.

Since Theme UI is an MDX user and MDX itself has gone all in on ESM - it's likely time to rip off the bandaid. Right now a fresh install of Theme UI, MDX, and Next.js effectively fails since it brings in MDX v2.

The other option is to rip out MDX and implement an API that folks can leverage to connect Theme UI and MDX. An API might look something like the following:

import { useMDXComponents } from 'theme-ui'

// ...

const components = useMDXComponents()

// ...

return <MDXProvider components={components} />
mryechkin commented 2 years ago

@johno +1 to that proposed API approach, keeps the pattern consistent with @mdx-js/react usage

web-programmer-here commented 2 years ago

Is there a fix for this? Using "@mdx-js/react": "^1.6.22", gives dependency error with react 18

npm install
npm ERR! code ERESOLVE
npm ERR! ERESOLVE could not resolve
npm ERR! 
npm ERR! While resolving: @mdx-js/react@1.6.22
npm ERR! Found: react@18.2.0
npm ERR! node_modules/react
npm ERR!   react@"18.2.0" from the root project
npm ERR!   peer react@">=16.8.0" from @emotion/react@11.10.0
npm ERR!   node_modules/@emotion/react
npm ERR!     @emotion/react@"^11.10.0" from the root project
npm ERR!     peer @emotion/react@"^11" from @theme-ui/color-modes@0.14.7
npm ERR!     node_modules/@theme-ui/color-modes
npm ERR!       @theme-ui/color-modes@"0.14.7" from @theme-ui/theme-provider@0.14.7
npm ERR!       node_modules/@theme-ui/theme-provider
npm ERR!         @theme-ui/theme-provider@"0.14.7" from theme-ui@0.14.7
npm ERR!         node_modules/theme-ui
npm ERR!       1 more (theme-ui)
npm ERR!     6 more (@theme-ui/components, @theme-ui/core, @theme-ui/css, ...)
npm ERR!   16 more (@theme-ui/color-modes, @theme-ui/components, ...)
npm ERR! 
npm ERR! Could not resolve dependency:
npm ERR! peer react@"^16.13.1 || ^17.0.0" from @mdx-js/react@1.6.22
npm ERR! node_modules/@mdx-js/react
npm ERR!   @mdx-js/react@"^1.6.22" from the root project
npm ERR!   peer @mdx-js/react@"^1 || ^2" from @theme-ui/mdx@0.14.7
npm ERR!   node_modules/@theme-ui/mdx
npm ERR!     @theme-ui/mdx@"0.14.7" from @theme-ui/theme-provider@0.14.7
npm ERR!     node_modules/@theme-ui/theme-provider
npm ERR!       @theme-ui/theme-provider@"0.14.7" from theme-ui@0.14.7
npm ERR!       node_modules/theme-ui
npm ERR!     1 more (theme-ui)
npm ERR! 
npm ERR! Conflicting peer dependency: react@17.0.2
npm ERR! node_modules/react
npm ERR!   peer react@"^16.13.1 || ^17.0.0" from @mdx-js/react@1.6.22
npm ERR!   node_modules/@mdx-js/react
npm ERR!     @mdx-js/react@"^1.6.22" from the root project
npm ERR!     peer @mdx-js/react@"^1 || ^2" from @theme-ui/mdx@0.14.7
npm ERR!     node_modules/@theme-ui/mdx
npm ERR!       @theme-ui/mdx@"0.14.7" from @theme-ui/theme-provider@0.14.7
npm ERR!       node_modules/@theme-ui/theme-provider
npm ERR!         @theme-ui/theme-provider@"0.14.7" from theme-ui@0.14.7
npm ERR!         node_modules/theme-ui
npm ERR!       1 more (theme-ui)
npm ERR! 
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force, or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
hasparus commented 2 years ago

@web-programmer-here, use --legacy-peer-deps for now as a workaround until a new version of Theme UI is released.

web-programmer-here commented 2 years ago

@hasparus thanks, that fixed my issue, is there an eta for theme ui update to fix this issue? thanks

LekoArts commented 2 years ago

FYI, we'll be releasing a new major of gatsby-plugin-mdx on August 16 with support for MDX v2: https://github.com/gatsbyjs/gatsby/pull/35650

I haven't tried https://github.com/LekoArts/mdx-v2-example with Theme UI yet to see if there any compat issues, just wanted to put this on y'all radar.

lachlanjc commented 2 years ago

Great news @johno! Our latest develop release fixes this issue thanks to @hasparus. Just forked your test repo & updated deps, it's working: https://github.com/lachlanjc/repro-mdx-v2-theme-ui/commit/5990f8e1c093e27493777e66df9f080f6d2deb1e

johno commented 2 years ago

Awesome @lachlanjc and @hasparus, thanks! Y'all rock!