diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 0c2b7c0f5e..2b08884362 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -455,6 +455,7 @@ # ================================================ /packages/compiler-cli/ngcc/** @angular/fw-ngcc @angular/framework-global-approvers +/aio/content/guide/ngcc.md @angular/fw-ngcc @angular/framework-global-approvers @@ -885,6 +886,7 @@ testing/** @angular/fw-test /aio/content/guide/migration-dynamic-flag.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes /aio/content/guide/migration-injectable.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes /aio/content/guide/migration-localize.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes +/aio/content/guide/migration-module-with-providers.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes # ================================================ diff --git a/aio/content/guide/deprecations.md b/aio/content/guide/deprecations.md index 19d092ce51..c536e19a3e 100644 --- a/aio/content/guide/deprecations.md +++ b/aio/content/guide/deprecations.md @@ -362,6 +362,10 @@ See the [dedicated migration guide for adding missing `@Injectable` decorators]( See the [dedicated migration guide for `$localize`](guide/migration-localize). +{@a module-with-providers} +### Migrating `ModuleWithProviders` + + See the [dedicated migration guide for `ModuleWithProviders`](guide/migration-module-with-providers). {@a removed} diff --git a/aio/content/guide/migration-module-with-providers.md b/aio/content/guide/migration-module-with-providers.md new file mode 100644 index 0000000000..ca77ef09af --- /dev/null +++ b/aio/content/guide/migration-module-with-providers.md @@ -0,0 +1,78 @@ +# `ModuleWithProviders` Migration + +## What does this schematic do? + + +Some Angular libraries, such as `@angular/router` and `@ngrx/store`, implement APIs that return a type called `ModuleWithProviders` (typically via a method named `forRoot()`). +This type represents an `NgModule` along with additional providers. +Angular version 9 deprecates use of `ModuleWithProviders` without an explicitly generic type, where the generic type refers to the type of the `NgModule`. + +This schematic will add a generic type to any `ModuleWithProviders` usages that are missing the generic. +In the example below, the type of the `NgModule` is `SomeModule`, so the schematic changes the type to be `ModuleWithProviders`. + + +**Before** +```ts + +@NgModule({...}) +export class MyModule { + static forRoot(config: SomeConfig): ModuleWithProviders { + return { + ngModule: SomeModule, + providers: [ + {provide: SomeConfig, useValue: config} + ] + }; + } +} + +``` + +**After** + +```ts +@NgModule({...}) +export class MyModule { + static forRoot(config: SomeConfig): ModuleWithProviders { + return { + ngModule: SomeModule, + providers: [ + {provide: SomeConfig, useValue: config } + ] + }; + } +} +``` + +In the rare case that the schematic can't determine the type of `ModuleWithProviders`, you may see the schematic print a TODO comment to update the code manually. + + +## Why is this migration necessary? + +`ModuleWithProviders` has had the generic type since Angular version 7, but it has been optional. +This has compiled because the `metadata.json` files contained all the metadata. +With Ivy, `metadata.json` files are no longer required, so the framework cannot assume that one with the necessary types has been provided. +Instead, Ivy relies on the generic type for `ModuleWithProviders` to get the correct type information. + +For this reason, Angular version 9 deprecates `ModuleWithProviders` without a generic type. +A future version of Angular will remove the default generic type, making an explicit type required. + +## Should I add the generic type when I add new `ModuleWithProviders` types to my application? + +Yes, any time your code references the `ModuleWithProviders` type, it should have a generic type that matches the actual `NgModule` that is returned (for example, `ModuleWithProviders`). + + +## What should I do if the schematic prints a TODO comment? + +The schematic will print a TODO comment in the event that it cannot detect the correct generic for the `ModuleWithProviders` type. +In this case, you'll want to manually add the correct generic to `ModuleWithProviders`. It should match the type of whichever `NgModule` is returned in the `ModuleWithProviders` object. + +## What does this mean for libraries? + +Libraries should add the generic type to any usages of the `ModuleWithProviders` type. + + +## What about applications using non-migrated libraries? + +`ngcc` should transform any non-migrated libraries to generate the proper code. +For more information on `ngcc` see the [ngcc guide](guide/ngcc). diff --git a/aio/content/guide/ngcc.md b/aio/content/guide/ngcc.md new file mode 100644 index 0000000000..586a0f0407 --- /dev/null +++ b/aio/content/guide/ngcc.md @@ -0,0 +1,7 @@ + +# `ngcc` + +## What is `ngcc`? + +The Angular Compatibility Compiler, or `ngcc`, is a process that the CLI automatically runs which compiles all your libraries with Ivy. +This means that even if the libraries your app depends on don't use Ivy, `ngcc` will update them to use Ivy for you. diff --git a/aio/content/navigation.json b/aio/content/navigation.json index 2bcc126d61..a57c609642 100644 --- a/aio/content/navigation.json +++ b/aio/content/navigation.json @@ -744,6 +744,11 @@ "title": "Usage Analytics", "tooltip": "For administrators, guide to gathering usage analytics from your users.", "url": "cli/usage-analytics-gathering" + }, + { + "title": "ngcc", + "tooltip": "Description of the Angular Compatibility Compiler.", + "url": "guide/ngcc" } ] },