Эта проблема

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

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

Итак, давайте посмотрим, что произойдет, если вы разместите 2 приложения на одной странице:

Как видите, выполняется рендеринг только одного приложения (скрипты любого приложения идут первыми в html). Итак, как нам это обойти.

Решение 1

Одно из решений, которое вы можете найти в Интернете, - просто обернуть каждое из ваших Angular-приложений в iFrame. Если вы похожи на меня и видите, что решение - это iFrame, вы, вероятно, вздрагиваете (не волнуйтесь, я найду более приятное решение). Технически это работает, потому что каждое приложение работает в собственной изолированной среде и, следовательно, не вызывает проблем с другими приложениями. Для простых приложений это может сработать, но когда все становится сложнее и вам нужны входные данные в или из вашего приложения, это может стать более серьезной проблемой. Ваше приложение также не имеет доступа к маршрутам в родительских окнах и в конечном итоге становится кошмаром для общения.

Решение 2

Используйте угловые элементы. Если вы не использовали Angular Elements, они представляют собой фантастический инструмент, который позволяет вам компилировать приложения Angular в веб-компоненты. Это позволяет использовать более собственный подход JS / HTML. Я не буду вдаваться в подробности о том, как создавать элементы Angular в этой статье, но есть много отличных ресурсов по этой теме.

Некоторое время мы использовали этот подход и отлично работали… пока этого не произошло. Проблема стала апгрейдом. Итак, хотя какое-то время все будет отлично работать, если приложение 1 обновит Angular или другую зависимость, от которой приложение 2 зависело и развернуло до обновления другого приложения (и было критическое изменение), то одно или оба приложения просто перестанут работать. на странице. Это большая проблема, потому что она возникает только во время выполнения, и невозможно узнать, есть ли в одном приложении критические изменения, пока вы не добавите оба на страницу. Это сделало наши процессы обновления очень громоздкими и потребовало скоординированных выпусков, что противоречит нашим процессам CI / CD и недостаточно хорошо разделяет наши проблемы. Так что, хотя это было жизнеспособное решение, это было не то решение, которое мы искали.

Решение 3

Это заставило меня искать новый ответ, что-то, что поддерживало бы изолированный подход iFrames, но не позволяло бы приложениям жить на странице изначально, как с Angular Elements. Покопавшись некоторое время, я не смог найти решение этой проблемы. Так почему же эти приложения отображаются только в самом верхнем доступном. Чтобы понять это, мы должны разобраться, как Angular компилирует наши файлы. Когда мы заглядываем под капот, он просто использует Webpack для создания наших пакетов. Зная это и покопавшись, я обнаружил, что Webpack создает в окне один объект с пространством имен. Чтобы увидеть это, откройте консоль на любой странице с приложением Angular и введите window.webpackJsonp. Как только вы это увидите, вы увидите все объекты, которые веб-пакет имеет пространство имен под этим объектом. Это натолкнуло меня на мысль попробовать переименовать выводимое пространство имен. Angular не дает вам возможности сделать это изначально, но, к счастью, поиграв с Angular Elements, я смог поиграть с инструментом Ngx Build Plus. Это очень мощный инструмент, который позволяет вам настроить Webpack для вашего процесса сборки Angular.

Этот инструмент работает как для Nrwl Nx, так и для обычного приложения Angular. В этом руководстве мы рассмотрим простую реализацию в существующем автономном приложении Angular.

Для начала выполните «npm install ngx-build-plus -D»

Затем вы можете добавить build plus в качестве компоновщика проектов, запустив «ng add ngx-build-plus»

Теперь мы настроили компоновщик Angular для использования ngx-build-plus, а это значит, что нам просто нужно настроить процесс сборки.

Для этого нам просто нужно добавить файл на нашем корневом уровне, мы назовем его webpack.extra.js. После того, как вы его создали, вам просто нужно добавить следующее, поскольку оно

module.exports = {
   output: {
     jsonpFunction: 'namespacedName'
   }
}

Замените namespacedName уникальным namespaceName вашего приложения. В этом примере я использовал webpackApplicationOne и webpackApplicationTwo.

Теперь нам просто нужно запустить нашу сборку с одним дополнительным параметром «ng build - prod - extra-webpack-config webpack.extra.js».

Теперь, когда я объединяю свои 2 приложения в один index.html и запускаю его, я получаю:

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

Ник Фаверо - сторонник Angular, которому нравится среда, которую он предоставляет. Он старший инженер-программист в DHI Group / Dice, и если вы ищете новую техническую карьеру, найдите новую карьеру на Dice.com или работу в DHI.