Ответ 1
TL;DR:
-
CoreModule
должен иметь толькоservices
и импортироваться только один раз вAppModule
. -
SharedModule
должен иметь ничего, кромеservices
и импортироваться во все модули, которым нужны общие материалы (которые также могут бытьAppModule
).
Но:
Модули реального мира часто являются гибридами, которые целенаправленно отклоняются от руководящих принципов [выше]. Эти руководящие принципы не являются законами; следуйте им, если у вас нет веских оснований для этого.
RTFM:
Итак, пройдя все документы NgModules (плюс некоторые другие вещи, чтобы понять контекст), я легко нашел ответ на ваши 2-й и 3-й вопросы там. Вот они:
SharedModule
- Создание
SharedModule
сcomponents
,directives
иpipes
, которые используются во всем мире в вашем приложении. Этот модуль должен состоять полностью изdeclarations
, большинство из которых экспортируются.SharedModule
может реэкспортировать другие модули виджетов, такие какCommonModule
,FormsModule
и модули с помощью элементов управления пользовательского интерфейса, которые вы используете наиболее широко.SharedModule
не должен иметьproviders
по причинам, описанным ранее. Также ни один из импортированных или реэкспортируемых модулей не имеет поставщиков. Если вы отклоняетесь от этого руководства, знайте, что вы делаете и почему.- Импортируйте
SharedModule
в свои функциональные модули, как загруженные при запуске приложения, так и те, которые вы лените позже.
CoreModule
- Создайте
CoreModule
сproviders
для служб singleton, которые вы загружаете, когда приложение запускается.- Импортируйте
CoreModule
в корневойAppModule
. Никогда не импортируйтеCoreModule
в любой другой модуль.- Подумайте о том, чтобы сделать
CoreModule
чистым сервисным модулем безdeclarations
.
Хотя они более подробные, чем версия TL;DR
выше, и теперь вы можете продолжать и продолжать кодирование, в ней упоминаются некоторые вещи, которые вы должны прочитать, чтобы понять документы (например, "модуль виджета", "причины, объясненные ранее", "чистые служебные модули "), и он также не отвечает на ваш первый вопрос.
Так что попробуй это сделать!
Зачем мне нужны два модуля?
Вам не нужны два модуля. Это то, что находится в документах:
Корневой модуль - это все, что вам нужно в простом приложении с несколькими компонентами.
С учетом сказанного важно сначала задать другой вопрос:
Почему люди организуют свои проекты на нескольких модулях?
Основное объяснение этого происходит сразу после вышеупомянутого утверждения в документах:
По мере того, как приложение растет, вы реорганизуете корневой модуль в функциональные модули, которые представляют коллекции связанных функций. Затем вы импортируете эти модули в корневой модуль.
Но вы спросили: "Почему?" и это требует более чем базового объяснения. Поэтому давайте начнем объяснять, какие проблемы могут возникнуть, если ваше приложение начнет расти, и вы не разделяете функциональные возможности на функциональные модули:
- Корневой модуль начинает загромождать код, который трудно читать и работать, поскольку он должен импортировать все зависимости (например, сторонние модули), предоставлять все службы и объявлять все компоненты, директивы и каналы. Чем больше понадобится приложение, тем больше будет этот модуль.
- У разных функций нет четкой границы между ними, что усложняет задачу, а не просто понимать структуру приложения, но также имеет разные обязанности в команде.
- Вы можете начать решать конфликты между различными частями вашего приложения. Например, если у вас есть директивы или компоненты, которые делают то же самое в двух разных частях вашего приложения, вам придется либо начать использовать более длинные имена, чтобы их отличить, либо переименовать их при импорте.
Хотя вы можете подумать, что приведенные выше примеры не являются точно проблемами (возможно, вы работаете в одиночку и можете жить со своим собственным беспорядком или все ваши товарищи по команде тоже беспорядочны), имейте в виду, что другие люди, безусловно, не согласятся с вами, и почему вы "наблюдали за несколькими проектами [там]... используя этот подход".
Учитывая, что вы согласны с этим и хотите организовать растущее приложение в функциональных модулях, обратите внимание на следующие заявления из документов:
Корневой модуль и модуль функций имеют один и тот же контекст выполнения. Они имеют один и тот же инжектор зависимости, что означает, что услуги в одном модуле доступны для всех.
Модули имеют следующие существенные технические отличия:
- Вы загружаете корневой модуль для запуска приложения; вы импортируете модуль функций для расширения приложения.
- Функциональный модуль может выставлять или скрывать свою реализацию из других модулей.
Информация, которую нельзя забывать: "услуги в одном модуле доступны для всех [модулей]", в то время как в каждом модуле, который хочет их использовать, нужно вводить другие вещи, такие как "Компоненты", "Директивы" и "Трубы".
С этой информацией мы можем теперь приблизиться к тому, что вы хотите знать, отвечая на следующий вопрос:
Все ли функциональные модули равны?
НЕТ! По крайней мере, предполагается, что они не должны быть равными, так как предлагается, чтобы у вас не было только корневого модуля, но вы можете делать все, что хотите. Но вы не должны.
В документах есть таблица, показывающая различия между предложенными группами модулей функций. Позвольте взглянуть на выдержку из нее:
FEATURE SHOULD HAVE SHOULD HAVE SHOULD HAVE
MODULE DECLARATIONS PROVIDERS EXPORTS
Domain Yes Rare Top component
Routed Yes Rare No
Routing No Yes (Guards) RouterModule
Service No Yes No
Widget Yes Rare Yes
ВНИМАНИЕ! Они делают это довольно ясно, что это...
... предварительные рекомендации, основанные на раннем опыте использования NgModules в нескольких приложениях.
Итак, опять же, вы не придерживаетесь этих рекомендаций, и могут произойти отклонения, но вы должны знать, что вы делаете и почему.
Теперь проанализируйте эту таблицу:
- Группы
Service
иWidget
являются единственными, которые имеют разные значения между ними в каждом столбце. - Группы
Domain
иRouted
в основном такие же, как и группаWidget
, только с ограниченным или отсутствием экспорта. - Группа
Routing
- это, в основном, группаService
с исключением экспорта и ограничена конкретным поставщиком.
Итак, рассмотрим группы Domain
, Routed
и Routing
только варианты Service
или Widget
и сосредоточимся на этих последних двух.
Услуги должны обратить ваше внимание. Помните, что вы никогда не должны забывать, что "услуги в одном модуле доступны для всех [модулей]"? Ну, если они называют себя модуль особенности группы Services
, что, поскольку он должен быть изолирован от других модулей, так что можно импортировать только один раз. Например, вы можете иметь UserModule
который состоит из таких сервисов, как SignUpService
, SignInService
, SocialAuthService
и UserProfileService
. Где бы вы ни импортировали этот UserModule
, все его службы будут доступны для приложений. И согласно приведенной выше таблице, он не должен иметь деклараций и экспорта, а только поставщиков.
Виджеты звучат более обобщенно, но он должен вам что-то сказать. Помните, что вы также никогда не должны забывать, что "в каждом модуле, который хочет их использовать, нужно вводить другие вещи, такие как" Компоненты "," Директивы "и" Трубы "."? Так что это тип модуля, который вы будете использовать для них. Например, вы можете иметь UIModule
с ButtonComponent
, NavComponent
, SlideshowComponent
, HighlightLinkDirective
, CtaPipe
. И каждый раз, когда вам нужно использовать один или все экспортированные элементы, вы импортируете только UIModule
.
Итак, в основном, из-за того, как Angular имеет дело с Сервисами, когда вы начинаете разделять функциональные возможности на функциональные модули, вам нужно изолировать службы в своих собственных модулях, а другие могут быть организованы между ними по вашему желанию.
Как CoreModule
и SharedModule
вписываются в это?
Чтобы упростить это, CoreModule
является Service
модулем, а SharedModule
- модулем Widget
. И поэтому вы должны импортировать первый только один раз в AppModule
а последний - во все модули, которые в нем нуждаются. Из приведенных выше примеров UserModule
будет импортироваться с помощью CoreModule
и UIModule
с помощью SharedModule
.
Но, как указывалось ранее, это рекомендации и отклонения могут произойти, даже в своих собственных примерах они объявляют компоненты в CoreModule
, но с наблюдением:
Этот образец страницы отходит от этого совета, объявляя и экспортируя [в
CoreModule
] два компонента, которые используются только в корневом AppComponent, объявленном AppModule. Кто-то, следующий за этим руководством, строго заявил бы об этих компонентах в AppModule.
Лично я считаю, что самая большая путаница касается выбора наименований. В общем, люди будут думать, что все, что является частью вашего ядра приложения (например, пользовательский материал, NavBar, панель загрузки, тостеры и т.д.), SharedModule
в CoreModule
и все, что разделяет несколько функций, войдет в SharedModule
.
Это на самом деле не правда и немного вводит в заблуждение, поскольку все сервисы распределяются между всеми модулями "по своей природе", и ни один сервис не должен включаться в SharedModule
, а также NavbarComponent
является частью ядра вашего приложения, и ни один компонент не должен быть включен в CoreModule
.
В любом случае, рекомендация заключается в том, чтобы следовать рекомендациям, пока не найдете причину не делать этого.
И вот остальная часть таблицы выше, чтобы помочь лучше понять руководящие принципы:
FEATURE CAN BE SOME
MODULE IMPORTED BY EXAMPLES
Domain Feature, AppModule ContactModule (before routing)
Routed Nobody ContactModule, DashboardModule,
Routing Feature (for routing) AppRoutingModule, ContactRoutingModule
Service AppModule HttpModule, CoreModule
Widget Feature CommonModule, SharedModule
Ура!