-
Notifications
You must be signed in to change notification settings - Fork 27.7k
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
next/image not working when using in esm projects #54777
Comments
|
It was working just fine in previous versions of next.js 13. |
@yanush Which specific version was working? |
@devjiwonchoi version 13.3.4 with experimental appDir true was working fine, but I'm not sure whether this version was using the legacy image by default |
Any updates on this matter? |
Interesting, we have a working
|
Workaround 1:
|
So I upgraded the original reproduction to
Seems like a JS compiler bug? Updated reproduction PR here: yanush/nextjs_issue_20230830#1
|
Ah interesting, since this import Image from 'next/image'; // in ESM project with "type": "module" in package.json
console.log('Image', Image);
// Image { unstable_getImgProps: [Getter], default: [Getter] } |
@karlhorky, Thanks for all your suggestions and workaround attempts! |
Just thinking, one way to get compatibility here without a larger CJS -> ESM transition would be to *also* export a named export for these cases. Then the following would "just work" in ESM with import { Image } from 'next/image'; To be clear, for users who want to stay with the default export, the following would still work: import Image from 'next/image'; cc @feedthejim @shuding would the team be open for such a change? (backwards compatible) cc @remcohaszing because we were talking about lacking ESM support in Next.js and using named exports |
While I personally prefer named exports, I also believe there should be only one way to use an export. Adding a named export is a workaround. There is a deeper problem, this issue is just a symptom. Also it affects pretty much all Next.js exports, not just A library (defined as something you import, e.g. What really needs to happen, is that code like this: import React from 'react'
export function unstable_getImgProps() {
// …
}
export interface ImageProps {
// …
}
export default function Image(props: ImageProps): React.ReactElement {
// …
} needs to be transformed to import * as React from 'react'
namespace Image {
export function unstable_getImgProps() {
// …
}
export interface ImageProps {
// …
}
// This is for strict backwards compatibility. It’s not needed for typical Next.js users.
export { Image as default }
}
function Image(props: ImageProps): React.ReactElement {
// …
}
export = Image Or go a step further and enable import React = require('react')
namespace Image {
export function unstable_getImgProps() {
// …
}
export interface ImageProps {
// …
}
// This is for strict backwards compatibility. It’s not needed for typical Next.js users.
export { Image as default }
}
function Image(props: ImageProps): React.ReactElement {
// …
}
export = Image P.s. If Vercel is invested in supporting ESM/TypeScript (which means fixing this), I am for hire to fix this on a freelance contract. |
If this work to make the Are The Types Wrong? by @andrewbranchpublint by @bluwy |
Oh and it would be great if new end to end tests were added to verify continued ESM support as time goes on and new features get added. Ideas for end to end tests:
|
# Description Attempting to fix import issue in Pages router with suggested workaround for ESM projects: vercel/next.js#54777 (comment) <!-- Specify above which issue this fixes by referencing the issue number (`#<ISSUE_NUMBER>`) or issue URL. --> <!-- Example: Fixes https://github.com/colbyfayock/next-cloudinary/issues/<ISSUE_NUMBER> --> ## Type of change <!-- Please select all options that are applicable. --> - [ ] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) - [ ] Fix or improve the documentation - [ ] This change requires a documentation update # Checklist <!-- These must all be followed and checked. --> - [ ] I have followed the contributing guidelines of this project as mentioned in [CONTRIBUTING.md](/CONTRIBUTING.md) - [ ] I have created an [issue](https://github.com/colbyfayock/next-cloudinary/issues) ticket for this PR - [ ] I have checked to ensure there aren't other open [Pull Requests](https://github.com/colbyfayock/next-cloudinary/pulls) for the same update/change? - [ ] I have performed a self-review of my own code - [ ] I have run tests locally to ensure they all pass - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes needed to the documentation
# [5.17.0-beta.1](v5.16.0...v5.17.0-beta.1) (2023-12-22) ### Features * Updates next/image import to dist path ([#388](#388)) ([59ad1ff](59ad1ff)), closes [/github.com/vercel/next.js/issues/54777#issuecomment-1808505837](https://github.com//github.com/vercel/next.js/issues/54777/issues/issuecomment-1808505837)
## What When users specify `"type": "module"` in Next.js app, especially with `create-next-app`, `Image` component is not working. An error `Unsupported Server Component type: {...}` is thrown. ## Why `next/image` API is mixing with a client component as default export and a named export as server component. But the entry file of the API is still CJS file, which will import the module as the object. So you'll get `{ default, unstable_getImageProps }` when you do `import Image from 'next/image'` instead of `Image` component itself, where the CJS module load all the exports as an object. This is expected behavior for ESM but breaks the usage. It only errors when you're using js extensions, if you're using typescript, it still works. If you're using turbopack, it works in dev mode. This is also because webpack can't analyze the exports from CJS module of that `next/image` entry file. Usually we can assign the default export to the module itself, then attach other named exports onto it, so the default export equals the `module.exports` itself. But for `next/image` since the default export is an client component, doing that will error with React as you cannot modify the react client reference. Turbopack doesn't use the same way to analyze the default export, so it doesn't have this problem. ## How We create few ESM version of entry files of nextjs APIs, then pick up them to let app router for bundling, instead of using the `next/<api name>.js` CJS files. Those ESM entries still point to the `next/dist/..` CJS files. In this way webpack and directly gets the exports from the `next/dist/...` files and be aware of the module exports. No more CJS module wrapping the ESM module, the default and named exports can preserve correctly. Fixes #54777 Closes NEXT-1774 Closes NEXT-1879 Closes NEXT-1923
@huozhi thanks for the fix in #59852 I can confirm that Broken with CodeSandbox demo: https://codesandbox.io/p/devbox/esm-js-import-bug-w-next-image-14-0-5-canary-24-773jvq?file=%2Fpnpm-lock.yaml%3A10%2C62 Working with CodeSandbox demo: https://codesandbox.io/p/devbox/esm-js-import-bug-w-next-image-14-0-5-canary-25-x58yz8?file=%2Fpnpm-lock.yaml%3A10%2C62 |
## What When users specify `"type": "module"` in Next.js app, especially with `create-next-app`, `Image` component is not working. An error `Unsupported Server Component type: {...}` is thrown. ## Why `next/image` API is mixing with a client component as default export and a named export as server component. But the entry file of the API is still CJS file, which will import the module as the object. So you'll get `{ default, unstable_getImageProps }` when you do `import Image from 'next/image'` instead of `Image` component itself, where the CJS module load all the exports as an object. This is expected behavior for ESM but breaks the usage. It only errors when you're using js extensions, if you're using typescript, it still works. If you're using turbopack, it works in dev mode. This is also because webpack can't analyze the exports from CJS module of that `next/image` entry file. Usually we can assign the default export to the module itself, then attach other named exports onto it, so the default export equals the `module.exports` itself. But for `next/image` since the default export is an client component, doing that will error with React as you cannot modify the react client reference. Turbopack doesn't use the same way to analyze the default export, so it doesn't have this problem. ## How We create few ESM version of entry files of nextjs APIs, then pick up them to let app router for bundling, instead of using the `next/<api name>.js` CJS files. Those ESM entries still point to the `next/dist/..` CJS files. In this way webpack and directly gets the exports from the `next/dist/...` files and be aware of the module exports. No more CJS module wrapping the ESM module, the default and named exports can preserve correctly. Fixes vercel#54777 Closes NEXT-1774 Closes NEXT-1879 Closes NEXT-1923
This closed issue has been automatically locked because it had no new activity for 2 weeks. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you. |
Verify canary release
Provide environment information
Operating System: Platform: darwin Arch: arm64 Version: Darwin Kernel Version 22.5.0: Thu Jun 8 22:22:20 PDT 2023; root:xnu-8796.121.3~7/RELEASE_ARM64_T6000 Binaries: Node: 18.17.1 npm: 9.6.7 Yarn: N/A pnpm: N/A Relevant Packages: next: 13.4.20-canary.12 eslint-config-next: 13.4.19 react: 18.2.0 react-dom: 18.2.0 typescript: 5.2.2 Next.js Config: output: N/A
Which area(s) of Next.js are affected? (leave empty if unsure)
No response
Link to the code that reproduces this issue or a replay of the bug
https://github.com/yanush/nextjs_issue_20230830
To Reproduce
npx create-next-app@latest
Using the following options:
TypeScript: No
EsLint: Yes
Tailwind CSS: No
src/ directory: No
App Router: Yes
import Alias: No
Edit package.json and add:
"type": "module",
Edit next.config.js file to match esm:
Describe the Bug
I get these errors:
Warning: React.jsx: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object.
Check your code at page.js:19.
Warning: React.jsx: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object.
The errors referring to lines that contain Image Tags
Notice:
Using the legacy Image works fine (Changing page.js import to:
import Image from 'next/legacy/image'
)Changing the project to commonjs also seems to solve the issue
Both of these fixes are not ideal for me
Expected Behavior
Should be working fine with the new image and don't throw errors
Which browser are you using? (if relevant)
No response
How are you deploying your application? (if relevant)
No response
NEXT-1774
The text was updated successfully, but these errors were encountered: