-
Notifications
You must be signed in to change notification settings - Fork 28.4k
MDX Plugin String Format resolution doesn't work with ESM plugins with multiple exports #73757
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
Comments
Seems some bundlers (webpack, turbopack) can't import this when the rehype package is passed as a string. Tracking the issue here, but adding the default key also fixes it vercel/next.js#73757 Would appreciate if you could merge + cut a release.
It looks like the issue here is when the package doesn't have a "default" export - see the above PR that fixed it for me. I still think this is a bug though because I could import the package without issue, it only happened when passing a string |
I am getting
with
Along with TS errors. Did you figure it out? |
When using the string format, make sure every entry in the plugin list is an array (not only when you have options) For example, instead of this ( const withMDX = createMDX({
options: {
remarkPlugins: [],
rehypePlugins: ['rehype-slug'],
},
}) you need to put 'rehype-slug' (the plugin string name) into an array: const withMDX = createMDX({
options: {
remarkPlugins: [],
rehypePlugins: [['rehype-slug']],
},
}) meaning that now the plugin entry is an array (that contains the string) and the list of plugins is an array too Note the new loader which adds support for MDX (remark / rehype) plugins (when using tubopack) made its first appearence in @next/mdx 15.1, so if your next.js version is older you need to import plugins instead (or upgrade to @next/mdx 15.1) This typescript types error, @next/mdx is still using the types from the @mdxjs/loader (instead of defining new types in the @next/mdx/js-loader To get rid of this error until the types are fixed, just use a typescript comment to let typescript know it should ignore the problem: const withMDX = createMDX({
options: {
// @ts-ignore wrong types
remarkPlugins: [['remark-gfm', remarkGFMOptions]],
rehypePlugins: [],
},
}) P.S. I have more info regarding mdx (rehype / remark) plugins in combination with turbopack and / or the mdx rust compiler in my next.js 15 mdx tutorial |
It doesn't work when it's in an array form either. I've tried. |
I don't think this is exclusive to MDX resolution. Renaming my next config from |
A couple more example issues referenced above 👆🏻 |
Have a try with experimental: {
mdxRs: true,
} |
Hello 👋 I went on a deep dive with this one in a quest to use emojis from remark-emojis. I ended up just writing a script to do it for me. Would appreciate knowing if I've missed something or followed the wrong thread. 🙂 Having a look, I found three points of failure — one is the known issue of not serializing to a string. TLDR:Next.js cannot work with ES6 packages that contain only 'import' pathways in their 'exports' field of their package.json. This is due to its use of 'require' in two core places. Firstly, what do I mean by import of their exports pathway?Node introduced multiple entry points to modules within the package.json. One reason was to ease the bridge between ES6 modules and CommonJS. We could now specify an entry point to the CommonJS modules as well as to the ES6 modules in one package. To do this, we use the 'exports' field in our package.json to specify which way 'import' should go, which way 'require' should go, and other functionalities or default settings. With packages like remark-emoji, the exports field only specifies an import pathway: "exports": { If there was a default one level higher, then require would go here. Since there isn't, there is no valid entry point for require, which is correct as this package exclusively uses ES6 modules. @wesbos, this is why you see the addition of default in your example working — because require is flowing that way. Ok, but why isn't it happening in Next.js? Next.js seems to support ES6. Bundling Issue with next.config.ts:When bundling using next.config.ts (note the .ts), we encounter: ERR_PACKAGE_PATH_NOT_EXPORTED To replicate, simply write: import emoji from 'remark-emoji'; This error message comes from the resolve-pkg-maps package. This package is a dependency of 'get-tsconfig', which Next.js uses during the configuration process. The error itself arises because the package being imported does not provide a valid entry point for require, which results in the error. To be clear, resolve-pkg-maps works as expected when given the correct conditionals, but somewhere along the flow it is not. The package remark-emoji is also correct, its exports key is valid. Somewhere in the flow however, its being told to use require to retrieve from remark-emoji, leading to the break, as remark-emoji does not posses and exports pathway for require. Switching to next.config.js avoids this issue as we avoid the above flow, allowing import to work as expected. Issue with the MDX Loader:Within the plugin options, we can provide one of two values:The package directly (e.g., import emoji from 'remark-emoji'; then providing emoji). This will break because we encounter the non-serializable issue since the imported plugin is a function. Or just include the name as a string (['remark-emoji']).The problem here is that the MDX loader (next-mdx/mdx-js-loader.js) tries to require the plugin directly, which fails because it attempts to require an ES module without a CommonJS entry point, resulting in: TypeError: Cannot read properties of null (reading 'in') This happens here:
Next Steps
Would love to try and resolve this! Or if I've got something off, please let me know! 😄 This was fun! |
Link to the code that reproduces this issue
https://github.com/wesbos/next-mdx-plugin-string-issue
To Reproduce
When using strings to import a MDX Rehype plugin, the Next.js importer fails.
I believe this is only when the package has multiple ESM exports - like this package: https://github.com/stefanprobst/rehype-extract-toc/blob/main/package.json
Thansk to @karlhorky for linking me to the possible commit / code. CC @timneutkens
https://github.com/vercel/next.js/pull/72802/files#diff-d5904dff78d88856dc003d263e6f70f0a607166230fba8e4b947a3bae5e4e87cR10
We get the Error:
Or
This error does not happen if the plugin is imported inside
next.config.mjs
and passed as a javascript function, but since Turborepo must pass as a string, I cannot do this.The error exists both with and without --turbo.
Current vs. Expected behavior
_
Provide environment information
Operating System: Platform: darwin Arch: arm64 Version: Darwin Kernel Version 24.1.0: Thu Oct 10 21:03:15 PDT 2024; root:xnu-11215.41.3~2/RELEASE_ARM64_T6000 Available memory (MB): 65536 Available CPU cores: 10 Binaries: Node: 23.1.0 npm: 10.9.0 Yarn: 1.22.22 pnpm: 9.10.0 Relevant Packages: next: 15.0.4-canary.51 // Latest available version is detected (15.0.4-canary.51). eslint-config-next: N/A react: 19.0.0-beta-04b058868c-20240508 react-dom: 19.0.0-beta-04b058868c-20240508 typescript: 5.1.3 Next.js Config: output: N/A
Which area(s) are affected? (Select all that apply)
Markdown (MDX)
Which stage(s) are affected? (Select all that apply)
next dev (local)
Additional context
No response
The text was updated successfully, but these errors were encountered: