Tree-shakable providers trigger the Angular compiler to introduce import statements in user's code, which we didn't do before. It turns out we have places where we conflate module paths on disk with module names (earlier versions of the compiler didn't have this distinction)
So we end up writing imports like import {} from 'wksp/packages/path/to/thing'
that should have been import {} from '@pkg_name/path/to/thing'
As far as we know, this issue only affects Bazel users who compile with ngc
and use tree-shakable providers. So far we have only seen this issue internally in Angular.
This was found as part of #20030
To repro, add a tree-shakable provider e.g. paste into packages/common/src/common_module.ts
import {Injectable, PLATFORM_ID} from '@angular/core';
import {DOCUMENT, isPlatformBrowser} from '@angular/common';
export function viewportScrollerFactory(platformId: string, document: any) {
return isPlatformBrowser(platformId) ? null: null;
}
@Injectable(
{providedIn: 'root', useFactory: viewportScrollerFactory, deps: [PLATFORM_ID, DOCUMENT]})
export abstract class ViewportScroller {}
then build the npm package
bazel build //packages/common:npm_package
And look for the string angular/packages
in the output:
$ export bin=$(bazel info bazel-bin)
$ find $bin -type f -exec fgrep -l angular/packages {} \; | grep -v ngsummary | grep -v ngfactory
we remove ngsummary files because these always have had paths on disk as module identifiers.
ngfactory files are not shipped with the package so these are probably harmless too.
Interestingly, we find the bad import in the ES2015 output:
bin/packages/common/src/common_module.closure.js
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import { NgModule } from '@angular/core';
import { COMMON_DIRECTIVES } from './directives/index';
import { DEPRECATED_PLURAL_FN, NgLocaleLocalization, NgLocalization, getPluralCase } from './i18n/localization';
import { COMMON_DEPRECATED_I18N_PIPES } from './pipes/deprecated/index';
import { COMMON_PIPES } from './pipes/index';
import { Injectable, PLATFORM_ID } from '@angular/core';
import { DOCUMENT, isPlatformBrowser } from '@angular/common';
import * as i0 from "@angular/core";
import * as i1 from "@angular/core/src/application_tokens";
import * as i2 from "angular/packages/common/src/dom_tokens"; // <-------------------------
but not in the ES5 output
bin/packages/common/src/common_module.js
(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
}
else if (typeof define === "function" && define.amd) {
define("@angular/common/src/common_module", ["require", "exports", "tslib", "@angular/core", "@angular/common/src/directives/index", "@angular/common/src/i18n/localization", "@angular/common/src/pipes/deprecated/index", "@angular/common/src/pipes/index", "@angular/core", "@angular/common", "@angular/core", "@angular/core/src/application_tokens", "@angular/common/src/dom_tokens"], factory);
}
})(function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var core_1 = require("@angular/core");
var index_1 = require("@angular/common/src/directives/index");
var localization_1 = require("@angular/common/src/i18n/localization");
var index_2 = require("@angular/common/src/pipes/deprecated/index");
var index_3 = require("@angular/common/src/pipes/index");
var core_2 = require("@angular/core");
var common_1 = require("@angular/common");
var i0 = require("@angular/core");
var i1 = require("@angular/core/src/application_tokens");
var i2 = require("@angular/common/src/dom_tokens");
We're running into this issue now too.
We call the compiler API's internally in a mono-repo, this results for us internally also in import paths like :
import * as i1 from "@our-group/our-package/src/some-service";
This happens for us in ES5 output though, but I assume the root cause is similar.
Workarounds for us is defining the factory ourselves in the @Injectable. That stops angular from generating the factory and thus generating the faulty import.
Not sure if I need to provide more info / reproducible:
Most helpful comment
We're running into this issue now too.
We call the compiler API's internally in a mono-repo, this results for us internally also in import paths like :
This happens for us in ES5 output though, but I assume the root cause is similar.
Workarounds for us is defining the factory ourselves in the @Injectable. That stops angular from generating the factory and thus generating the faulty import.
Not sure if I need to provide more info / reproducible: