Repository: next.js
Issue: [NEXT-638] Next.js in a monorepo does not include file referenced in code
Labels: bug,TypeScript,linear: next

### Verify canary release

- [X] I verified that the issue exists in the latest Next.js canary release

### Provide environment information

```
Operating System:
      Platform: linux
      Arch: x64
      Version: #66~20.04.1-Ubuntu SMP Wed Jan 25 09:41:30 UTC 2023
    Binaries:
      Node: 19.0.1
      npm: 8.19.2
      Yarn: 1.22.17
      pnpm: 7.24.2
    Relevant packages:
      next: 13.1.7-canary.17
      eslint-config-next: N/A
      react: 18.2.0
      react-dom: 18.2.0
```

### Which area(s) of Next.js are affected? (leave empty if unsure)

_No response_

### Link to the code that reproduces this issue

https://github.com/millsp/nextjs-monorepo-file-not-found

### To Reproduce

- Clone the provided reproduction repository
- Follow steps in `README` of each branch
- There are two branches:
    1. [A JS-based code branch](https://github.com/millsp/nextjs-monorepo-file-not-found/tree/js)
    Which shows the described bug and how the workaround fixes it
    2. [A TS-based code branch](https://github.com/millsp/nextjs-monorepo-file-not-found/tree/ts)
    Which shows the described bug and how the workaround is broken

### Describe the Bug

An unexpected file not found error happens from an imported package that reads from the local file system (using Next.js in a monorepo).

In this monorepo, I have a package called `service` and another one called `file-reader`. Here’s the representation of the project:

```
.
├── packages
│   ├── file-reader
│   │   ├── index.js
│   │   ├── node_modules
│   │   ├── package.json
│   │   └── file.txt
│   └── service
│       ├── next.config.js
│       ├── next-env.d.ts
│       ├── node_modules
│       ├── package.json
│       └── pages
│           └── api
│               └── test.js
├── pnpm-workspace.yaml
└── README.md
```

`service` needs to use `file-reader`, and `file-reader` needs to read `file.txt`, but running the code with `next build` or `next dev`, and opening the API endpoint, we will then encounter an `ENOENT: no such file or directory` error:

```
Server Error
Error: ENOENT: no such file or directory, open '/nextjs-monorepo-notfound/packages/service/.next/server/pages/api/file.txt'
```

#### Analysis why this is happening

Since `v13.1.7-canary.11` (which included https://github.com/vercel/next.js/pull/45864), the result of `pnpm exec next build` includes the `file.txt` in the correct location:

```
.next/standalone
├── node_modules
├── package.json
└── packages
    ├── file-reader
    │   ├── file.txt
    │   ├── index.js
    │   └── package.json
    └── service
        ├── .env
        ├── .next
        │   └── server
        │       ├── pages
        │       │   ├── api 
        │       │   │   ├── test.js // this bundle includes `file-reader`
        │       │   │   └── test.js.nft.json
        ├── package.json
        └── server.js
```

(Before `v13.1.7-canary.11` that was not the case and you had to use `outputFileTracingRoot: "../../"` manually to make it work - thanks @ijjk for that timely fix!).

So why is the file still not found when executing the code, although it is included directly?

Our current understanding is that because there is a bundling step, `file-reader` will get bundled as the API endpoint (or as a `chunk`). However, the files this bundle is looking for (here `file.txt`) are not present right next to it. Remember, `file-reader` wants to open a file called `file.txt` and expects it to be near its `index.js`. 

So for this to work, we would need to have a tree like this instead:

```diff
.next/standalone
├── node_modules
├── package.json
└── packages
    ├── file-reader
    │   ├── file.txt
    │   ├── index.js
    │   └── package.json
    └── service
        ├── .env
        ├── .next
        │   └── server
        │       ├── pages
        │       │   ├── api
+       │       │   │   ├── file.txt
        │       │   │   ├── test.js // this bundle includes `file-reader`
        │       │   │   └── test.js.nft.json
        ├── package.json
        └── server.js
```

#### Our attempt at finding a workaround

We tried marking `file-reader` as external:

```js
webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
   config.externals = [...config.externals, 'file-reader']
   return config
},
```

This works perfectly when your codebase is JS-only, but breaks completely as soon as you use TypeScript. Because marking as external skips the Next.js transpilation step, then we end up with new errors instead:

```
Server Error
SyntaxError: Cannot use import statement outside a module

This error happened while generating the page. Any console logs will be displayed in the terminal window.

/nextjs-monorepo-notfound/packages/file-reader/index.ts:1
import path from 'path'
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at Object.compileFunction (node:vm:360:18)
```

(We have also tried `transpilePackages` in this context, but that didn’t have any effect)

This shows how bundling is causing these path issues.

### Expected Behavior

Next.js should include the files so they are found at runtime, and the user does not get an error. 

In other words, Next.js should be able to understand how to copy the correct files near the generated bundles and include these in their respective `nft.json` files for a valid `standalone` build.

### Why does Prisma care

In short, this also affects Prisma Client. Instead of the `file-reader` in the reproduction, this would be a generated Prisma Client. It includes a `schema.prisma` and a Query Engine file that live next to its code. When you run your app, the `schema.prisma` is not found. We have many issues about this:

[https://github.com/prisma/prisma/issues/12853](https://github.com/prisma/prisma/issues/12853)
[https://github.com/prisma/prisma/issues/12921](https://github.com/prisma/prisma/issues/12921)
[https://github.com/prisma/prisma/issues/12588](https://github.com/prisma/prisma/issues/12588)
[https://github.com/prisma/prisma/issues/13233](https://github.com/prisma/prisma/issues/13233)
[https://github.com/prisma/prisma/issues/12823](https://github.com/prisma/prisma/issues/12823)
[https://github.com/prisma/prisma/issues/14566](https://github.com/prisma/prisma/issues/14566)
[https://github.com/prisma/prisma/issues/17687](https://github.com/prisma/prisma/issues/17687)

And these issues are full with related, but slightly different, reports of the same problem. 

After some research, we figured out that what they all shared was that they are using Next.js in a monorepo context — and then could understand and reproduce the problem without Prisma as well. That became our reproduction above.

For the Prisma Client to work well in a Next.js app in a monorepo context, we need to find a solution for that problem, and ideally not a workaround.

### Which browser are you using? (if relevant)

_No response_

### How are you deploying your application? (if relevant)

_No response_

<sub>[NEXT-638](https://linear.app/vercel/issue/NEXT-638/nextjs-in-a-monorepo-does-not-include-file-referenced-in-code)</sub>