Open DiegoAndai opened 6 months ago
Hey @huozhi, may I ask you to look into this issue and https://github.com/vercel/next.js/issues/64796? Thanks in advance!
I tried to create a minimal repro, but I couldn't figure it out. I'm sorry about this.
With failed you mean everything worked in minimal repros?
Does it work if you run npm run dev --turbo
?
When testing the libraries on a Next.js app with pages router and esmExternals: false, we get the following error:
And with esmExternals: true
it works?
14.2.x turbopack havent supported esmExternals so it's not able to run it.
The root cause is for pages router, since you disable the esmExternals
it's resolving cjs on server side and client still resolving esm but will barrel optimization on client side. We can probably disable the barrel optimization when esmExternals is false. But it gonna slow down a lot on bundling.
Ideally you shouldn't need to disable esmExternals
option, curious what's reason that makes you disable it?
With failed you mean everything worked in minimal repros?
Yes, I tried to reproduce the issue in a new Next.js app but couldn't.
And with esmExternals: true it works?
Yes, probably because of what @huozhi explained in the comment above.
Ideally you shouldn't need to disable esmExternals option, curious what's reason that makes you disable it?
I agree, but we are not able to use esmExternals: true
because of another longstanding issue 😅: https://github.com/vercel/next.js/issues/49898, which we worked around with esmExternals: false
: https://github.com/vercel/next.js/issues/49898#issuecomment-1762202697. The linked issue is still reproducible in our docs with Next.js 14 and esmExternals: true
Hi!
Any progress on this issue? It is affecting us as well. Thanks!
@DiegoAndai the repro in #49898 is incorrect, it's require a ESM and expect it to be sync. What's the underlaying issue that make you to disable the flag? I think we need to fix that one
@DiegoAndai the repro in https://github.com/vercel/next.js/issues/49898 is incorrect, it's require a ESM and expect it to be sync.
What do you mean by "it's incorrect"?
What's the underlaying issue that make you to disable the flag?
If I disable it, I get the same error that prompted us to create https://github.com/vercel/next.js/issues/49898. This is the error:
⨯ ../packages/mui-icons-material/lib/ArrowDropDownRounded.js (11:30) @ eval
⨯ TypeError: (0 , _createSvgIcon.default) is not a function
at eval (webpack-internal:///../packages/mui-icons-material/lib/ArrowDropDownRounded.js:11:64)
at ../packages/mui-icons-material/lib/ArrowDropDownRounded.js (/Users/diegoandai/MUI/DiegoAndai/material-ui/docs/export/server/pages/_document.js:3703:1)
at __webpack_require__ (/Users/diegoandai/MUI/DiegoAndai/material-ui/docs/export/server/webpack-runtime.js:33:42)
at eval (webpack-internal:///../packages/mui-docs/src/branding/brandingTheme.ts:16:98)
at __webpack_require__.a (/Users/diegoandai/MUI/DiegoAndai/material-ui/docs/export/server/webpack-runtime.js:97:13)
at eval (webpack-internal:///../packages/mui-docs/src/branding/brandingTheme.ts:1:21)
at ../packages/mui-docs/src/branding/brandingTheme.ts (/Users/diegoandai/MUI/DiegoAndai/material-ui/docs/export/server/pages/_document.js:49:1)
at __webpack_require__ (/Users/diegoandai/MUI/DiegoAndai/material-ui/docs/export/server/webpack-runtime.js:33:42)
at eval (webpack-internal:///../packages/mui-docs/src/branding/index.ts:3:72)
at __webpack_require__.a (/Users/diegoandai/MUI/DiegoAndai/material-ui/docs/export/server/webpack-runtime.js:97:13)
at eval (webpack-internal:///../packages/mui-docs/src/branding/index.ts:1:21)
at ../packages/mui-docs/src/branding/index.ts (/Users/diegoandai/MUI/DiegoAndai/material-ui/docs/export/server/pages/_document.js:60:1)
at __webpack_require__ (/Users/diegoandai/MUI/DiegoAndai/material-ui/docs/export/server/webpack-runtime.js:33:42)
at eval (webpack-internal:///./pages/_document.js:21:76)
at __webpack_require__.a (/Users/diegoandai/MUI/DiegoAndai/material-ui/docs/export/server/webpack-runtime.js:97:13) {
page: '/'
}
9 | var _createSvgIcon = _interopRequireDefault(require("./utils/createSvgIcon"));
10 | var _jsxRuntime = require("react/jsx-runtime");
> 11 | var _default = exports.default = (0, _createSvgIcon.default)( /*#__PURE__*/(0, _jsxRuntime.jsx)("path", {
| ^
12 | d: "m8.71 11.71 2.59 2.59c.39.39 1.02.39 1.41 0l2.59-2.59c.63-.63.18-1.71-.71-1.71H9.41c-.89 0-1.33 1.08-.7 1.71"
13 | }), 'ArrowDropDownRounded');
TypeError: (0 , _createSvgIcon.default) is not a function
at eval (webpack-internal:///../packages/mui-icons-material/lib/ArrowDropDownRounded.js:11:64)
at ../packages/mui-icons-material/lib/ArrowDropDownRounded.js (/Users/diegoandai/MUI/DiegoAndai/material-ui/docs/export/server/pages/_document.js:3703:1)
at __webpack_require__ (/Users/diegoandai/MUI/DiegoAndai/material-ui/docs/export/server/webpack-runtime.js:33:42)
at eval (webpack-internal:///../packages/mui-docs/src/branding/brandingTheme.ts:16:98)
at __webpack_require__.a (/Users/diegoandai/MUI/DiegoAndai/material-ui/docs/export/server/webpack-runtime.js:97:13)
at eval (webpack-internal:///../packages/mui-docs/src/branding/brandingTheme.ts:1:21)
at ../packages/mui-docs/src/branding/brandingTheme.ts (/Users/diegoandai/MUI/DiegoAndai/material-ui/docs/export/server/pages/_document.js:49:1)
at __webpack_require__ (/Users/diegoandai/MUI/DiegoAndai/material-ui/docs/export/server/webpack-runtime.js:33:42)
at eval (webpack-internal:///../packages/mui-docs/src/branding/index.ts:3:72)
at __webpack_require__.a (/Users/diegoandai/MUI/DiegoAndai/material-ui/docs/export/server/webpack-runtime.js:97:13)
at eval (webpack-internal:///../packages/mui-docs/src/branding/index.ts:1:21)
at ../packages/mui-docs/src/branding/index.ts (/Users/diegoandai/MUI/DiegoAndai/material-ui/docs/export/server/pages/_document.js:60:1)
at __webpack_require__ (/Users/diegoandai/MUI/DiegoAndai/material-ui/docs/export/server/webpack-runtime.js:33:42)
at eval (webpack-internal:///./pages/_document.js:21:76)
at __webpack_require__.a (/Users/diegoandai/MUI/DiegoAndai/material-ui/docs/export/server/webpack-runtime.js:97:13) {
page: '/'
}
Here's more background: https://github.com/emotion-js/emotion/issues/3032#issuecomment-1550470774.
If you want to test it yourself, I've created a branch for it: https://github.com/DiegoAndai/material-ui/tree/disable-esm-externals-false. So you can
git clone https://github.com/DiegoAndai/material-ui.git
git checkout disable-esm-externals-false
pnpm install
pnpm docs:dev
localhost:3000
and the issue will show.Note that this is still reproducible in next v14.
Thanks in advance for taking a look 😊.
In #49898 's reproduction
There's a file cjs module requiring a ESM module, and they expect the require can get a sync module, which is not correct.
// ./common.js
module.exports = require("./esmish");
// ./esmish.js
export { default as unitless } from "@emotion/unitless";
This would break the module resolving when you expect them to work properly.
Do you know what's the similar case in mui or emotion-js that causes you have to disable esmExternals
? In the future that option might not able to control anymore since the module can resolve properly if they are configured properly in package.json
. That's why I say we don't want you to disable the flag. I'd love to learn more why it makes you do that.
@huozhi from the error I'm getting:
X ../packages/mui-icons-material/lib/ArticleRounded.js (11:30) @ eval
X TypeError: (0 , _createSvgIcon.default) is not a function
The issue seems to be this:
https://github.com/mui/material-ui/blob/next/packages/mui-icons-material/lib/ArticleRounded.js (and similar files) import from https://github.com/mui/material-ui/blob/next/packages/mui-icons-material/lib/utils/createSvgIcon.js, and the default export seems like is not set up properly. This is one instance but we probably have this setup throughout the mui codebase.
Might this be it?
There's a file cjs module requiring a ESM module, and they expect the require can get a sync module, which is not correct.
@huozhi I've been investigating this a little bit, and your comment seems to point in the direction. Our setup involves a monorepo that contains workspaces for a next.js application and packages that are consumed by this application as well as published. Our setup contains some custom webpack configuration to transpile dependent workspaces by combining aliases with the default babel loader:
Inspecting the bundles with esmExternals: false
, this setup produces a sync module (for e.g. @mui/utils
), when this setting is removed, this produces an async module.
Some modules external to the repository also depend on packages from workspace. To make sure on the server they resolve these dependencies to the exact same version as the transpiled ones, they are omitted from the webpack externals as per:
Some of these packages (e.g. @mui/x-data-grid) don't export node.js compatible ESM modules, so it seems like webpack resolves to using their commonjs files. These call sync require
on @mui/utils
and that's where the problem happens.
I'm aware this is a bit of an exotic setup. I'm personally not a huge fan of the complexity, but it has great DX. We need a way out of this situation.
transpilePackages
because our package sources are contained in a src
folder and it doesn't look like there is a way to make import specifiers resolve to a typescript file that isn't adjecent to the js file it would resolve to. Is there a way to make transpilePackages
aware of where it can find TS sources? Does the Next.js team plan to make it possible in some way to make transpilePackages
aware of the TS source location?transpilePackages
to hot reload changes in the Next.js app when the output of the previous changestranspilePackages
respect publishConfig.directory
?
Link to the code that reproduces this issue
https://github.com/DiegoAndai/esm-test-13-nextjs-pages-mui-exports-ts
To Reproduce
npm install
npm run dev
http://localhost:3000
in the browserDescription
We're trying to add the
exports
field to thepackage.json
of MUI core libraries (PR | Docs). This app is using the MUI libraries from the PR build (e.g., https://pkg.csb.dev/mui/material-ui/commit/fb7a4ff2/@mui/material). When testing the libraries on a Next.js app with pages router andesmExternals: false
, we get the following error:Full error
``` ⨯ TypeError: _mui_utils_deepmerge__WEBPACK_IMPORTED_MODULE_3__ is not a function at createPalette (webpack-internal:///./node_modules/@mui/material/styles/createPalette.mjs:266:27) at createTheme (webpack-internal:///./node_modules/@mui/material/styles/createTheme.mjs:47:83) at eval (webpack-internal:///./node_modules/@mui/material/styles/defaultTheme.mjs:7:82) at ./node_modules/@mui/material/styles/defaultTheme.mjs (/Users/diegoandai/MUI/experiments/esm-test-13-nextjs-pages-mui-exports-ts/.next/server/vendor-chunks/@mui.js:260:1) at __webpack_require__ (/Users/diegoandai/MUI/experiments/esm-test-13-nextjs-pages-mui-exports-ts/.next/server/webpack-runtime.js:33:42) at eval (webpack-internal:///./node_modules/@mui/material/styles/styled.mjs:8:75) at ./node_modules/@mui/material/styles/styled.mjs (/Users/diegoandai/MUI/experiments/esm-test-13-nextjs-pages-mui-exports-ts/.next/server/vendor-chunks/@mui.js:310:1) at __webpack_require__ (/Users/diegoandai/MUI/experiments/esm-test-13-nextjs-pages-mui-exports-ts/.next/server/webpack-runtime.js:33:42) at eval (webpack-internal:///./node_modules/@mui/material/Button/Button.mjs:13:77) at ./node_modules/@mui/material/Button/Button.mjs (/Users/diegoandai/MUI/experiments/esm-test-13-nextjs-pages-mui-exports-ts/.next/server/vendor-chunks/@mui.js:20:1) at __webpack_require__ (/Users/diegoandai/MUI/experiments/esm-test-13-nextjs-pages-mui-exports-ts/.next/server/webpack-runtime.js:33:42) at eval (webpack-internal:///./node_modules/@mui/material/Button/index.mjs:6:69) at ./node_modules/@mui/material/Button/index.mjs (/Users/diegoandai/MUI/experiments/esm-test-13-nextjs-pages-mui-exports-ts/.next/server/vendor-chunks/@mui.js:40:1) at __webpack_require__ (/Users/diegoandai/MUI/experiments/esm-test-13-nextjs-pages-mui-exports-ts/.next/server/webpack-runtime.js:33:42) at __barrel_optimize__?names=Button!=!./node_modules/@mui/material/index.mjs (/Users/diegoandai/MUI/experiments/esm-test-13-nextjs-pages-mui-exports-ts/.next/server/pages/index.js:26:75) { page: '/' } GET / 500 in 128ms ```This seems related to default import/export interop between esm and cjs: https://www.typescriptlang.org/docs/handbook/modules/appendices/esm-cjs-interop.html
The expected is for the app to run without erroring.
Provide environment information
Which area(s) are affected? (Select all that apply)
Pages Router
Which stage(s) are affected? (Select all that apply)
next dev (local)
Additional context
14.2.3
,13.5.1
, and13.4.0
.