Вы когда-нибудь задумывались о том, как загружается приложение angular или, проще говоря, как приложение запускается за сценой и попадает в браузер. Если вы использовали свое приложение angular с другим приложением, таким как ReactJS, Vuejs и т. Д., В той же среде или, например, с любой системой CMS, такой как WordPress или Adobe AEM, вы, вероятно, столкнулись бы с проблемами и, возможно, столкнулись бы с термином начальной загрузки. В этих сценариях создание экземпляра приложения может стать большой проблемой для достижения желаемой цели.

В этой статье я попытаюсь объяснить, как загружаются приложения AngularJS (‹v2) и последней версии Angular (› = v2), каковы различные способы и как вы реализуете или контролировать их.

Итак, начнем !!

1) AngularJS (‹v2)

Давайте сначала поговорим об AngularJS. Я постараюсь сделать его кратким и охватить только важные моменты, но если вы хотите узнать больше, ознакомьтесь с официальным документом angular по следующей ссылке:

Https://docs.angularjs.org/guide/bootstrap

Существует два основных способа загрузки приложения AngularJS:

1.1 По умолчанию или автоматическая загрузка

1.2 Ручная загрузка

1.1 Начальная загрузка по умолчанию

С точки зрения имплантации есть две обязательные вещи, которые необходимо сделать для запуска приложения AngularJS на веб-странице: сначала вам нужно добавить скрипт AngularJS, а затем вы должны пометить элемент html тегом ng-app атрибут, в котором вы хотите, чтобы приложение было инициализировано. ng-app принимает необязательную строку, имя модуля, которая, если она предоставлена, создает экземпляр модуля с этим именем. Сначала он разрешает зависимости этого модуля, затем анализирует и компилирует шаблоны, настраивает область видимости, затем связывает ее с шаблоном и, наконец, внедряет ее в DOM с указанным тегом ng-app в html. Именно так приложение AngularJS инициализируется и отображается на странице html.

Довольно просто и понятно, правда?

Но что, если вам нужен больший контроль над процессом начальной загрузки, например. запуск процесса начальной загрузки по вашей команде, или у вас есть ситуация, когда вы узнаете имя модуля позже или элемент html, в котором вы хотите, чтобы ваше приложение загружалось? Во всех этих случаях вас спасет ручная начальная загрузка. AngularJS предоставляет способ загрузки вашего приложения вручную. Давайте посмотрим, как это работает !!

1.2 Ручная загрузка

Из приведенного выше объяснения ясно, что точкой запуска процесса начальной загрузки является атрибут ng-app в элементе html. И если вы можете каким-то образом контролировать это, то, вероятно, вы сможете контролировать начальную загрузку. Один из способов, о котором вы, вероятно, могли подумать, - это динамически назначать атрибут с помощью vanilla javaScript любому элементу, который был бы хорошей попыткой, но он не сработает, потому что angular находит атрибут ng-app после полной загрузки страницы и если он не находит никаких тегов, он ничего не делает, а также не следит за ng-app, он просто смотрит один раз, когда страница загружается в первый раз. Таким образом, правильный способ сделать это не путем добавления ng-app в документ, а путем указания, на каком элементе вы хотите, чтобы оно было загружено. Давайте посмотрим, что я имею в виду, рассмотрим следующий фрагмент:

<!doctype html>
<html>
<body>
  <div ng-controller="MyController">
    Hello {{greetMe}}!
   </div> 
 <!-- Step 1 -->
 <script src="http://code.angularjs.org/snapshot/angular.js"></script>
  <!-- Step 2-->
  <script>
    angular.module('myApp', [])
      .controller('MyController', ['$scope', function ($scope) {
        $scope.greetMe = 'World';
      }]);
    angular.element(function() {
      angular.bootstrap(document, ['myApp']);
    });
  </script>
</body>
</html>

Сначала вам нужно добавить скрипт angular, а затем вам нужно использовать ссылочный объект angular и элемент вспомогательного метода , в котором вы предоставите функцию обратного вызова, в которой вы будете использовать angular.bootstrap, который принимает два параметра для одного элемента DOM (в официальном документе указывается весь документ, но можно ссылаться на любой элемент DOM), где вы хотите загрузить приложение и второй - это массив модулей, которые вы хотите загрузить. Просто убедитесь, что вы вызываете метод начальной загрузки только после загрузки документа. На этом этапе, если вы следите за тем, как вы, возможно, думали, что если метод начальной загрузки принимает элемент для начальной загрузки, то можно ли загрузить несколько приложений в один и тот же документ ?? Тогда технически ответ - да. это возможно, но пользователи angular говорят, что этот сценарий не очень хорошо протестирован, поэтому попробуйте на свой страх и риск. Они также предупредили, чтобы не выполняли загрузку элемента, который использует любую директиву с включением, например ngIf, ngInclude и ngView. При этом приложение $rootElement и инжектор приложения теряются, в результате чего анимация перестает работать и инжектор становится недоступным извне.

2) Угловой (›= v2)

Angular ничем не отличается от AngularJS с точки зрения начальной загрузки, но, за исключением одного дополнительного способа, в последнем выпуске версии 6 есть один интересный способ, представленный в Angular, который является одним из моих любимых из функций версии 6. Я считаю, что этот новый способ значительно упростит использование компонентов angular с другими фреймворками и экосистемами, такими как ReactJS, VueJs или любой системой CMS, такой как wordpress и т. Д. Итак, давайте начнем !!

В Angular обычно есть 3 способа начальной загрузки приложения:

2.1 По умолчанию или автоматическая загрузка

2.2 Ручная загрузка

2.3 Угловые элементы (›= v6)

2.1 По умолчанию или автоматическая загрузка

Это стандартный способ начальной загрузки приложения angular, а main.ts содержит начальную точку приложения.

platformBrowserDynamic().bootstrapModule(AppModule);

часть platformBrowserDynamic () создает платформу для нашего модуля приложения. Платформа Angular - это точка входа для Angular на веб-странице. Каждая страница имеет ровно одну платформу, а службы (такие как отражение), которые являются общими для каждого приложения Angular, запущенного на странице, связаны в ее области действия.

Angular также имеет концепцию запущенного экземпляра приложения, которую вы обычно можете внедрить с помощью токена ApplicationRef. На одной платформе потенциально может быть много приложений. Каждое приложение создается из модуля с использованием метода bootstrapModule. Это именно тот метод, который используется в main.ts. Таким образом, оператор, показанный в документации, сначала создает платформу, а затем экземпляр приложения.

Angular может быть загружен в других средах хоста Javascript помимо браузера (например, на сервере или в веб-воркере), поэтому важно, чтобы мы указали среду, в которой должно быть загружено наше приложение.

Функция bootstrapModule() помогает запустить наш корневой модуль, принимая корневой модуль в качестве аргумента.

AppModule обрабатывается в соответствии с деталями, указанными в метаданных, связанных с AppModule, зависимости и объявления сначала обрабатываются и разрешаются, прежде чем перейти к фактическому рендерингу в DOM.

NgModules помогает организовать приложение в единые функциональные блоки, которые задаются декоратором @NgModule. Важной конфигурацией в декораторе NgModule является свойство bootstrap, которое указывает компонент для начальной загрузки при запуске приложения. Поэтому, когда все зависимости и службы в поставщике разрешены, angular создает экземпляр компонента начальной загрузки и вставляет в DOM, где вы указали селектор компонентов.

Так работает механизм начальной загрузки по умолчанию.

2.2 Ручная загрузка

Вышеупомянутый процесс автоматической начальной загрузки подразумевает, что вы знаете, с каким компонентом вы хотите запустить приложение. Но представьте себе ситуацию, когда компонент для начальной загрузки приложения определяется сервером во время выполнения. Как вы можете загрузить приложение позже, когда получите эту информацию о компоненте? В такой ситуации может пригодиться ручная самозагрузка. Посмотрим, как этого можно достичь.

Сначала создадим компонент:

import { Component } from '@angular/core';

@Component({
  selector: 'd-comp',
  template: `<span>I am the dynamic component</span>`
})
export class ComponentDynamic {}

Теперь все будет так же, как в вышеупомянутом процессе, за исключением конфигурации начальной загрузки, вы не будете указывать какой-либо компонент в массиве начальной загрузки, просто оставьте его. Но нам нужно указать компонент (ы) в entryComponents, чтобы компилятор создавал для них фабрики. Angular автоматически добавляет все компоненты, указанные в свойстве bootstrap, к компонентам записи, поэтому обычно вы не добавляете корневой компонент в entryComponents.

@NgModule({
  imports:      [ BrowserModule ],
  declarations: [ ComponentDynamic ],
  entryComponents: [ ComponentDynamic ]
})

Теперь мы не указываем селекторы компонентов в index.html, поскольку мы хотим делать это динамически, поэтому теперь это выглядит так:

<body>
  <h1 id="dynamicComponentElement">
     Loading Dynamic Component content here ...
  </h1>
</body>

Если вы запустите приложение сейчас, вы получите следующую ошибку:

The module AppModule was bootstrapped, but it does not declare “@NgModule.bootstrap” components nor a “ngDoBootstrap” method. Please define one of these

Итак, здесь Angular жалуется, что мы не указали, какой компонент следует использовать для начальной загрузки. Позже мы будем загружать приложение вручную, и для этого нам нужно добавить метод ngDoBoostrap в класс AppModule:

export class AppModule {
  ngDoBootstrap(app) { 
    // obtain reference to the DOM element that shows status
    // and change the status to `Loaded`
    const dynamicComponentElement =                                           document.querySelector('#dynamicComponentElement');
    dynamicComponentElement.textContent = 'Loaded';
    // create DOM element for the component being bootstrapped
    // and add it to the DOM
    const componentElement = document.createElement('d-comp');
    document.body.appendChild(componentElement);
    // bootstrap the application with the component
    app.bootstrap(ComponentDynamic);
  }
}

в приведенном выше фрагменте сначала мы получаем элемент DOM, в котором мы хотим, чтобы наш компонент был загружен, затем мы создаем элемент для нашего динамического компонента с помощью селектора компонентов и добавляем его в тело, а затем, наконец, загружаем элемент, добавленный в DOM, с соответствующим компонент с помощью метода app.bootstrap, указав компонент в качестве аргумента.

И вот как вы можете вручную загрузить компонент. Как вы можете видеть здесь, это дает нам больше контроля над способом по умолчанию, и вы можете решить, какой компонент вы хотите загрузить, используя обычный javascript или получив имя компонента из глобальной области javascript браузера.

2.3 Угловые элементы (›= v6)

Самый большой недостаток или головная боль метода ручной начальной загрузки - это создание, добавление и начальная загрузка нашего элемента вручную, и что, если бы у нас был способ, в котором мы просто использовали бы селектор компонентов и пропустили эту часть ручной начальной загрузки? Если у вас такие же мысли, то вы не одиноки с момента выпуска версии 4, эта функция является наиболее ожидаемой функцией в Angular, а в версии 6 она, наконец, появилась в виде angular-elements.

Элементы Angular основаны на концепции веб-компонентов. Это набор функций, которые в настоящее время добавляет W3C к спецификациям HTML и DOM, которые позволяют создавать повторно используемые виджеты или компоненты в веб-документах и ​​веб-приложениях. За ними стоит намерение принести компонентную разработку программного обеспечения во всемирную паутину. Модель компонентов допускает инкапсуляцию и взаимодействие отдельных элементов HTML.

Давайте посмотрим, как угловые элементы используют это

Функция angular elements входит в другой пакет под названием @ angular / elements, который экспортирует createCustomElement() API, который обеспечивает мост от интерфейса компонентов Angular и функциональность обнаружения изменений к встроенному DOM API.

Преобразование компонента в настраиваемый элемент делает всю необходимую инфраструктуру Angular доступной для браузера. Создание настраиваемого элемента является простым и понятным, и оно автоматически связывает ваше определяемое компонентом представление с обнаружением изменений и привязкой данных, сопоставляя функциональность Angular с соответствующими эквивалентами в собственном HTML. Для более глубокого понимания ознакомьтесь со следующей ссылкой



Давайте на этот раз пошагово:

Шаг 1. Добавьте угловой элемент и полифиллы

Чтобы создать собственный элемент, вам нужно добавить angular-elements в свой модуль, а с версии 6 angular CLI вы можете сделать это, просто используя следующую команду:

ng add @angular/elements

Это добавит в ваш проект пакет угловых элементов, а также полифиллы.

Шаг 2. Создайте компонент

import { Component, Input } from '@angular/core';
@Component({
    selector: 'my-app',
    templateUrl: './app.component.html',
    styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
    @Input() name = 'Angular 6';
}

Шаг 3: Зарегистрируйте компонент в модуле

@NgModule({
    imports:      [ BrowserModule ],
    declarations: [ AppComponent ],
    entryComponents:    [ AppComponent ]
})
export class AppModule {
    constructor(private injector:Injector){}
    ngDoBootstrap(){
        const AppElement = createCustomElement(AppComponent, {         injector: this.injector });
       customElements.define('my-app', AppElement);
    }
}

Это важный шаг: мы используем createCustomElement функцию Angular для создания класса, который можно использовать с встроенными customElements.define функциональными возможностями браузеров.

Документация по Angular лучше всего описывает это:

createCustomElement Создает класс, который инкапсулирует функциональные возможности предоставленного компонента и использует информацию о конфигурации для предоставления большего контекста классу. Принимает входные и выходные данные фабрики компонентов, чтобы преобразовать их в соответствующий API пользовательских элементов и добавить перехватчики для входных изменений.

Инжектор конфигурации - это начальный инжектор, установленный в классе и используемый по умолчанию для каждого созданного экземпляра. Это поведение можно переопределить с помощью статического свойства, чтобы повлиять на все вновь созданные экземпляры, или в качестве аргумента конструктора для одноразовых созданий.

Особенностью этого модуля также является то, что, поскольку наш ButtonComponent не является частью какого-либо другого компонента, а также не является корнем приложения Angular, нам нужно специально указать Angular скомпилировать его: для этого мы помещаем его в entryComponent список.

Нам также нужно указать Angular использовать этот модуль для начальной загрузки, отсюда и метод ngDoBootstrap.

Шаг 4. Сборка

Теперь просто создайте его, используя стандартную команду ng build, он выведет 4 файла (runtime.js, scripts.js, polyfills.js и main.js).

Примечание. Вы можете оптимизировать и эти файлы, и объединить их в один файл для простоты использования.

Шаг 5. Используйте

Чтобы использовать его, просто включите скрипт (ы) на веб-страницу и вставьте элемент селектора настраиваемых компонентов в свой html. Вот и все.

Файлы сборки связаны со всем, что требуется вашему пользовательскому компоненту, включая поддерживающую экосистему Angular, ваш модуль с пользовательскими компонентами и необходимые полифиллы. Эти файлы содержат все, что нужно для выполнения вашего пользовательского элемента на любой платформе. Он также заботится о поиске настраиваемого элемента с помощью селектора и начальной загрузке соответствующего компонента и его рендеринге в DOM.

Надеюсь, это было полезно, и вы кое-что узнали !!

если да, то пожалуйста:

→ нажмите кнопку хлопка 👏 ниже, чтобы это увидело больше людей
→ и подпишитесь на нашу публикацию по адресу https://medium.com/learnwithrahul

Продолжай учиться !! Продолжайте делиться !!

Примеры Stackblitz:

Угловые элементы: https://stackblitz.com/edit/angular-f3nrpv?file=app%2Fapp.component.html

2.2 Ручная загрузка Angular: https://stackblitz.com/edit/angular-h312t4?file=app%2Fapp.module.ts