ngcc: doesn’t process library prefixed exports properly

🐞 bug report

Affected Package

The issue is caused by package @angular/compiler-cli, package where ngcc belongs.

Is this a regression?

No, this is the first time we’re trying to upgrade from Angular 8 to 9.


We have 30+ Angular Libraries released with Angular v8 right now.
Upgrading the websites from v8 to v9, ngcc throws exceptions from the compiled files of our libraries (__ivy_ngcc__/fesm2015/app.js). The exceptions are related to Injectables consumed from our /common library.

The issue is that we export our Services with the company prefix,
and ngcc is not compiling the libraries properly missing such prefix and not finding the Service.
I will go deep in the exception to illustrate the problem.

🔥 Exception or Error

ERROR in ./node_modules/@company/services/__ivy_ngcc__/fesm2015/app.js 7920:148-166
"export 'HttpService' (imported as 'ɵngcc1') was not found in '@company/common'

ERROR in ./node_modules/@company/forms/__ivy_ngcc__/fesm2015/app.js 11190:272-294
"export 'PhoneNumberPipe' (imported as 'ɵngcc3') was not found in '@company/common'

Where node_modules/@company/services/__ivy_ngcc__/fesm2015/app.js has:

import * as ɵngcc0 from '@angular/core';
import * as ɵngcc1 from '@myndmanagement/common';

(function () { ɵngcc0.ɵsetClassMetadata(ChargeCodeService, [{
        type: Injectable
    }], function () { return [{ type: ɵngcc1.HttpService }]; }, null); })();

but ɵngcc1.HttpService does not exists, it should be PrefixHttpService.

Looking at node_modules/@company/services/fesm2015/app.js it seems ok:

import { PrefixHttpService } from '@company/common';
ChargeCodeService.decorators = [
    { type: Injectable }
/** @nocollapse */
ChargeCodeService.ctorParameters = () => [
    { type: MyndHttpService }
export { ChargeCodeService as PrefixChargeCodeService };

Then Ivy’s compiler is removing the Prefix for some reason 🙁
the library’s index.d.ts correctly maps them as:

export {
  CommandsService as PrefixCommandsService,
  HttpService as PrefixHttpService,
} from './services/index';

🔬 Minimal Reproduction

I will provide enough details to show the problem, as a reproduction is complicated right now.
I can mount a reproduction the next weekend if it’s required.

🌍 Your Environment

Angular Version:

Angular CLI: 9.1.12
Node: 10.18.0
OS: linux x64

Angular: 9.1.12
... animations, cli, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... router, service-worker
Ivy Workspace: Yes

Package                           Version
@angular-devkit/architect         0.901.12
@angular-devkit/build-angular     0.901.12
@angular-devkit/build-optimizer   0.901.12
@angular-devkit/build-webpack     0.901.12
@angular-devkit/core              9.1.12
@angular-devkit/schematics        9.1.12
@angular/cdk                      9.2.4
@angular/flex-layout              9.0.0-beta.31
@angular/pwa                      0.901.12
@ngtools/webpack                  9.1.12
@schematics/angular               9.1.12
@schematics/update                0.901.12
rxjs                              6.5.5
typescript                        3.8.3
webpack                           4.42.0

Anything else relevant?

@gkalpak I’ve seen some PRs from you fixing re-exports, and this topic seems related to your work.
Could you give us a hand here please? thanks in advance!!

1 possible answer(s) on “ngcc: doesn’t process library prefixed exports properly

  1. @gkalpak your failing test was almost perfect. There was just a minor typo in the export aliases:

    class Foo {}
    export Foo as Bar;

    should be

    class Foo {}
    export {Foo as Bar};

    Now (for me) it is failing (as expected) with

    Expected 'shared-lib/index' to be 'shared-lib'.


    Expected 'Foo' to be 'Qux'.

    (although I think we actually mean Baz not Qux)