APP_INITIALIZER in library causes "Lambda not supported" error
Asked Answered
F

2

8

When defining an APP_INITIALIZER in a library module, the build fails with the Lambda not supported error. The build error is thrown when the function is exported as per docs:

import { NgModule, APP_INITIALIZER } from '@angular/core';
import { MylibComponent } from './mylib.component';

export function myLibInit() {
  return () => console.log('Hi from exported function');
}

@NgModule({
  providers: [
    {
      provide: APP_INITIALIZER,
      multi: true,
      useFactory: myLibInit
    }
  ]
})
export class MylibModule { }

The build error is thrown in both dev and prod.

I have alternatively also tried defining the factory function using ES6 object method shorthand notation:

import { NgModule, APP_INITIALIZER } from '@angular/core';
import { MylibComponent } from './mylib.component';

@NgModule({
  providers: [
    {
      provide: APP_INITIALIZER,
      multi: true,
      useFactory() {
        return () => console.log('Hi from ES6 object method shorthand')
      }
    }
  ]
})
export class MylibModule { }

This passes both the dev and prod build, but the app throws the ERROR TypeError: this.appInits[r] is not a function error at runtime when the library and app is built with the prod flag.

How does one correctly use the APP_INITIALIZER in a library and not get build or runtime errors?

A reproduction can be found here:

  1. git clone https://github.com/samherrmann/angular-sandbox.git
  2. cd angular-sandbox
  3. git checkout lambda-not-supported
  4. npm install
  5. npm run build

GitHub issue regarding this problem can be found here.

Florin answered 22/8, 2018 at 23:58 Comment(0)
E
15

What I understand is that while compiling, the typescript compiler tries to resolve as much as it can.

So when you are doing it like this:

export function myLibInit() {
  return () => console.log('Hi from exported function');
}

It tries to resolve it to simply () => console.log('Hi from exported function'); because nothing else is being done in the function.

Now, let us make the function do a little more:

export function myLibInit() {
  var x = 2+2; //let us just do something to keep this original function
  return () => console.log('Hi from exported function');
}

This one compiles without error, because it is not returning the only and exactly lamda function.

Also the below one works as well because there is an extra assignment.

export function myLibInit() {
  var x = () => console.log('Hi from exported function');
  return x;
}

You can of course return a promise.

I did see your links to some tutorials and they are doing exactly what you have problem with and I think they are probably old or not done with the version of angular you are working. Because documentation clearly states that

"The compiler does not currently support function expressions or lambda functions. "

And they are doing somewhat similar to that. One reason could be that they actually never performed the build because it doesn't give you error on ng serve

I can see that they have closed your issue on github but I think they should review it because of my above explanation.

Eel answered 23/8, 2018 at 1:18 Comment(3)
wow!... I confirmed that assigning the inner function to a variable before returning it does indeed work. I don't understand though why does an inline return (the way I had it) work in the app project but not in a library? How is the compilation between an app and a library different? There are even inline returns within Angular itself.Florin
I have found another open GitHub issue that tracks this inconsistent behavior.Florin
The kind of inline return within angular you have pointed out is probably something you can do as well. It is within Promise. But even if it works or not, I think it is a bug and should be fixed. Or at least there should be some more explanation of it.Eel
H
0

Try using this code sample above your function myLibInit(). See this for more info.

/**
 * @dynamic
 */
Hogwash answered 3/3, 2021 at 17:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.