vercel / next.js

The React Framework
https://nextjs.org
MIT License
126.02k stars 26.88k forks source link

[NEXT-783] ESM file extension pattern not supported #46806

Open Izhaki opened 1 year ago

Izhaki commented 1 year ago

This is very much a revival of the now closed https://github.com/vercel/next.js/issues/41961. Also related: https://github.com/vercel/next.js/discussions/32239

Various packages are now esm-only, PlanetScale's edge-supporting JS driver is one example.

However, since NextJS still uses CJS file naming for relative imports, it is impossible to run tests in NodeJS (say with Cucumber) that consume project scripts that import such esm-only libraries.

Another way to look at it is that despite NextJS's increasing ESM support (and ultimately nobody is using CJS (require) in app code), NextJS relative imports are still written as an ESM/CJS hybrid:

import './someScript'; // `import` is ESM; `./someScript` is CJS.

With Vercel shipping bleeding-edge technology, and esm seen as the de-facto future standard, support for ESM explicit file extension pattern appears to be a looming necessity.

As discussed in https://github.com/vercel/next.js/issues/41961, experimental/fullySpecified is incomplete.

The following diagram depicts the issue (imports must have the .js extension in Node, but that causes NextJS builds to break):

nextjs-esm-only

Provide environment information

Operating System:
      Platform: darwin
      Arch: arm64
      Version: Darwin Kernel Version 21.6.0: Mon Dec 19 20:43:09 PST 2022; root:xnu-8020.240.18~2/RELEASE_ARM64_T6000
    Binaries:
      Node: 18.14.1
      npm: 9.3.1
      Yarn: N/A
      pnpm: 7.25.0
    Relevant packages:
      next: 13.2.3 (13.2.4-canary.4 fails to install atm)
      eslint-config-next: 13.2.3
      react: 18.2.0
      react-dom: 18.2.0

Link to the code that reproduces this issue

https://github.com/Izhaki/nodenextjs-reproduction

To Reproduce

Manual reproduction

/** @type {import('next').NextConfig} */
const config = {
  experimental: {
    fullySpecified: true,
  },
  reactStrictMode: true,
}
export default config;
export default function test() {
  console.log("Test");
}
import test from "@/test.js";

Describe the Bug

App fails to build:

wait  - compiling...
error - ./src/pages/index.tsx:5:0
Module not found: Can't resolve '@/test.js'
  3 | import { Inter } from 'next/font/google'
  4 | import styles from '@/styles/Home.module.css'
> 5 | import test from '@/test.js'
  6 | 
  7 | const inter = Inter({ subsets: ['latin'] })
  8 | 

https://nextjs.org/docs/messages/module-not-found

Expected Behavior

With the fullySpecified flag enabled, both webpack and swc should handle module specifiers with file extensions.

Typescript: As explained in the typescript documentation for ESM support, typescript import will have to be .js and not .ts:

This code works in CommonJS modules, but will fail in ES modules because relative import paths need to use extensions. As a result, it will have to be rewritten to use the extension of the output of foo.ts - so bar.ts will instead have to import from ./foo.js.

However, seeing the required webpack configuration changes in https://github.com/vercel/next.js/issues/41961, possibly a .ts extension will work just fine.

NEXT-783

github-actions[bot] commented 1 year ago

We cannot recreate the issue with the provided information. Please add a reproduction in order for us to be able to investigate.

Why was this issue marked with the please add a complete reproduction label?

To be able to investigate, we need access to a reproduction to identify what triggered the issue. We prefer a link to a public GitHub repository (template), but you can also use a tool like CodeSandbox or StackBlitz.

To make sure the issue is resolved as quickly as possible, please make sure that the reproduction is as minimal as possible. This means that you should remove unnecessary code, files, and dependencies that do not contribute to the issue.

Please test your reproduction against the latest version of Next.js (next@canary) to make sure your issue has not already been fixed.

I added a link, why was it still marked?

Ensure the link is pointing to a codebase that is accessible (e.g. not a private repository). "example.com", "n/a", "will add later", etc. are not acceptable links -- we need to see a public codebase. See the above section for accepted links.

What happens if I don't provide a sufficient minimal reproduction?

Issues with the please add a complete reproduction label that receives no meaningful activity (e.g. new comments with a reproduction link) are automatically closed and locked after 30 days.

If your issue has not been resolved in that time and it has been closed/locked, please open a new issue with the required reproduction.

I did not open this issue, but it is relevant to me, what can I do to help?

Anyone experiencing the same issue is welcome to provide a minimal reproduction following the above steps. Furthermore, you can upvote the issue using the :+1: reaction on the topmost comment (please do not comment "I have the same issue" without reproduction steps). Then, we can sort issues by votes to prioritize.

I think my reproduction is good enough, why aren't you looking into it quicker?

We look into every Next.js issue and constantly monitor open issues for new comments.

However, sometimes we might miss one or two due to the popularity/high traffic of the repository. We apologize, and kindly ask you to refrain from tagging core maintainers, as that will usually not result in increased priority.

Upvoting issues to show your interest will help us prioritize and address them as quickly as possible. That said, every issue is important to us, and if an issue gets closed by accident, we encourage you to open a new one linking to the old issue and we will look into it.

Useful Resources

Izhaki commented 1 year ago

Reproduction added here, the commit with changes atop the base create-next-app is here.