Skip to content

Custom typescript transformer source file changes are not applied #16250

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

Closed
2 of 15 tasks
JulianH opened this issue Nov 21, 2019 · 5 comments
Closed
2 of 15 tasks

Custom typescript transformer source file changes are not applied #16250

JulianH opened this issue Nov 21, 2019 · 5 comments

Comments

@JulianH
Copy link

JulianH commented Nov 21, 2019

🐞 Bug report

Command (mark with an x)

  • new
  • build
  • serve
  • test
  • e2e
  • generate
  • add
  • update
  • lint
  • xi18n
  • run
  • config
  • help
  • version
  • doc

Is this a regression?

Yes, the custom transformer worked in angular 7

Description

We are using a custom typescript transformer which is replacing provider tokens in component decorators to enable custom implementations of services depending on the build configuration.

Example:

@Component({
    selector: 'booking-editor',
    template: '...',
    providers: [
        BookingUiService
    ]
})
export class BookingEditorComponent {
  constrcutor(uiService: BookingUiService){}
}

which will be transformed to the following:

@Component({
    selector: 'booking-editor',
    template: '...',
    providers: [
      { provide: BookingUiService, useClass: CustomBookingUiService }
    ]
})
export class BookingEditorComponent {
  constrcutor(uiService: BookingUiService){}
}

This custom transformer we add to the beginning of _transformers array of the AngularCompilerPlugin.

Until the upgrade from Angular 7 to Angular 8, this worked like a charm but now on runtime, the custom implementation is not present, when doing the build with AOT enabled, the JIT build does use the transformed version.

If i dump the modified ts.SourceFile, i can see the applied change as well as another already applied change, the importFactory transformer adds export { ɵ0 }; to the sourceFile, even if i add the custom transformer to the beginning of the _transformers list?

🌍 Your Environment


     _                      _                 ____ _     ___ 
    / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
   / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | | 
  / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | | 
 /_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
                |___/
    

Angular CLI: 8.3.17
Node: 10.13.0
OS: win32 x64
Angular: 8.2.13
... animations, common, compiler, compiler-cli, core, forms     
... language-service, platform-browser, platform-browser-dynamic
... router

Package                           Version
-----------------------------------------------------------     
@angular-devkit/architect         0.803.17
@angular-devkit/build-angular     0.803.17
@angular-devkit/build-optimizer   0.803.17
@angular-devkit/build-webpack     0.803.17
@angular-devkit/core              8.3.17
@angular-devkit/schematics        8.3.17
@angular/cli                      8.3.17
@ngtools/webpack                  8.3.17
@schematics/angular               8.3.17
@schematics/update                0.803.17
rxjs                              6.4.0
typescript                        3.4.5
webpack                           4.41.2
@alan-agius4
Copy link
Collaborator

Hi @JulianH,

The export { ɵ0 }; is added by the NGC compiler. I am not quite sure what is happening here without a reproduction.

That being said it is important to highlight that you are using a private API (_transformers) which in reality it's behaviour might change or be removed without any prior notice.

@ngbot ngbot bot added this to the needsTriage milestone Nov 22, 2019
@JulianH
Copy link
Author

JulianH commented Nov 22, 2019

Hi @alan-agius4,

thank you for the response. Yes i kow, using the private API is not the best option here. But as angular also strongly relies on typescript transformers, i am sure that such an API will be present always :-)

Do you need a repo with the custom transformer for the reproduction of this problem?

Does the NGC compiler also not see the angular internal transformations and works on the unmodified typescript files?

@JulianH
Copy link
Author

JulianH commented Nov 25, 2019

Hi @alan-agius4,

here is the repo to reproduce the problem: https://github.com/JulianH/angular-provider-transformer.

What i've also identified is, that only AOT is affected, with JIT the metadata are still present and used by the compiler to create the correct provider instance:

var AppComponent = /** @class */ (function () {
    function AppComponent(service) {
        this.service = service;
        this.title = 'angular-transformer';
    }
    AppComponent.ctorParameters = function () { return [
        { type: _service1__WEBPACK_IMPORTED_MODULE_3__["Service1"] }
    ]; };
    AppComponent = tslib__WEBPACK_IMPORTED_MODULE_0__["__decorate"]([
        Object(_angular_core__WEBPACK_IMPORTED_MODULE_2__["Component"])({
            selector: 'app-root',
            template: tslib__WEBPACK_IMPORTED_MODULE_0__["__importDefault"](__webpack_require__(/*! raw-loader!./app.component.html */ "./node_modules/raw-loader/dist/cjs.js!./src/app/app.component.html")).default,
            providers: [{
                        provide: _service1__WEBPACK_IMPORTED_MODULE_3__["Service1"],
                        useClass: _service2__WEBPACK_IMPORTED_MODULE_1__["Service2"]
            }]
        })
    ], AppComponent);
    return AppComponent;
}());

The AOT result looks like this:

function View_AppComponent_Host_0(_l) {
	return _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵvid"](0, [
		(_l()(),_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵeld"](0, 0, null, null, 2, "app-root", [], null, null, null, View_AppComponent_0, RenderType_AppComponent)),
		_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵprd"](512, null, _service1__WEBPACK_IMPORTED_MODULE_1__["Service1"], _service1__WEBPACK_IMPORTED_MODULE_1__["Service1"], []),
		_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵdid"](2, 49152, null, 0, _app_component__WEBPACK_IMPORTED_MODULE_2__["AppComponent"], [_service1__WEBPACK_IMPORTED_MODULE_1__["Service1"]], null, null)
	], null, null);
}

It seems, that there is no support for typescript transformers when using the AOT compiler as he is working with StaticSymbols. Is there any chance, to process the result of the AOT to achieve the same result as with a typescript transformer?

Or can you suggest any alternative to us, to replace provider tokens based on an configuration/environment without introducing a lot of cicrular dependencies?

Thank you in advance!

@JulianH
Copy link
Author

JulianH commented Nov 26, 2019

Hello @alan-agius4,

yesterday i spend time to identify how the ivy compilation process is working and identified, that it will be basically impossible for us, to use typescript transformers in the future, which are updating the component decorator metadata.

Therefore we will follow a different approach, to use the already existing environements to export there the provider tokens for the custom services we want to use.

@JulianH JulianH closed this as completed Nov 26, 2019
@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 Dec 27, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants