Repository: next.js
Issue: Optimizing barrel file import from local workspace packages does not work with optimizePackageImports and turbopack
Labels: Performance,Turbopack,linear: turbopack

### Link to the code that reproduces this issue

https://github.com/PMudra/reproduction-app-optimize-package-imports-npm-workspaces

### To Reproduce

1. Install packages in root of workspace: `npm install`.
2. Start the application:
   1. `cd packages/frontend`
   2. `npm run dev -- --turbopack`
3. Inspect the page using your browser dev tools. The "Sources" and "Coverage" tabs are helpful.

### Current vs. Expected behavior

#### Example

In my example project, I am using npm workspaces to organize a Next.js app with a library "my-lib". The folders are like this:

```
├── packages
│   ├── frontend
│   │   ├── app
│   │   │   ├── favicon.ico
│   │   │   ├── layout.tsx
│   │   │   └── page.tsx
│   │   ├── next.config.ts
│   │   ├── next-env.d.ts
│   │   ├── package.json
│   │   └── tsconfig.json
│   └── my-lib
│       ├── featureA.js
│       ├── featureB.js
│       ├── index.js
│       └── package.json
├── package.json
├── package-lock.json
└── README.md
```

The Next.js app `frontend` depends on `my-lib`. When running `npm install`, a symlink is created in `node_modules` folder by npm like so: `node_modules/my-lib -> ../packages/my-lib`.

`my-lib` has 2 modules: `featureA` and `featureB`. The next.js app currently only uses `featureA` which is imported using the barrel file in `index.js`. `my-lib` looks like this:

```ts
// featureA.js
export function featureA() {
  console.log("featureA");
}
```

```ts
// featureB.js
export function featureB() {
  console.log("featureA");
}
```

```ts
// index.js (barrel file)
export * from "./featureA";
export * from "./featureB";
```

`page.tsx` looks like this:

```ts
"use client";
import { featureA } from "my-lib";

export default function Home() {
  featureA();
  return null;
}
```

```ts
// next.config.ts
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  /* config options here */
  reactStrictMode: true,

  experimental: {
    optimizePackageImports: ["my-lib"],
  }
};
export default nextConfig;

```

#### Current behavior

When inspecting which files are loaded, I can currently observe that `featureA` and `featureB` are being loaded:

![Image](https://github.com/user-attachments/assets/b35421b7-7338-4494-a2ab-4f29985655d5)

#### Expected behavior

I would expect that specifying `optimizePackageImports: ["my-lib"]` would prevent the `featureB` module to be loaded by the browser.

The result should look like as if im importing from `import { featureA } from "my-lib/featureA";`:

![Image](https://github.com/user-attachments/assets/2561d110-a2a7-467a-87e5-1b888f44fe72)

### Provide environment information

```bash
Operating System:
  Platform: linux
  Arch: x64
  Version: #14-Ubuntu SMP PREEMPT_DYNAMIC Sat Nov 30 23:51:51 UTC 2024
  Available memory (MB): 63439
  Available CPU cores: 16
Binaries:
  Node: 22.13.0
  npm: 10.9.2
  Yarn: N/A
  pnpm: 10.0.0
Relevant Packages:
  next: 15.2.0-canary.18 // Latest available version is detected (15.2.0-canary.18).
  eslint-config-next: N/A
  react: 19.0.0
  react-dom: 19.0.0
  typescript: 5.7.3
Next.js Config:
  output: N/A
```

### Which area(s) are affected? (Select all that apply)

Developer Experience, Performance, Turbopack

### Which stage(s) are affected? (Select all that apply)

next dev (local)

### Additional context

- My example is a very minimal reproduction of the repository I am working on. We have multiple apps and multiple (generated) libraries and we want to make use of `optimizePackageImports` because performance in dev mode is starting to be a pain.
- Everything seems to be working as expected when using webpack.
- The deprecated option `modularizeImports` seems to be working, too. But setting that up in my real repo seems to be complicated.
- I suspect symlinks to be the cause of the issue. When I manually copy `my-lib/` into `node_modules/my-lib`, the optimization seems to work fine.
- I am having the same issue using pnpm which uses symlinks, too. I haven't tried yarn.

There are some workarounds. All of them are not satisfying. Are there better ones?

- Use webpack.
- Don't import from barrel files.
- Move away from the monorepo.
- Use deprecated `modularizeImports`.

Related issues:

- https://github.com/vercel/next.js/issues/48748
- https://github.com/vercel/next.js/issues/54708

Thanks for looking into this and let me know if you need more information.