Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unused import is created when compiling with NGC #21280

Closed
alan-agius4 opened this issue Jan 3, 2018 · 14 comments
Closed

Unused import is created when compiling with NGC #21280

alan-agius4 opened this issue Jan 3, 2018 · 14 comments
Labels
area: compiler Issues related to `ngc`, Angular's template compiler freq2: medium type: confusing
Milestone

Comments

@alan-agius4
Copy link
Contributor

alan-agius4 commented Jan 3, 2018

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[X] Bug report  
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question

Current behavior

Angular Compiler is not stripping out unused inputs for classes that are used solely for type definitions.

import { Component, Input } from "@angular/core";
import { FormControl } from "@angular/forms";

@Component({
   template: ``
})
export class MainComponent  {
  @Input() form: FormControl;
} 

In the output file generated by NGC there is an unused import that is used only for types within the component https://github.com/alan-agius4/angular-ngc-unused-imports/blob/master/ngc-out/main.component.js#L2

import { Component, Input } from "@angular/core";
import { FormControl } from "@angular/forms"; // this is unused
export class MainComponent {
}
MainComponent.decorators = [
    { type: Component, args: [{
                template: ``
            },] },
];
/** @nocollapse */
MainComponent.ctorParameters = () => [];
MainComponent.propDecorators = {
    "form": [{ type: Input },],
};

When using TSC there is no unused import https://github.com/alan-agius4/angular-ngc-unused-imports/blob/master/tsc-out/main.component.js

import * as tslib_1 from "tslib";
import { Component, Input } from "@angular/core";
let MainComponent = class MainComponent {
};
tslib_1.__decorate([
    Input()
], MainComponent.prototype, "form", void 0);
MainComponent = tslib_1.__decorate([
    Component({
        template: ``
    })
], MainComponent);
export { MainComponent };

Expected behavior

The import statement is dropped.

Minimal reproduction of the problem with instructions

https://github.com/alan-agius4/angular-ngc-unused-imports

What is the motivation / use case for changing the behavior?

No unused import is created, As when I generate my library and using rollup to create FESM, this will create an import to the whole dependency example;

import { FormControl } from "@angular/forms";

will be transformed to

import "@angular/forms";

and like this there will be no treeshaking and the bundle size will eventually increase a lot

Environment


Angular version: 5.1.2
TypeScript version: 2.5.3

Other details:
microsoft/TypeScript#17552

@sarunint
Copy link
Contributor

sarunint commented Jan 3, 2018

Rollup should be smart enough to not include @angular/forms. Have you tried running rollup yet?

@alan-agius4
Copy link
Contributor Author

alan-agius4 commented Jan 3, 2018 via email

@alan-agius4 alan-agius4 changed the title Unused import is creating when compiling with NGC Unused import is created when compiling with NGC Jan 3, 2018
@kara kara added the area: core Issues related to the framework runtime label Jan 3, 2018
@ngbot ngbot bot added this to the Backlog milestone Jan 23, 2018
@ngbot ngbot bot modified the milestones: Backlog, needsTriage Feb 26, 2018
@FirstVertex
Copy link

It happens with ElementRef too.
Additional info here

@trotyl
Copy link
Contributor

trotyl commented Jan 4, 2019

This isn't about ngc or tsc, but whether emitDecoratorMetadata set to true. Currently ngc always switch on that option for lib build:

if (transformDecorators) {
// This is needed as a workaround for https://github.com/angular/tsickle/issues/635
// Otherwise tsickle might emit references to non imported values
// as TypeScript elided the import.
options.emitDecoratorMetadata = true;
}

TypeScript can either preserve all type annotation imports or drop them all, there's no smart detection in between, so emitDecoratorMetadata must be used otherwise ctorParameters would be broken. As long as emitDecoratorMetadata used, type annotation imports will all be preserved by TypeScript.

Given all angular packages were marked sideEffects: false, it should have no size impact for final Webpack users. A better solution is rollup/rollup#2593, which will handle sideEffects directly in library build.

@alan-agius4
Copy link
Contributor Author

@trotyl, you are right it's due to emitDecoratorMetadata.

Though for AOT it will result in an unused import since there won't be any decorator metadata, thus ideally the ngc compiler should elide the unused imports since tsc won't do see microsoft/TypeScript#17552

This is not just due to the bundle size, but also the build time, the more modules you include the slower the build is. Though @ngtools/webpack does have a workaround for these usecases https://github.com/angular/angular-cli/blob/master/packages/ngtools/webpack/src/transformers/elide_imports.ts

@hpawe01
Copy link
Contributor

hpawe01 commented Feb 28, 2020

@alan-agius4 thank you for pointing the workaround at @ngtools/webpack. But do you know how do I incorporate this transformer into the default Angular CLI config (without ejecting)?

@alan-agius4
Copy link
Contributor Author

@hpawe01, the CLI already handles this when building the application.

How are you experiencing this issue?

@hpawe01
Copy link
Contributor

hpawe01 commented Feb 28, 2020

@alan-agius4, I have an Angular library (with latest dependencies), that I build with ivy disabled (for npm publishing). The default @angular-devkit/build-ng-packagr:build builder is used.

And when ngc is bundling the project to FESM2015 and FESM5, the warnings appear:

Bundling to FESM2015
WARNING: 'AfterViewInit', 'OnChanges', 'OnInit', 'SimpleChanges', 'HostListener', 'OnDestroy' and 'EmbeddedViewRef' are imported from external module '@angular/core' but never used
WARNING: 'SafeStyle', 'SafeResourceUrl' and 'SafeUrl' are imported from external module '@angular/platform-browser' but never used
...

@pkozlowski-opensource pkozlowski-opensource added area: compiler Issues related to `ngc`, Angular's template compiler and removed area: core Issues related to the framework runtime labels Mar 12, 2020
@Vikki123
Copy link

Was there any fix or workaround for this ?

@guillaume-f
Copy link

Same issue...

Compiling TypeScript sources through ngc Bundling to FESM2015 WARNING: Non-existent export 'BlobFileData' is imported from dist\kernel\esm2015\lib\core\services\file-transfer.service.js WARNING: 'InjectionToken', 'Type', 'OnInit', 'AfterContentInit', 'OnChanges', 'SimpleChanges', 'OnDestroy' and 'EmbeddedViewRef' are imported from external module '@angular/core' but never used WARNING: 'Data', 'Event', 'UrlTree', 'ActivatedRouteSnapshot', 'CanActivate', 'CanActivateChild', 'CanLoad', 'Route', 'RouterStateSnapshot' and 'Routes' are imported from external module '@angular/router' but never used WARNING: 'HttpEvent' is imported from external module '@angular/common/http' but never used WARNING: 'Action' is imported from external module '@ngrx/store' but never used WARNING: 'MenuItem' is imported from external module 'primeng/api' but never used WARNING: 'ControlValueAccessor', 'ValidationErrors' and 'Validator' are imported from external module '@angular/forms' but never used Bundling to FESM5 WARNING: Non-existent export 'BlobFileData' is imported from dist\kernel\esm5\lib\core\services\file-transfer.service.js WARNING: 'InjectionToken', 'Type', 'OnInit', 'AfterContentInit', 'OnChanges', 'SimpleChanges', 'OnDestroy' and 'EmbeddedViewRef' are imported from external module '@angular/core' but never used WARNING: 'Data', 'Event', 'UrlTree', 'ActivatedRouteSnapshot', 'CanActivate', 'CanActivateChild', 'CanLoad', 'Route', 'RouterStateSnapshot' and 'Routes' are imported from external module '@angular/router' but never used WARNING: 'HttpEvent' is imported from external module '@angular/common/http' but never used WARNING: 'Action' is imported from external module '@ngrx/store' but never used WARNING: 'MenuItem' is imported from external module 'primeng/api' but never used WARNING: 'ControlValueAccessor', 'ValidationErrors' and 'Validator' are imported from external module '@angular/forms' but never used

@maxisam
Copy link
Contributor

maxisam commented Apr 4, 2020

The workaround is simply put OnInit etc in a separate import statement.

ng-packagr/ng-packagr#1543 (comment)

@alxhub
Copy link
Member

alxhub commented May 28, 2020

@alan-agius4 I don't think it's feasible for ngc to remove these imports, unfortunately. ngc has zero knowledge of whether imports are consumed or under what circumstances. That information is internal to TypeScript and not exposed to us. Adding the logic to extract it for ourselves would be expensive both in terms of complexity and performance.

The much more practical answer is to not rely on emitDecoratorMetadata, which Ivy in AOT mode does not.

@alan-agius4
Copy link
Contributor Author

alan-agius4 commented May 28, 2020

Agreed and in the CLI we also have a transformer to elide unused imports.

The issue is caused because of a TS issue when using transformers microsoft/TypeScript#17552

@alxhub alxhub closed this as completed May 28, 2020
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Jun 29, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area: compiler Issues related to `ngc`, Angular's template compiler freq2: medium type: confusing
Projects
None yet
Development

No branches or pull requests