Repository: next.js
Issue: [NEXT-783] ESM file extension pattern not supported
Labels: Webpack

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](https://github.com/planetscale/database-js) 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**:

```js
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](https://user-images.githubusercontent.com/880132/222994523-2be1befe-c620-4d18-a87b-624c1a7f2018.jpeg)

### Provide environment information

```bash
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

- Clone https://github.com/Izhaki/nodenextjs-reproduction
- `pnpm dev`
- Go to http://localhost:3000/

#### Manual reproduction

- Create a NextJS app
- Use the following config:

```
/** @type {import('next').NextConfig} */
const config = {
  experimental: {
    fullySpecified: true,
  },
  reactStrictMode: true,
}
export default config;
```

- Create  the following `src/test.js`:

```
export default function test() {
  console.log("Test");
}
```

- Add the following import in `src/pages/index.tsx`:

```
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](https://www.typescriptlang.org/docs/handbook/esm-node.html#type-in-packagejson-and-new-extensions), 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. 

<sub>[NEXT-783](https://linear.app/vercel/issue/NEXT-783/esm-file-extension-pattern-not-supported)</sub>