forked from angular/angular.io
-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathngmodule-faq.jade
1174 lines (881 loc) · 49.8 KB
/
ngmodule-faq.jade
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
block includes
include ../_util-fns
:marked
**Angular Modules** help organize an application into cohesive blocks of functionality.
The [Angular Modules chapter](../guide/ngmodule.html) covers the concepts and takes you step by step
from the most elementary `@NgModule` to a multi-faceted sample with lazy loaded modules.
_This_ chapter answers the questions many developers ask about Angular Module design and implementation.
.alert.is-important
:marked
These FAQs assume that you have already read the [Angular Module](../guide/ngmodule.html) chapter.
:marked
Declarations
* [What classes should I add to _declarations_?](#q-what-to-declare)
* [What is a _declarable_?](#q-declarable)
* [What classes should I *not* add to _declarations_?](#q-what-not-to-declare)
* [Why list the same component in multiple _NgModule_ properties?](#q-why-multiple-mentions)
* [What does "_Can't bind to 'x' since it isn't a known property of 'y'_" mean?](#q-why-cant-bind-to)
Imports
* [What should I import?](#q-what-to-import)
* [Should I import _BrowserModule_ or _CommonModule_?](#q-browser-vs-common-module)
* [What if I import the same module twice?](#q-reimport)
Exports
* [What should I export?](#q-what-to-export)
* [What should I *not* export?](#q-what-not-to-export)
* [Can I re-export imported classes and modules?](#q-re-export)
* [What is the _forRoot_ method?](#q-for-root)
Service Providers
* [Why is a service provided in a feature module visible everywhere?](#q-module-provider-visibility)
* [Why is a service provided in a _lazy loaded_ module visible only to that module?](#q-lazy-loaded-module-provider-visibility)
* [What if two modules provide the _same_ service?](#q-module-provider-duplicates)
* [How do I restrict service scope to a module?](#q-component-scoped-providers)
* [Should I add app-wide providers to the root _AppModule_ or the root _AppComponent_?](#q-root-component-or-module)
* [Should I add other providers to a module or a component?](#q-component-or-module)
* [Why is it bad if _SharedModule_ provides a service to a lazy loaded module?](#q-why-bad)
* [Why does lazy loading create a child injector?](#q-why-child-injector)
* [How can I tell if a module or service was previously loaded?](#q-is-it-loaded)
Entry Components
* [What is an _entry component_?](#q-entry-component-defined)
* [What is the difference between a _bootstrap_ component and an _entry component_?](#q-bootstrap_vs_entry_component)
* [When do I add components to _entryComponents_?](#q-when-entry-components)
* [Why does Angular need _entryComponents_?](#q-why-entry-components)
General
* [What kinds of modules should I have and how should I use them?](#q-module-recommendations)
* [What's the difference between Angular and JavaScript Modules?](#q-ng-vs-js-modules)
* [What is a "template reference"?](#q-template-reference)
* [How does Angular find components, directives, and pipes in a template?](#q-template-reference)
* [What is the Angular Compiler?](#q-angular-compiler)
* [Can you summarize the _NgModule_ API?](#q-ngmodule-api)
.l-hr
a#q-what-to-declare
.l-main-section
:marked
### What classes should I add to _declarations_?
Add [declarable](#q-declarable) classes — components, directives, and pipes — to a `declarations` list.
These classes must be declared in _exactly one_ module of the application.
Declare them in _this_ module if they _belong_ to this module.
.l-hr
a#q-declarable
.l-main-section
:marked
### What is a _declarable_?
_Declarables_ are the class types — components, directives, and pipes —
that you can add to a module's `declarations` list.
They're the _only_ classes that you can add to `declarations`.
.l-hr
a#q-what-not-to-declare
.l-main-section
:marked
### What classes should I _not_ add to _declarations_?
Only [declarable](#q-declarable) classes can be added to a module's `declarations` list.
Do *not* declare
* a class that is already declared in another module, whether an app module, @angular module, or 3rd party module
* an array of directives imported from another module.
For example, do not declare FORMS_DIRECTIVES from `@angular/forms`.
* module classes
* service classes
* non-Angular classes and objects such as
strings, numbers, functions, entity models, configurations, business logic, and helper classes.
.l-hr
a#q-why-multiple-mentions
.l-main-section
:marked
### Why list the same component in multiple _NgModule_ properties?
We often see `AppComponent` listed in both `declarations` and `bootstrap`.
We might see `HeroComponent` listed in `declarations`, `exports`, and `entryComponents`.
That _feels_ redundant but these properties have different functions
and we can't infer that membership in one list implies membership in another list.
* `AppComponent` could be declared in this module but not bootstrapped.
* `AppComponent` could be bootstrapped in this module but declared in a different feature module.
* `HeroComponent` could be imported from another app module (so we can't declare it) and re-exported by this module.
* `HeroComponent` could be exported for inclusion in an external component's template and also dynamically loaded in a pop-up dialog.
.l-hr
a#q-why-cant-bind-to
.l-main-section
:marked
### What does "_Can't bind to 'x' since it isn't a known property of 'y'_" mean?
This error usually means either that you neglected to declare the directive "x"
or you haven't imported the module to which "x" belongs.
For example, if "x" is `ngModel`, you probably haven't imported the `FormsModule` from `@angular/forms`.
Perhaps you declared "x" in an application sub-module but forgot to export it?
The "x" class won't be visible to other modules until you add it to the `exports` list.
.l-hr
a#q-what-to-import
.l-main-section
:marked
### What should I import?
Import modules whose public (exported) [declarable classes](#q-declarable)
you need to reference in this module's component templates.
This invariably means importing `CommonModule` from `@angular/common` for access to
the Angular directives such as `NgIf` and `NgFor`.
You can import it directly or from another module that [re-exports](#q-reexport) it.
Import `FormsModule` from `@angular/forms`
if your components have `[(ngModel)]` two-way binding expressions.
Import _shared_ and _feature_ modules when this module's components incorporate their
components, directives, and pipes.
Only [import _BrowserModule_](#q-browser-vs-common-module) in the root `AppModule`.
.l-hr
a#q-browser-vs-common-module
.l-main-section
:marked
### Should I import _BrowserModule_ or _CommonModule_?
The **root application module** (`AppModule`) of almost every browser application
should import `BrowserModule` from `@angular/platform-browser`.
`BrowserModule` provides services that are essential to launch and run a browser app.
`BrowserModule` also re-exports `CommonModule` from `@angular/common`
which means that component in the `AppModule` module also have access to
the Angular directives every app needs such as `NgIf` and `NgFor`.
_Do not import_ `BrowserModule` in any other module.
*Feature modules* and *lazy loaded modules* should import `CommonModule` instead.
They need the common directives. They don't need to re-install the app-wide providers.
.l-sub-section
:marked
`BrowserModule` throws an error if you try to lazy load a module that imports it.
:marked
Importing `CommonModule` also frees feature modules for use on _any_ target platform, not just browsers,
a fact of some interest to authors of cross-platform libraries.
.l-hr
a#q-reimport
.l-main-section
:marked
### What if I import the same module twice?
That's not a problem. When three modules all import Module 'A',
Angular evaluates Module 'A' once, the first time it encounters it, and does not do so again.
That's true at whatever level `A` appears in a hierarchy of imported modules.
When Module 'B' imports Module 'A', Module 'C' imports 'B', and Module 'D' imports `[C, B, A]`,
then 'D' triggers the evaluation of 'C' which triggers the evaluation of 'B' which evaluates 'A'.
When Angular gets to the 'B' and 'A' in 'D', they're already cached and ready to go.
Angular does not like modules with circular references so don't let Module 'A' import Module 'B' which imports Module 'A'.
.l-hr
a#q-what-to-export
.l-main-section
:marked
### What should I export?
Export [declarable](#q-declarable) classes that components in _other_ modules
should be able to reference in their templates. These are your _public_ classes.
If you don't export a class, it stays _private_, visible only to other component
declared in this module.
You _can_ export any declarable class — components, directives, and pipes —
whether it is declared in this module or in an imported module.
You _can_ re-export entire imported modules which effectively re-exports all of their exported classes.
A module can even export a module that it doesn't import.
.l-hr
a#q-what-not-to-export
.l-main-section
:marked
### What should I *not* export?
Do *not* export
* Private components, directives, and pipes that you need only within components declared in this module.
If you don't want another module to see it, don't export it.
* Non-declarable objects such as services, functions, configurations, entity models, etc.
* Components that are only loaded dynamically by the router or by bootstrapping.
Such [entry components](#q-entry-component-defined) can never be selected in another component's template.
There's no harm in exporting them but no benefit either.
* Pure service modules that don't have public (exported) declarations.
For example, there is no point in re-exporting `HttpModule` because it doesn't export anything.
It's only purpose is to add http service providers to the application as a whole.
.l-hr
a#q-reexport
a#q-re-export
.l-main-section
:marked
### Can I re-export classes and modules?
Absolutely!
Modules are a great way to selectively aggregate classes from other modules and
re-export them in a consolidated, convenience module.
A module can re-export entire modules which effectively re-exports all of their exported classes.
Angular's own `BrowserModule` exports a couple of modules like this:
code-example.
exports: [CommonModule, ApplicationModule]
:marked
A module can export a combination of its own declarations, selected imported classes, and imported modules.
.l-sub-section
:marked
Don't bother re-exporting pure service modules.
Pure service modules don't export [declarable](#q-declarable) classes that another module could use.
For example, there is no point in re-exporting `HttpModule` because it doesn't export anything.
It's only purpose is to add http service providers to the application as a whole.
.l-hr
a#q-for-root
.l-main-section
:marked
### What is the _forRoot_ method?
The `forRoot` static method is a convention that makes it easy for developers to configure the module's provider(s).
The `RouterModule.forRoot` method is a good example.
Apps pass a `Routes` object to `RouterModule.forRoot` in order to configure the app-wide `Router` service with routes.
`RouterModule.forRoot` returns a [ModuleWithProviders](../api/core/index/ModuleWithProviders-interface.html).
We add that result to the `imports` list of the root `AppModule`.
.alert.is-important
:marked
Only call and import a `.forRoot` result in the root application module, `AppModule`.
Importing it in any other module, particularly in a lazy loaded module,
is contrary to the intent and is likely to produce a runtime error.
:marked
`RouterModule` also offers a `forChild` static method for configuring the routes of lazy loaded modules.
**_forRoot_** and **_forChild_** are conventional names for methods that
configure services in root and feature modules respectively.
Angular doesn't recognize these names but Angular developers do.
Follow this convention when you write similar modules with configurable service providers.
.l-hr
a#q-module-provider-visibility
.l-main-section
:marked
### Why is a service provided in a feature module visible everywhere?
Providers listed in the `@NgModule.providers` of a bootstrapped module have **application scope**.
Adding a service provider to `@NgModule.providers` effectively publishes the service to the entire application.
When we import a module,
Angular adds the module's service providers (the contents of its `providers` list)
to the application _root injector_.
This makes the provider visible to every class in the application that knows the provider's lookup token.
This is by design.
Extensibility through module imports is a primary goal of the Angular module system.
Merging module providers into the application injector
makes it easy for a module library to enrich the entire application with new services.
By adding the `HttpModule` once, every application component can make http requests.
However, this can feel like an unwelcome surprise if you are expecting the module's services
to be visible only to the components declared by that feature module.
If the `HeroModule` provides the `HeroService` and the root `AppModule` imports `HeroModule`,
any class that knows the `HeroService` _type_ can inject that service,
not just the classes declared in the `HeroModule`.
.l-hr
a#q-lazy-loaded-module-provider-visibility
.l-main-section
:marked
### Why is a service provided in a lazy loaded module visible only to that module?
Unlike providers of the modules loaded at launch,
providers of lazy loaded modules are *module-scoped*.
When the Angular router lazy-loads a module, it creates a new execution context.
That [context has its own injector](#q-why-child-injector "Why Angular creates a child injector") which is a direct child of the application injector.
The router adds the lazy module's providers and the providers of its imported modules to this child injector.
These providers are insulated from changes to application providers with the same lookup token.
When the router creates a component within the lazy loaded context,
Angular prefers service instances created from these providers to the service instances of the application root injector.
.l-hr
a#q-module-provider-duplicates
.l-main-section
:marked
### What if two modules provide the _same_ service?
When two imported modules, loaded at the same time, list a provider with the same token,
the second module's provider "wins". That's because both providers are added to the same injector.
When Angular looks to inject a service for that token,
it creates and delivers the instance created by the second provider.
_Every_ class that injects this service gets the instance created by the second provider.
Even classes declared within the first module get the instance created by the second provider.
_This can be an unwelcome surprise_.
If Module A provides a service for token 'X' and imports a module B
that also provides a service for token 'X', then Module A's service definition "wins".
The service provided by the root `AppModule` takes precedence over services provided by imported modules.
The `AppModule` always wins.
.l-hr
a#q-component-scoped-providers
.l-main-section
:marked
### How do I restrict service scope to a module?
When a module is loaded at application launch,
its `@NgModule.providers` have ***application-wide scope***.
They are available for injection throughout the application.
Imported providers are easily replaced by providers from another imported module.
Such replacement may be by design. It could be unintentional and have adverse consequences.
.alert.is-important
:marked
As a general rule, import modules with providers _exactly once_, preferably in the application's _root module_.
That's also usually the best place to configure, wrap, and override them.
:marked
Suppose a module requires a customized `HttpBackend` that adds a special header for all Http requests.
If another module elsewhere in the application also customizes `HttpBackend`
or merely imports the `HttpModule`, it could override this module's `HttpBackend` provider,
losing the special header. The server will reject http requests from this module.
.alert.is-important
:marked
Avoid this problem by importing the `HttpModule` only in the `AppModule`, the application _root module_.
:marked
If you must guard against this kind of "provider corruption", *don't rely on a launch-time module's `providers`.*
Load the module lazily if you can.
Angular gives a [lazy-loaded module](#q-lazy-loaded-module-provider-visibility) its own child injector.
The module's providers are visible only within the component tree created with this injector.
If you must load the module eagerly, when the application starts,
***provide the service in a component instead.***
Continuing with the same example, suppose the components of a module truly require a private, custom `HttpBackend`.
Create a "top component" that acts as the root for all of the module's components.
Add the custom `HttpBackend` provider to the top component's `providers` list rather than the module's `providers`.
Recall that Angular creates a child injector for each component instance and populates the injector
with the component's own providers.
When a child of this component _asks_ for the `HttpBackend` service,
Angular provides the local `HttpBackend` service,
not the version provided in the application root injector.
Child components will make proper http requests no matter what other modules do to `HttpBackend`.
Be sure to create module components as children of this module's top component.
You can embed the child components in the top component's template.
Alternatively, make the top component a routing host by giving it a `<router-outlet>`.
Define child routes and let the router load module components into that outlet.
.l-hr
a#q-root-component-or-module
.l-main-section
:marked
### Should I add app-wide providers to the root _AppModule_ or the root _AppComponent_?
.alert.is-helpful
:marked
Register application-wide providers in the root `AppModule`, not in the `AppComponent`.
:marked
Lazy-loaded modules and their components can inject `AppModule` services;
they cannot inject `AppComponent` services.
Register a service in `AppComponent` providers _only_ if the service must be hidden
from components outside the `AppComponent` tree. This is a rare exceptional use case.
More generally, [prefer registering providers in modules](#q-component-or-module) to registering in components.
#### **_Discussion_:**
Angular registers all startup module providers with the application root injector.
The services created from root injector providers are available to the entire application.
They are _application-scoped_.
Certain services (e.g., the `Router`) only work when registered in the application root injector.
By contrast, Angular registers `AppComponent` providers with the `AppComponent`'s own injector.
`AppComponent`services are available only to that component and its component tree.
They are _component-scoped_.
The `AppComponent`'s injector is a _child_ of the root injector, one down in the injector hierarchy.
That is _almost_ the entire application for apps that don't use the router.
But "almost" isn't good enough for routed applications.
`AppComponent` services don't exist at the root level where routing operates.
Lazy loaded modules can't reach them.
In the Angular Module Chapter sample applications, if we had registered `UserService` in the `AppComponent`,
the `HeroComponent` couldn't inject it.
The application would fail the moment a user navigated to "Heroes".
.l-hr
a#q-component-or-module
.l-main-section
:marked
### Should I add other providers to a module or a component?
In general, prefer registering feature-specific providers in modules (`@NgModule.providers`)
to registering in components (`@Component.providers`).
Register a provider with a component when you _must_ limit the scope of a service instance
to that component and its component tree.
Apply the same reasoning to registering a provider with a directive.
For example, a hero editing component that needs a private copy of a caching hero service should register
the `HeroService` with the `HeroEditorComponent`.
Then each new instance of the `HeroEditorComponent` gets its own cached service instance.
The changes that editor makes to heroes in its service do not touch the hero instances elsewhere in the application.
[Always register _application-wide_ services with the root `AppModule`](q-root-component-or-module),
not the root `AppComponent`.
.l-hr
a#q-why-bad
.l-main-section
:marked
### Why is it bad if _SharedModule_ provides a service to a lazy loaded module?
This question arose in the [Angular Module](../guide/ngmodule.html#no-shared-module-providers) chapter
when we discussed the importance of keeping providers out of the `SharedModule`.
Suppose we had listed the `UserService` in the module's `providers` (which we did not).
Suppose every module imports this `SharedModule` (which they all do).
When the app starts, Angular eagerly loads the `AppModule` and the `ContactModule`.
Both instances of the imported `SharedModule` would provide the `UserService`.
Angular registers one of them in the root app injector (see [above](#q-reimport)).
Then some component injects `UserService`, Angular finds it in the app root injector,
and delivers the app-wide singleton `UserService`. No problem.
Now consider the `HeroModule` _which is lazy loaded!_
When the router lazy loads the `HeroModule`, it creates a child injector and registers the `UserService`
provider with that child injector. The child injector is _not_ the root injector.
When Angular creates a lazy `HeroComponent`, it must inject a `UserService`.
This time it finds a `UserService` provider in the lazy module's _child injector_
and creates a _new_ instance of the `UserService`.
This is an entirely different `UserService` instance
than the app-wide singleton version that Angular injected in one of the eagerly loaded components.
That's almost certainly a mistake.
.l-sub-section
:marked
Prove it for yourself.
Run the <live-example name="ngmodule">live example</live-example>.
Modify the `SharedModule` so that it provides the `UserService` rather than the `CoreModule`.
Then toggle between the "Contact" and "Heroes" links a few times.
The username goes bonkers as the Angular creates a new `UserService` instance each time.
.l-hr
a#q-why-child-injector
.l-main-section
:marked
### Why does lazy loading create a child injector?
Angular adds `@NgModule.providers` to the application root injector ... unless the module is lazy loaded.
Then it creates a _child injector_ and adds the module's providers to the child injector.
This means that a module behaves differently depending on whether it is loaded during application start
or lazy loaded later. Neglecting that difference can lead to [adverse consequences](#q-why-bad).
Why doesn't Angular add lazy loaded providers to the app root injector as it does for eagerly loaded modules?
Why the inconsistency?
The answer is grounded in a fundamental characteristic of the Angular dependency injection system.
An injector can add providers _until it is first used_.
Once an injector starts creating and delivering services, its provider list is frozen. No new providers allowed.
When an applications starts, Angular first configures the root injector with the providers of all eagerly loaded modules
_before_ creating its first component and injecting any of the provided services.
Once the application begins, the app root injector is closed to new providers.
Time passes. Application logic triggers lazy loading of a module.
Angular must add the lazy loaded module's providers to an injector _somewhere_.
It can't added them to the app root injector because that injector is closed to new providers.
So Angular creates a new child injector for the lazy loaded module context.
.l-hr
a#q-is-it-loaded
.l-main-section
:marked
### How can I tell if a module or service was previously loaded?
Some modules and its services should only be loaded once by the root `AppModule`.
Importing the module a second time by lazy loading a module could [produce errant behavior](#q-why-bad)
that may be difficult to detect and diagnose.
We can guard against that danger by writing a constructor that attempts to inject the module or service
from the root app injector. If the injection succeeds, the class has been loaded a second time.
We can throw an error or take other remedial action.
Certain Angular modules (such as `BrowserModule`) implements such a guard
as does this Angular Module chapter sample's `CoreModule` constructor.
+makeExample('ngmodule/ts/app/core/core.module.ts', 'ctor', 'app/core/core.module.ts (Constructor)')(format='.')
:marked
.l-hr
a#q-entry-component-defined
.l-main-section
:marked
### What is an _entry component_?
Any component that Angular loads _imperatively_ by type is an _entry component_,
A component loaded _declaratively_ via its selector is _not_ an entry component.
Most application components are loaded declaratively.
Angular uses the component's selector to locate the element in the template.
It then creates the HTML representation of the component and inserts it into the DOM at the selected element.
These are not entry components.
A few components are only loaded dynamically and are _never_ referenced in a component template.
The bootstrapped root `AppComponent` is an _entry component_.
True, its selector matches an element tag in `index.html`.
But `index.html` is not a component template and the `AppComponent`
selector doesn't match an element in any component template.
Angular loads `AppComponent` dynamically either because we listed it _by type_ in `@NgModule.bootstrap`
or because we boostrapped it imperatively with the module's `ngDoBootstrap` method.
Components in route definitions are also _entry components_.
A route definition refers to a component by its _type_.
The router ignores a routed component's selector (if it even has one) and
loads the component dynamically into a `RouterOutlet`.
The compiler can't discover these _entry components_ by looking for them in other component templates.
We must tell it about them ... by adding them to the `entryComponents` list.
Angular automatically adds two kinds of components to the module's `entryComponents`:
1. the component in the `@NgModule.bootstrap` list
1. components referenced in router configuration
We don't have to mention these components explicitly although it does not harm to do so.
.l-hr
a#q-bootstrap_vs_entry_component
.l-main-section
:marked
### What's the difference between a _bootstrap_ component and an _entry component_?
A bootstrapped component _is_ an [entry component](#q-entry-component-defined).
It's an entry component that Angular loads into the DOM during the bootstrap (application launch) process.
Other entry components are loaded dynamically by other means such as with the router.
The `@NgModule.bootstrap` property tells the compiler _both_ that this is an entry component _and_
that it should generate code to bootstrap the application with this component.
There is no need to list a component in both the `bootstrap` and `entryComponent` lists
although it is harmless to do so.
.l-hr
a#q-when-entry-components
.l-main-section
:marked
### When do I add components to _entryComponents_?
Most application developers won't need to add components to the `entryComponents`.
Angular adds certain components to _entry components_ automatically.
Components listed in `@NgModule.bootstrap` are added automatically.
Components referenced in router configuration are added automatically.
These two mechanisms account for almost all entry components.
If your app happens to bootstrap or dynamically load a component _by type_ in some other manner,
you'll have to add it to `entryComponents` explicitly.
Although it's harmless to add components to this list,
it's best to add only the components that are truly _entry components_.
Don't include components that [are referenced](#q-template-reference)
in the templates of other components.
.l-hr
a#q-why-entry-components
.l-main-section
:marked
### Why does Angular need _entryComponents_?
_Entry components_ are also declared.
Why doesn't the Angular compiler generate code for every component in `@NgModule.declarations`?
Then we wouldn't need entry components.
The reason is _tree shaking_. For production apps we want to load the smallest, fastest code possible.
The code should contain only the classes that we actually need.
It should exclude a component that's never used, whether or not that component is declared.
In fact, many libraries declare and export components we'll never use.
The _tree shaker_ will drop these components from the final code package
if we don't reference them.
If the [Angular compiler](#q-angular-compiler) generated code for every declared component,
it would defeat the purpose of the tree shaker.
Instead, the compiler adopts a recursive strategy that generates code only for the components we use.
It starts with the entry components,
then it generates code for the declared components it [finds](#q-template-reference) in an entry component's template,
then for the declared components it discovers in the templates of previously compiled components,
and so on. At the end of the process, it has generated code for every entry component
and every component reachable from an entry component.
If a component isn't an _entry component_ or wasn't found in a template,
the compiler omits it.
.l-hr
a#q-module-recommendations
.l-main-section
:marked
#### What kinds of modules should I have and how should I use them?
Every app is different and developers have varying levels of experience and comfort with the available choices.
Some suggestions and guidelines appear to have wide appeal.
.alert.is-important
:marked
The following is preliminary guidance based on early experience using Angular modules in a few applications.
Read with appropriate caution and reflection.
:marked
#### _SharedModule_
Create a `SharedModule` with the components, directives, and pipes that you use
everywhere in your app. This module should consist entirely of `declarations`
most of them exported.
It may re-export other [widget modules](#widget-feature-module) such as `CommonModule`,
`FormsModule` and modules with the UI controls that you use most widely.
It should ***not*** have `providers` for reasons [explained earlier](#q-why-bad).
Nor should any of its imported or re-exported modules have `providers`.
Know what you're doing and why if you deviate from this guideline.
Import the `SharedModule` in your _feature_ modules,
both those loaded when the app starts and those you lazy load later.
#### _CoreModule_
Create a `CoreModule` with `providers` for the singleton services you load when the application starts.
Import `CoreModule` in the root `AppModule` only.
Never import `CoreModule` in any module other than the root `AppModule`.
Consider making `CoreModule` a [pure services module](#service-feature-module) with no `declarations`.
.l-sub-section
:marked
This chapter sample departs from that advice by declaring and exporting two components that are
only used within the root `AppComponent` declared by `AppModule`.
Someone following this guideline strictly would have declared these components in the `AppModule` instead.
:marked
#### Feature Modules
Create _Feature Modules_ around specific application business domains, user workflows, and utility collections.
Feature modules tend to fall into one of these four groups:
* [Domain Feature Modules](#domain-feature-module)
* [Routed Feature Modules](#routed-feature-module)
* [Routing Modules](#routing-module)
* [Service Feature Modules](#service-feature-module)
* [Widget Feature Modules](#widget-feature-module)
.l-sub-section
:marked
Real world modules are often hybrids that knowingly deviate from the following guidelines.
They are guidelines, not laws.
Follow them until you have a good reason to do otherwise.
table
tr
th(style="vertical-align: top") Feature Module
th(style="vertical-align: top") Guidelines
tr
td(style="vertical-align: top")<a id="domain-feature-module"></a>Domain
td
:marked
Domain Feature Modules deliver a user experience **dedicated to a particular application domain**
like editing a customer or placing an order.
They typically have a top component that acts as the feature root.
Private, supporting sub-components descend from it.
Domain feature module consist mostly of _declarations_.
Only the top component is exported.
Domain feature modules rarely have _providers_.
When they do, the lifetime of the provided services
should be the same as the lifetime of the module.
Do not provide application-wide singleton services in a domain feature module.
Domain feature modules are typically imported _exactly once_ by a larger feature module.
They might be imported by the root `AppModule` of a small application that lacks routing.
.l-sub-section
:marked
For an example, see [_ContactModule_](../guide/ngmodule.html#contact-module-v1)
in the Angular Module chapter, before we introduced routing.
tr
td(style="vertical-align: top")<a id="routed-feature-module"></a>Routed
td
:marked
_Routed Feature Modules_ are _Domain Feature modules_
whose top components are the **targets of router navigation routes**.
All lazy loaded modules are routed feature modules by definition.
This chapter's `ContactModule`, `HeroModule` and `CrisisModule` are routed feature modules.
Routed Feature Modules _should not export anything_.
They don't have to because none of their components ever appear in the template of an external component.
A lazy loaded Routed Feature Module should _not be imported_ by any module.
Doing so would trigger an eager load, defeating the purpose of lazy loading.
`HeroModule` and `CrisisModule` are lazy loaded. They aren't mentioned among the `AppModule` imports.
But an eager loaded Routed Feature Module must be imported by another module
so that the compiler learns about its components.
`ContactModule` is eager loaded and, therefore, is listed among the `AppModule` imports.
Routed Feature Modules rarely have _providers_ for reasons [explained earlier](#q-why-bad).
When they do, the lifetime of the provided services
should be the same as the lifetime of the module.
Do not provide application-wide singleton services in a routed feature module
or in a module that the routed module imports.
tr
td(style="vertical-align: top")<a id="routing-module"></a>Routing
td
:marked
A [_Routing Module_](../guide/router.html#routing-module) **provides routing configuration** for another module.
A Routing Module separates routing concerns from its companion module.
It typically:
* defines routes
* adds router configuration to the module's `imports`
* re-exports `RouterModule`
* adds guard and resolver service providers to the module's `providers`.
The name of the Routing Module should parallel the name of its companion module, using the suffix "Routing".
For example, `FooModule` in `foo.module.ts` has a routing module named `FooRoutingModule`
in `foo-routing.module.ts`
If the companion module is the _root_ `AppModule`,
the `AppRoutingModule` adds router configuration to its `imports` with `RouterModule.forRoot(routes)`.
All other Routing Modules are children that import `RouterModule.forChild(routes)`.
A Routing Module re-exports the `RouterModule` as a convenience
so that components of the companion module have access to
router directives such as `RouterLink` and `RouterOutlet`.
A Routing Module **should not have its own `declarations`!**
Components, directives, and pipes are the **responsibility of the feature module**
not the _routing_ module.
A Routing Module should _only_ be imported by its companion module.
The `AppRoutingModule`, `ContactRoutingModule` and `HeroRoutingModule` are good examples.
.l-sub-section
:marked
See also "[Do you need a _Routing Module_?](../guide/router.html#why-routing-module)".
tr
td(style="vertical-align: top")<a id="service-feature-module"></a>Service
td
:marked
_Service Modules_ **provide utility services** such as data access and messaging.
Ideally they consist entirely of _providers_ and have no _declarations_.
The `CoreModule` and Angular's `HttpModule` are good examples.
Service Modules should _only_ be imported by the root `AppModule`.
Do **not** import them in other feature modules.
Know what you're doing and why if you deviate from this guideline.
tr
td(style="vertical-align: top")<a id="widget-feature-module"></a>Widget
td
:marked
A _Widget Module_ makes **components, directives, and pipes** available to external modules.
`CommonModule` and `SharedModule` are widget modules.
Many third party UI component libraries are widget modules.
A Widget Module should consist entirely of _declarations_, most of them exported.
A Widget Module should rarely have _providers_.
Know what you're doing and why if you deviate from this guideline.
Import Widget Modules in any module whose component templates need the widgets.
:marked
The following table summarizes the key characteristics of each _Feature Module_ group.
.l-sub-section
:marked
Real world modules are often hybrids that knowingly deviate from these guidelines.
table
tr
th Feature Module
th Declarations
th Providers
th Exports
th Imported By
th Examples
tr
td Domain
td Yes
td Rare
td Top Component
td Feature, <code>AppModule</code>
td <code>ContactModule</code> (before routing)
tr
td Routed
td Yes
td Rare
td No
td Nobody
td <code>ContactModule</code>, <code>HeroModule</code>, <code>CrisisModule</code>
tr
td Routing
td No
td Yes (Guards)
td <code>RouterModule</code>
td Feature (for routing)
td <code>AppRoutingModule</code>, <code>ContactRoutingModule</code>, <code>HeroRoutingModule</code>
tr
td Service
td No
td Yes
td No
td <code>AppModule</code>
td <code>HttpModule</code>, <code>CoreModule</code>
tr
td Widget
td Yes
td Rare
td Yes
td Feature
td <code>CommonModule</code>, <code>SharedModule</code>
.l-hr
a#q-ng-vs-js-modules
.l-main-section
:marked
### What's the difference between Angular and JavaScript Modules?
Angular and JavaScript are two different yet complementary module systems.
In modern JavaScript, [every file is a _module_](http://exploringjs.com/es6/ch_modules.html).
Within each file we write an `export` statement to make parts of the module public:
code-example(format='.').
export class AppComponent { ... }
:marked
Then we `import` a part in another module:
code-example(format='.').
import { AppComponent } from './app.component';
:marked
This kind of modularity is a feature of the _JavaScript language_.
An _Angular Module_ is a feature of _Angular_ itself.
Angular's `NgModule` also has `imports` and `exports` and they serve a similar purpose.
We _import_ other Angular modules so we can use their exported classes in component templates.
We _export_ this Angular module's classes so they can be imported and used by components of _other_ modules.
The Angular module classes differ from JavaScript module class in three key respects:
1. An Angular module bounds [_declarable classes_](#q-declarables) only.
Declarables are the only classes that matter to the [Angular compiler](#q-angular-compiler).
1. Instead of defining all member classes in one giant file (as in a JavaScript module),
we list the module's classes in the `@NgModule.declarations` list.
1. An Angular module can only export the [_declarable classes_](#q-declarables)
it owns or imports from other modules.
It doesn't declare or export any other kind of class.
The Angular Module is also special in another way.
Unlike JavaScript modules, an Angular module can extend the _entire_ application with services
by adding providers to the `@NgModule.providers` list.
.alert.is-important
:marked
The provided services do not belong to the module nor are they scoped to the declared classes.
They are available _everywhere_.
:marked
Here's an _Angular Module_ class with imports, exports, and declarations.
+makeExample('ngmodule/ts/app/contact/contact.module.2.ts', 'class')(format=".")
:marked
Of course we use _JavaScript_ modules to write _Angular_ modules as seen in the complete `contact.module.ts` file:
+makeExample('ngmodule/ts/app/contact/contact.module.2.ts', '', 'app/contact/contact.module.ts')(format=".")
.l-hr
a#q-template-reference
.l-main-section
h4.
How does Angular find components, directives, and pipes in a template?<br>What is a <i><b>template reference</b></i>?
:marked
The [Angular compiler](#q-angular-compiler) looks inside component templates
for other components, directives, and pipes. When it finds one, that's a "template reference".
The Angular compiler finds a component or directive in a template when it can match the **selector** of that
component or directive to some HTML in that template.
The compiler finds a pipe if the pipe's **name** appears within the pipe syntax of the template HTML.
Angular only matches selectors and pipe names for classes that are declared by this module
or exported by a module that this module imports.
.l-hr
a#q-angular-compiler
.l-main-section
:marked