Skip to content

dev-server: export * re-export of a Vite-prebundled dependency breaks — "No matching export" build error, or ReferenceError: <name>_exports is not defined at runtime #33642

Description

@lmullot

Command

serve

Is this a regression?

  • Yes, this behavior used to work in the previous version

The previous version in which this bug was not present was

21.2.17

Description

When a local barrel file re-exports a third-party dependency with export *, and that dependency is prebundled by the dev server's Vite dependency optimizer, esbuild cannot enumerate the dependency's exports. Depending on the shape of the module graph this produces two different failures in ng serve only (ng build is always fine, since it does not use Vite prebundling):

  1. Deterministic build error (minimal repro below): every named import going through the barrel fails with X [ERROR] No matching export in "src/app/tracking/index.ts" for import "init" — although the export exists and the same code builds fine with ng build.
  2. Silent runtime break (observed in a large real-world workspace): the build succeeds, esbuild emits a runtime namespace object for the barrel (var amplitude_exports = {}; __reExport(amplitude_exports, ...)) in a shared chunk and rewrites consumers to (0, amplitude_exports.withAmplitude)(...) — but the entry chunk that uses the namespace does not import it from the shared chunk (it imports the module's init_* function from that same chunk, so the chunk reference itself is correct — only the namespace binding is missing). The app then throws Uncaught ReferenceError: amplitude_exports is not defined on load. Whether the import is emitted or dropped depends on the overall chunk graph: an app with an almost identical setup in another workspace gets the correct import { amplitude_exports } from "/chunk-….js" and works.

Minimal Reproduction

npx @angular/cli@22 new repro --defaults --style=css --ssr=false
cd repro
npm install @amplitude/analytics-browser@2.45.2   # any prebundled dep works

src/app/tracking/index.ts (the barrel):

export * from '@amplitude/analytics-browser';

src/app/app.config.ts (eager consumer):

import { init } from './tracking';

init('dummy-api-key', { autocapture: false });
// ...unchanged appConfig

src/app/app.routes.ts (two lazy consumers):

export const routes: Routes = [
  { path: 'a', loadComponent: () => import('./page-a/page-a').then(m => m.PageA) },
  { path: 'b', loadComponent: () => import('./page-b/page-b').then(m => m.PageB) },
];

src/app/page-a/page-a.ts:

import { Component } from '@angular/core';
import { track } from '../tracking';

@Component({ selector: 'app-page-a', template: '<p>A</p>' })
export class PageA {
  constructor() {
    track('page-a');
  }
}

src/app/page-b/page-b.ts (also imports the barrel dynamically — this makes the failure deterministic):

import { Component } from '@angular/core';
import { setUserId } from '../tracking';

@Component({ selector: 'app-page-b', template: '<p>B</p>' })
export class PageB {
  constructor() {
    setUserId('b');
    void import('../tracking').then(m => m.track('dynamic'));
  }
}

Then:

ng serve
X [ERROR] No matching export in "src/app/tracking/index.ts" for import "init"

    src/app/app.config.ts:4:9:
      4 │ import { init } from './tracking';
        ╵          ~~~~

X [ERROR] No matching export in "src/app/tracking/index.ts" for import "track"
X [ERROR] No matching export in "src/app/tracking/index.ts" for import "setUserId"

Expected behavior

ng serve should behave like ng build: named imports through an export * barrel of a (prebundled) dependency resolve normally, and any runtime namespace object emitted for such a barrel is imported by every chunk that references it.

Workaround

Excluding the dependency from prebundling fixes both variants, because esbuild then sees the dependency's exports statically and needs no runtime namespace:

"serve": {
  "options": {
    "prebundle": { "exclude": ["@amplitude/analytics-browser"] }
  }
}

Exception or Error


Your Environment

Angular CLI       : 22.0.7
Angular           : 22.0.7
Node.js           : 24.18.0
Package Manager   : npm 11.16.0
Operating System  : win32 x64

┌────────────────────────────┬───────────────────┬───────────────────┐
│ Package                    │ Installed Version │ Requested Version │
├────────────────────────────┼───────────────────┼───────────────────┤
│ @angular-devkit/core       │ 22.0.7            │ 22.0.7            │
│ @angular-devkit/schematics │ 22.0.7            │ 22.0.7            │
│ @angular/animations        │ 22.0.7            │ 22.0.7            │
│ @angular/build             │ 22.0.7            │ 22.0.7            │
│ @angular/cdk               │ 22.0.5            │ 22.0.5            │
│ @angular/cli               │ 22.0.7            │ 22.0.7            │
│ @angular/common            │ 22.0.7            │ 22.0.7            │
│ @angular/compiler          │ 22.0.7            │ 22.0.7            │
│ @angular/compiler-cli      │ 22.0.7            │ 22.0.7            │
│ @angular/core              │ 22.0.7            │ 22.0.7            │
│ @angular/forms             │ 22.0.7            │ 22.0.7            │
│ @angular/platform-browser  │ 22.0.7            │ 22.0.7            │
│ @angular/router            │ 22.0.7            │ 22.0.7            │
│ rxjs                       │ 7.8.2             │ 7.8.2             │
│ typescript                 │ 6.0.3             │ 6.0.3             │
│ vitest                     │ 4.1.10            │ 4.1.10            │
│ zone.js                    │ 0.16.2            │ 0.16.2            │
└────────────────────────────┴───────────────────┴───────────────────┘

Anything else relevant?

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions