<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Manfred Steyer</title>
    <description>The latest articles on DEV Community by Manfred Steyer (@manfredsteyer).</description>
    <link>https://dev.to/manfredsteyer</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F213260%2F25d4504f-8798-4748-a392-48446f37d723.jpg</url>
      <title>DEV Community: Manfred Steyer</title>
      <link>https://dev.to/manfredsteyer</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/manfredsteyer"/>
    <language>en</language>
    <item>
      <title>Tutorial: Getting Started with Webpack Module Federation and Angular</title>
      <dc:creator>Manfred Steyer</dc:creator>
      <pubDate>Sun, 29 Nov 2020 14:06:03 +0000</pubDate>
      <link>https://dev.to/manfredsteyer/tutorial-getting-started-with-webpack-module-federation-and-angular-2edd</link>
      <guid>https://dev.to/manfredsteyer/tutorial-getting-started-with-webpack-module-federation-and-angular-2edd</guid>
      <description>&lt;p&gt;This tutorial shows how to use Webpack Module Federation together with the Angular CLI and the &lt;code&gt;@angular-architects/module-federation&lt;/code&gt; plugin. The goal is to make a shell capable of &lt;strong&gt;loading a separately compiled and deployed microfrontend&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fangular-architects%2Fmodule-federation-plugin%2Fraw%2Fmain%2Fpackages%2Fmf%2Ftutorial%2Fresult.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fangular-architects%2Fmodule-federation-plugin%2Fraw%2Fmain%2Fpackages%2Fmf%2Ftutorial%2Fresult.png" alt="Microfrontend Loaded into Shell"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This topic is also an important part of our &lt;a href="https://www.angulararchitects.io/en/angular-workshops/advanced-angular-enterprise-architecture-incl-ivy/" rel="noopener noreferrer"&gt;Angular Workshop&lt;/a&gt; with a focus on Architectures (100% Online, Advanced, available in English and German)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Part 1: Clone and Inspect the Starterkit
&lt;/h2&gt;

&lt;p&gt;In this part you will clone the starterkit and inspect its projects.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Clone the starterkit for this tutorial:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/manfredsteyer/module-federation-plugin-example.git --branch starter
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Have a look to the &lt;code&gt;package.json&lt;/code&gt;. You should find this section:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"resolutions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"webpack"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"5.0.0"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;This section makes yarn to install webpack 5 for the CLI (and for all the other libraries depending on webpack).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Move into the project directory and install the dependencies with &lt;strong&gt;yarn&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd module-federation-plugin-example
yarn
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;You really &lt;strong&gt;need to install the dependencies with yarn&lt;/strong&gt; because providing resolutions as shown above is a &lt;strong&gt;yarn&lt;/strong&gt; feature.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Start the shell (&lt;code&gt;ng serve shell -o&lt;/code&gt;) and inspect it a bit:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Click on the &lt;code&gt;flights&lt;/code&gt; link. It leads to a dummy route. This route will later be used for loading the separately compiled microfrontend.&lt;/p&gt;

&lt;p&gt;Please &lt;strong&gt;ignore depreaction warnings&lt;/strong&gt;. They are a temporal issue in the current CLI beta when using webpack 5.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Have a look to the shell's source code. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Please note that the current CLI &lt;strong&gt;beta&lt;/strong&gt; lacks some features when using it with webpack 5, e. g. &lt;strong&gt;reloading an application in debug mode&lt;/strong&gt; (when using ng serve). Hence, you have to restart ng serve after changing a source file. This is just a temporal limitation and will be solved with one of the upcoming versions.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Stop the CLI (&lt;code&gt;CTRL+C&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Do the same for the microfrontend. In this project, it's called &lt;code&gt;mfe1&lt;/code&gt; (Microfrontend 1) You can start it with &lt;code&gt;ng serve mfe1 -o&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;

&lt;/ol&gt;

&lt;h2&gt;
  
  
  Part 2: Activate and Configure Module Federation
&lt;/h2&gt;

&lt;p&gt;Now, let's activate and configure module federation:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Install &lt;code&gt;@angular-architects/module-federation&lt;/code&gt; into the shell and into the micro frontend:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ng add @angular-architects/module-federation --project shell --port 5000

ng add @angular-architects/module-federation --project mfe1 --port 3000
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;This activates module federation, assigns a port for ng serve, and generates the skeleton of a module federation configuration.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Switch into the project &lt;code&gt;mfe1&lt;/code&gt; and open the generated configuration file &lt;code&gt;projects\mfe1\webpack.config.js&lt;/code&gt;. It contains the module federation configuration for &lt;code&gt;mfe1&lt;/code&gt;. Adjust it as follows:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ModuleFederationPlugin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;webpack/lib/container/ModuleFederationPlugin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="p"&gt;[...]&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;uniqueName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mfe1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;optimization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Only needed to bypass a temporary bug&lt;/span&gt;
        &lt;span class="na"&gt;runtimeChunk&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ModuleFederationPlugin&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;

            &lt;span class="c1"&gt;// For remotes (please adjust)&lt;/span&gt;
            &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mfe1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;remoteEntry.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

            &lt;span class="na"&gt;exposes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./Module&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./projects/mfe1/src/app/flights/flights.module.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;        
            &lt;span class="na"&gt;shared&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;singleton&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;strictVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; 
                &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@angular/common&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;singleton&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;strictVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; 
                &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@angular/router&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;singleton&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;strictVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;[...]&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}),&lt;/span&gt;
        &lt;span class="p"&gt;[...]&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;This exposes the &lt;code&gt;FlightsModule&lt;/code&gt; under the Name &lt;code&gt;./Module.&lt;/code&gt;. Hence, the shell can use this path to load it. &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Switch into the &lt;code&gt;shell&lt;/code&gt; project and open the file &lt;code&gt;projects\shell\webpack.config.js&lt;/code&gt;. Adjust it as follows:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ModuleFederationPlugin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;webpack/lib/container/ModuleFederationPlugin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="p"&gt;[...]&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;uniqueName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;shell&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;optimization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Only needed to bypass a temporary bug&lt;/span&gt;
        &lt;span class="na"&gt;runtimeChunk&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ModuleFederationPlugin&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;remotes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mfe1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mfe1@http://localhost:3000/remoteEntry.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; 
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="na"&gt;shared&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;singleton&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;strictVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; 
                &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@angular/common&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;singleton&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;strictVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; 
                &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@angular/router&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;singleton&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;strictVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;[...]&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}),&lt;/span&gt;
        &lt;span class="p"&gt;[...]&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;This references the separately compiled and deployed &lt;code&gt;mfe1&lt;/code&gt; project. There are some alternatives to configure its URL (see links at the end).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Open the &lt;code&gt;shell&lt;/code&gt;'s router config (&lt;code&gt;projects\shell\src\app\app.routes.ts&lt;/code&gt;) and add a route loading the microfrontend:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;flights&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;loadChildren&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mfe1/Module&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FlightsModule&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Please note that the imported URL consists of the names defined in the configuration files above.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;As the Url &lt;code&gt;mfe1/Module&lt;/code&gt; does not exist at compile time, ease the TypeScript compiler by adding the following line to the file &lt;code&gt;projects\shell\src\decl.d.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;declare&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mfe1/Module&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Part 3: Try it out
&lt;/h2&gt;

&lt;p&gt;Now, let's try it out!&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Start the &lt;code&gt;shell&lt;/code&gt; and &lt;code&gt;mfe1&lt;/code&gt; side by side:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ng serve shell -o
ng serve mfe1 -o
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;strong&gt;Hint:&lt;/strong&gt; You might use two terminals for this.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;After a browser window with the shell opened (&lt;code&gt;http://localhost:5000&lt;/code&gt;), click on &lt;code&gt;Flights&lt;/code&gt;. This should load the microfrontend into the shell:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fangular-architects%2Fmodule-federation-plugin%2Fraw%2Fmain%2Fpackages%2Fmf%2Ftutorial%2Fshell.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fangular-architects%2Fmodule-federation-plugin%2Fraw%2Fmain%2Fpackages%2Fmf%2Ftutorial%2Fshell.png" alt="Shell"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Also, ensure yourself that the microfrontend also runs in standalone mode at &lt;a href="http://localhost:3000:" rel="noopener noreferrer"&gt;http://localhost:3000:&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fangular-architects%2Fmodule-federation-plugin%2Fraw%2Fmain%2Fpackages%2Fmf%2Ftutorial%2Fmfe1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fangular-architects%2Fmodule-federation-plugin%2Fraw%2Fmain%2Fpackages%2Fmf%2Ftutorial%2Fmfe1.png" alt="Microfrontend"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Congratulations! You've implemented your first Module Federation project with Angular!&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 4: Switch to Dynamic Federation
&lt;/h2&gt;

&lt;p&gt;Now, let's remove the need for registering the micro frontends upfront with with shell.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Switch to your &lt;code&gt;shell&lt;/code&gt; application and open the file &lt;code&gt;webpack.config.js&lt;/code&gt;. Here, remove the registered remotes:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;remotes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Remove this line or comment it out:&lt;/span&gt;
    &lt;span class="c1"&gt;// "mfe1": "mfe1@http://localhost:3000/remoteEntry.js",&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Open the file &lt;code&gt;app.routes.ts&lt;/code&gt; and use the function &lt;code&gt;loadRemoteModule&lt;/code&gt; instead of the dynamic &lt;code&gt;import&lt;/code&gt; statement:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;loadRemoteModule&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular-architects/module-federation&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;[...]&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Routes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;[...]&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;flights&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;loadChildren&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
            &lt;span class="nf"&gt;loadRemoteModule&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                &lt;span class="na"&gt;remoteEntry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:3000/remoteEntry.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;remoteName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mfe1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;exposedModule&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./Module&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
            &lt;span class="p"&gt;})&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FlightsModule&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;[...]&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Restart both, the &lt;code&gt;shell&lt;/code&gt; and the micro frontend (&lt;code&gt;mfe1&lt;/code&gt;). &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The shell should still be able to load the micro frontend. However, now it's loaded dynamically.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This was quite easy, wasn't it? However, we can improve this solution a bit. Ideally, we load the remote entry upfront before Angular bootstraps. In this early phase, Module Federation tries to determine the highest compatible versions of all dependencies. Let's assume, the shell provides version 1.0.0 of a dependency (specifying ^1.0.0 in its &lt;code&gt;package.json&lt;/code&gt;) and the micro frontend uses version 1.1.0 (specifying ^1.1.0 in its &lt;code&gt;package.json&lt;/code&gt;). In this case, they would go with version 1.1.0. However, this is only possible if the remote's entry is loaded upfront.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Switch to the &lt;code&gt;shell&lt;/code&gt; project and open the file &lt;code&gt;main.ts&lt;/code&gt;. Adjust it as follows:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;loadRemoteEntry&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular-architects/module-federation&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="nf"&gt;loadRemoteEntry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:3000/remoteEntry.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mfe1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error loading remote entries&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./bootstrap&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Open the file &lt;code&gt;app.routes.ts&lt;/code&gt; and comment out (or remove) the property &lt;code&gt;remoteEntry&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;loadRemoteModule&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular-architects/module-federation&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;[...]&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Routes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;[...]&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;flights&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;loadChildren&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
            &lt;span class="nf"&gt;loadRemoteModule&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                &lt;span class="c1"&gt;// remoteEntry: 'http://localhost:3000/remoteEntry.js',&lt;/span&gt;
                &lt;span class="na"&gt;remoteName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mfe1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;exposedModule&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./Module&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
            &lt;span class="p"&gt;})&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FlightsModule&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;[...]&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Restart both, the &lt;code&gt;shell&lt;/code&gt; and the micro frontend (&lt;code&gt;mfe1&lt;/code&gt;). &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The shell should still be able to load the micro frontend.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 5: Share a Library of Your Monorepo
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Add a library to your monorepo:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ng g lib auth-lib
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In your &lt;code&gt;tsconfig.json&lt;/code&gt; in the project's root, adjust the path mapping for &lt;code&gt;auth-lib&lt;/code&gt; so that it points to the libs entry point:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"auth-lib"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="s2"&gt;"projects/auth-lib/src/public-api.ts"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As most IDEs only read global configuration files like the &lt;code&gt;tsconfig.json&lt;/code&gt; once, restart your IDE (Alternatively, your IDE might also provide an option for reloading these settings).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Open the &lt;code&gt;shell&lt;/code&gt;'s &lt;code&gt;webpack.config.js&lt;/code&gt; and register the created &lt;code&gt;auth-lib&lt;/code&gt; with the &lt;code&gt;sharedMappings&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sharedMappings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;mf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;SharedMappings&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;sharedMappings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../tsconfig.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;auth-lib&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;-- Add this entry!  &lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Also open the micro frontends (&lt;code&gt;mfe1&lt;/code&gt;) &lt;code&gt;webpack.config.js&lt;/code&gt; and do the same.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Switch to your &lt;code&gt;auth-lib&lt;/code&gt; project and open the file &lt;code&gt;auth-lib.service.ts&lt;/code&gt;. Adjust it as follows:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;providedIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AuthLibService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nf"&gt;user&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Authentication for **honest** users TM. (c) Manfred Steyer&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Switch to your &lt;code&gt;shell&lt;/code&gt; project and open its &lt;code&gt;app.component.ts&lt;/code&gt;. Use the shared &lt;code&gt;AuthLibService&lt;/code&gt; to login a user:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AuthLibService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;auth-lib&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-root&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;templateUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./app.component.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;shell&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AuthLibService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Max&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Switch to your &lt;code&gt;mfe1&lt;/code&gt; project and open its &lt;code&gt;flights-search.component.ts&lt;/code&gt;. Use the shared service to retrieve the current user's name:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FlightsSearchComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="p"&gt;[...]&lt;/span&gt;

    &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AuthLibService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[...])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="p"&gt;[...]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Open this component's template(&lt;code&gt;flights-search.component.html&lt;/code&gt;) and data bind the property &lt;code&gt;user&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;{{user}}&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    [...]
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Restart both, the &lt;code&gt;shell&lt;/code&gt; and the micro frontend (&lt;code&gt;mfe1&lt;/code&gt;). &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the shell, navigate to the micro frontend. If it shows the same user name, the library is shared.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  More Details on Module Federation
&lt;/h2&gt;

&lt;p&gt;Have a look at this &lt;a href="https://www.angulararchitects.io/aktuelles/the-microfrontend-revolution-part-2-module-federation-with-angular/" rel="noopener noreferrer"&gt;article series about Module Federation&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Angular Trainings, Workshops, and Consulting
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.angulararchitects.io/en/angular-workshops/" rel="noopener noreferrer"&gt;Angular Trainings and Workshops&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.angulararchitects.io/en/consulting/" rel="noopener noreferrer"&gt;Angular Consulting&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>angular</category>
      <category>architecture</category>
      <category>microfrontends</category>
      <category>modulefederation</category>
    </item>
    <item>
      <title>6 Steps to your Angular-based Microfrontend Shell</title>
      <dc:creator>Manfred Steyer</dc:creator>
      <pubDate>Sun, 01 Dec 2019 23:08:14 +0000</pubDate>
      <link>https://dev.to/manfredsteyer/6-steps-to-your-angular-based-microfrontend-shell-1nei</link>
      <guid>https://dev.to/manfredsteyer/6-steps-to-your-angular-based-microfrontend-shell-1nei</guid>
      <description>&lt;p&gt;In the last time, I helped numerous companies implementing Angular SPAs for microservice environments. As outlined in a &lt;a href="https://www.softwarearchitekt.at/aktuelles/a-software-architects-approach-towards/" rel="noopener noreferrer"&gt;former blog article&lt;/a&gt;, there are several approaches for this. &lt;/p&gt;

&lt;p&gt;In this article, I show how to implement one of them in 6 steps: A shell loading micro frontends on demand. Other than in my article about micro frontends and web components, I don't use web components for the macro architecture. Instead, I just go with ordinary SPAs which are loaded and bootstrapped on demand. For the micro architecture I still use web components.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.softwarearchitekt.at%2Fwp-content%2Fuploads%2F2019%2F11%2Fmicro-macro.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.softwarearchitekt.at%2Fwp-content%2Fuploads%2F2019%2F11%2Fmicro-macro.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While this decision simplifies the implementation, we can still isolate different applications using shadow DOM as Angular also supports this standard associated with web components for traditional Angular components since its first day.&lt;/p&gt;

&lt;p&gt;The case study loads a simple &lt;code&gt;client-a&lt;/code&gt; and a simple &lt;code&gt;client-b&lt;/code&gt; into the shell. Also, the former one shares a widget with the latter one:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.softwarearchitekt.at%2Fwp-content%2Fuploads%2F2019%2F11%2Fcase-study-01.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.softwarearchitekt.at%2Fwp-content%2Fuploads%2F2019%2F11%2Fcase-study-01.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.softwarearchitekt.at%2Fwp-content%2Fuploads%2F2019%2F11%2Fcase-study-02.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.softwarearchitekt.at%2Fwp-content%2Fuploads%2F2019%2F11%2Fcase-study-02.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/manfredsteyer/angular-microfrontend" rel="noopener noreferrer"&gt;source code&lt;/a&gt; for this can be found in my &lt;a href="https://github.com/manfredsteyer/angular-microfrontend" rel="noopener noreferrer"&gt;GitHub account here&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 0: Make sure you need it
&lt;/h2&gt;

&lt;p&gt;Make sure this approach fits to your architectural goals. Micro frontends come with a lot of consequences. You should be aware of them. My &lt;a href="https://www.softwarearchitekt.at/aktuelles/a-software-architects-approach-towards/" rel="noopener noreferrer"&gt;blog article here&lt;/a&gt; provides some guidance. &lt;/p&gt;
&lt;h2&gt;
  
  
  Step 1: Implement Your SPAs
&lt;/h2&gt;

&lt;p&gt;Implement your micro frontends as ordinary Angular applications. In an micro service architecture it's quite common that every part gets its own repository in order to decouple them as much as possible (see &lt;a href="https://martinfowler.com/articles/microservices.html#ComponentizationViaServices" rel="noopener noreferrer"&gt;Componentization via Services&lt;/a&gt;) On contrary, I've seen a lot of micro frontends based upon monorepos for practical reasons. &lt;/p&gt;

&lt;p&gt;Of course, now, we could discuss when the term micro frontend is appropriate. I won't, because this discussion doesn't really help. What counts is to find a architecture that fits your goals and to be aware of its consequences. &lt;/p&gt;

&lt;p&gt;If we go with a monorepo, we have to ensure, e. g. with linting rules, that the micro frontends are not coupled to each other. &lt;a href="https://nx.dev/angular" rel="noopener noreferrer"&gt;Nrwl's Nx&lt;/a&gt; provides a great solution for that: It allows to set up access restrictions defining which library can access which other one. Also, Nx can detect which parts of your monorepo are affected by a change in order to only recompile and retest them.&lt;/p&gt;

&lt;p&gt;Of course, this decision has consequences, as discussed in the &lt;a href="https://www.softwarearchitekt.at/aktuelles/a-software-architects-approach-towards/" rel="noopener noreferrer"&gt;mentioned blog article&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To make routing across micro frontends easier, it's a good idea to prefix all the routes with the application's name. In the following case, the application name is &lt;code&gt;client-a&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;NgModule&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;ReactiveFormsModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;BrowserModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;RouterModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forRoot&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;client-a/page1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Page1Component&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;client-a/page2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Page2Component&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;**&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EmptyComponent&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;useHash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;[...]&lt;/span&gt; 
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppModule&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;[...]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Expose Shared Widgets
&lt;/h2&gt;

&lt;p&gt;Expose widgets you want to share as Web Components/ Custom Elements. Please note that from the perspective of micro services, you should avoid sharing code between micro frontends as much as possible. The reason is that this causes coupling which is exactly what you want to avoid with this architectural style.&lt;/p&gt;

&lt;p&gt;For exposing an Angular Component as a Custom Element, you can use Angular Elements. My blog article about &lt;a href="https://www.softwarearchitekt.at/aktuelles/angular-elements-part-i/" rel="noopener noreferrer"&gt;Angular Elements&lt;/a&gt; and &lt;a href="https://www.softwarearchitekt.at/aktuelles/angular-elements-part-ii/" rel="noopener noreferrer"&gt;lazy and external Angular Elements&lt;/a&gt; provides the necessary information. &lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Compile your SPAs
&lt;/h2&gt;

&lt;p&gt;Webpack, and hence the Angular CLI, use a global array for registering bundles. It enables different (lazy) chunks of your application to find each other. However, if we are going to load several SPAs into one page, they will compete over this array, mess it up, and stop working. &lt;/p&gt;

&lt;p&gt;For this dilemma, we have two solutions:&lt;/p&gt;

&lt;p&gt;1) Just put everything into one bundle, so that this global array is not needed&lt;br&gt;
2) Rename the global array&lt;/p&gt;

&lt;p&gt;Here, I use solution 1) because a micro frontend is by definition small and just having one bundle makes loading it on demand easier. Also, as we will see later, we can share libraries like RxJS or Angular itself between them.&lt;/p&gt;

&lt;p&gt;To accompish this, you can leverage &lt;code&gt;ngx-build-plus&lt;/code&gt; which extenses the CLI by a &lt;code&gt;--single-bundle&lt;/code&gt; switch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ng add ngx-build-plus
ng build &lt;span class="nt"&gt;--prod&lt;/span&gt; &lt;span class="nt"&gt;--single-bundle&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This switch makes the CLI to put your whole code into one main bundle. However, scripts, styles, and polyfills are still put into a bundle of their own. The reason behind this is, that it's very likely that the shell already loads these aspects and you don't want to load them again.&lt;/p&gt;

&lt;p&gt;If you favor solution 2) you could use &lt;a href="https://www.npmjs.com/package/ngx-build-plus" rel="noopener noreferrer"&gt;ngx-build-plus&lt;/a&gt; to influence the CLI's webpack config. Using the setting &lt;a href="https://www.softwarearchitekt.at/aktuelles/angular-elements-part-ii/" rel="noopener noreferrer"&gt;output.jsonpFunction&lt;/a&gt; you can define the name for the array mentioned.&lt;/p&gt;

&lt;p&gt;
 
&lt;/p&gt;



&lt;br&gt;
We also offer an &lt;a href="https://www.softwarearchitekt.at/schulungen/advanced-angular-enterprise-anwendungen-und-architektur/" rel="noopener noreferrer"&gt;advanced Angular workshop&lt;/a&gt; containing this topic and more strategies for your Angular-based enterprise architectures. Please find all the information about it &lt;a href="https://www.softwarearchitekt.at/schulungen/advanced-angular-enterprise-anwendungen-und-architektur/" rel="noopener noreferrer"&gt;here&lt;/a&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.softwarearchitekt.at%2Fwp-content%2Fuploads%2F2018%2F06%2Fsharepic-ac-2-opt-1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.softwarearchitekt.at%2Fwp-content%2Fuploads%2F2018%2F06%2Fsharepic-ac-2-opt-1.jpg"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;
 
&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Create a shell and load the bundles on demand
&lt;/h2&gt;

&lt;p&gt;Loading the bundles on demand is straight forward. All you need is some vanilla JavaScript code dynamically creating a &lt;code&gt;script&lt;/code&gt; tag and the tag for application's root element:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// add script tag&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;script&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;script&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[...]/client-a/main.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// add app&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;frontend&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;client-a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;content&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;frontend&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Of course, you can also wrap this into a directive. &lt;/p&gt;

&lt;p&gt;Also, you need some code to show and hide the loaded micro frontend on demand:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;frontend&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;visible&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5: Communication Between Microfrontends
&lt;/h2&gt;

&lt;p&gt;In general, we should keep the communication between microfrontends at a minimum, as it couples them to each other. &lt;/p&gt;

&lt;p&gt;To implement communication, we have several options. Here, I go with the least obtrusive one: using the query string. This has several advantages:&lt;/p&gt;

&lt;p&gt;1) It does not matter in which order the micro frontends are loaded. When they are loaded, they can grab the current parameters from the url&lt;br&gt;
2) It allows deep linking&lt;br&gt;
3) It's like the web is supposed to work&lt;br&gt;
4) It's easy to implement&lt;/p&gt;

&lt;p&gt;Setting an url parameter with the Angular router is just a matter of calling one method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;navigate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;queryParamsHandling&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;merge&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;queryParams&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt; &lt;span class="p"&gt;}});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The option &lt;code&gt;merge&lt;/code&gt; makes sure that the existing url parameters are not lost. If there is already a parameter &lt;code&gt;id&lt;/code&gt;, the router will overwrite it. &lt;/p&gt;

&lt;p&gt;Also, listening for changes within url parameters is also something the Angular router can help with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;queryParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;params&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are some alternatives for this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If you wrap your micro frontends into web components, you could use their properties and events to communicate with the shell.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The shell could put a "message bus" into the global namespace:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;messageBus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;BehaviorSubject&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MicroFrontendEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Both, the shell and the Microfrontends could now subscribe to this message bus and listen for specific events they are interested into. Also, both can emit events.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Using custom Events provided by the browser:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Sender&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;customer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raiseEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CustomEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;CustomerSelected&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;details&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;}))&lt;/span&gt;

&lt;span class="c1"&gt;// Receiver&lt;/span&gt;
&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;CustomerSelected&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 6: Sharing Libraries Between Micro Frontends
&lt;/h2&gt;

&lt;p&gt;Now, as we have several self-contained micro frontends, each of them has its own dependencies, e. g. Angular itself or RxJS. From an micro service perspective, this is perfect because it allows each team behind your micro frontends to choose any library or framework in any version. They can even decide by their own if and when to update to newer versions. &lt;/p&gt;

&lt;p&gt;However, from the perspective of performance and loading time, this is a bad situation because it leads to code duplication within the bundles. For instance, we could end up with having a specific angular version in several of your bundles:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.softwarearchitekt.at%2Fwp-content%2Fuploads%2F2019%2F11%2Fbuild1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.softwarearchitekt.at%2Fwp-content%2Fuploads%2F2019%2F11%2Fbuild1.png" alt="Each Build gets it's own version of Angular and the other libs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fortunately, there is a solution for this: Webpack externals. I've already written about it in the context of &lt;a href="https://www.softwarearchitekt.at/aktuelles/your-options-for-building-angular-elements/" rel="noopener noreferrer"&gt;external (standalone) Angular Elements&lt;/a&gt; and for micro apps I will repeat the most important aspects here:&lt;/p&gt;

&lt;p&gt;Externals allow us to share common libraries. For this, they are just loaded so that they can be referenced via the global namespace. In the case of most libraries we can use UMD bundles which do exactly this besides other things. Then, we have to tell webpack to not bundle them together with every micro frontend but to reference it within the global namespace instead:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.softwarearchitekt.at%2Fwp-content%2Fuploads%2F2019%2F11%2Fbuild3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.softwarearchitekt.at%2Fwp-content%2Fuploads%2F2019%2F11%2Fbuild3.png" alt="Each Build uses the same version of Angular and the other libs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To use webpack externals together with the Angular CLI you can leverage &lt;a href="https://www.npmjs.com/package/ngx-build-plus" rel="noopener noreferrer"&gt;ngx-build-plus&lt;/a&gt; which even comes with a schematic introducing the needed changes into your application.&lt;/p&gt;

&lt;p&gt;To get it, you can &lt;code&gt;ng add&lt;/code&gt; it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ng add ngx-build-plus
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, call the following schematic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ng g ngx-build-plus:externals
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This also introduces an npm script &lt;code&gt;build:&amp;lt;project-name&amp;gt;:externals&lt;/code&gt;. For the default project there is a script &lt;code&gt;build:externals&lt;/code&gt; too.&lt;/p&gt;

&lt;p&gt;If you look into the &lt;code&gt;angular.json&lt;/code&gt; after running this script, you see that Angular is loaded using UMD bundles:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"node_modules/rxjs/bundles/rxjs.umd.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"node_modules/@angular/core/bundles/core.umd.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"node_modules/@angular/common/bundles/common.umd.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"node_modules/@angular/common/bundles/common-http.umd.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"node_modules/@angular/compiler/bundles/compiler.umd.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"node_modules/@angular/elements/bundles/elements.umd.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"node_modules/@angular/platform-browser/bundles/platform-browser.umd.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"node_modules/@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These UMD bundles put Angular into &lt;code&gt;window.ng&lt;/code&gt; where it can be reused by several separately compiled micro frontends.&lt;/p&gt;

&lt;p&gt;Also, if you have a look into the generated &lt;code&gt;webpack.externals.js&lt;/code&gt;, you find a section mapping package names to global variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;webpack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;webpack&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;externals&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rxjs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rxjs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ng.core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@angular/common&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ng.common&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@angular/common/http&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ng.common.http&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@angular/platform-browser&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ng.platformBrowser&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@angular/platform-browser-dynamic&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ng.platformBrowserDynamic&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@angular/compiler&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ng.compiler&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@angular/elements&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ng.elements&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@angular/router&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ng.router&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@angular/forms&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ng.forms&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This, for instance, makes the produced bundle to reference the global variable &lt;code&gt;ng.core&lt;/code&gt; when it needs &lt;code&gt;@angular/core&lt;/code&gt;. Hence, &lt;code&gt;@angular/core&lt;/code&gt; does not need to be part of the bundle anymore.&lt;/p&gt;

&lt;p&gt;Please note that this is not the default operation mode for Angular and hence it comes with some risks. &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;With the right wrinkles, implementing a shell for micro elements is not that difficult. However, as outlined &lt;a href="https://www.softwarearchitekt.at/aktuelles/a-software-architects-approach-towards/" rel="noopener noreferrer"&gt;here&lt;/a&gt;, this is only one way for implementing micro apps and -- as all -- it comes with its very own advantages and disadvantages. Hence, before implementing it, make sure it fits your architectural goals.&lt;/p&gt;

&lt;h2&gt;
  
  
  More Free e-Book
&lt;/h2&gt;

&lt;p&gt;If you liked this article, you also may like my &lt;a href="https://leanpub.com/enterprise-angular" rel="noopener noreferrer"&gt;free e-Book on Angular Architecture&lt;/a&gt;, which can be found &lt;a href="https://leanpub.com/enterprise-angular" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Also, we offer an &lt;a href="https://www.softwarearchitekt.at/schulungen/advanced-angular-enterprise-anwendungen-und-architektur/" rel="noopener noreferrer"&gt;advanced Angular workshop&lt;/a&gt; containing this topic and more strategies for your Angular-based enterprise architectures.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.softwarearchitekt.at%2Fwp-content%2Fuploads%2F2019%2F11%2Febook.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.softwarearchitekt.at%2Fwp-content%2Fuploads%2F2019%2F11%2Febook.png"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>microfrontends</category>
      <category>externals</category>
      <category>microservices</category>
    </item>
    <item>
      <title>Sustainable Angular Architectures with Tactical DDD and MonoRepos?</title>
      <dc:creator>Manfred Steyer</dc:creator>
      <pubDate>Tue, 17 Sep 2019 18:16:30 +0000</pubDate>
      <link>https://dev.to/angular/sustainable-angular-architectures-with-tactical-ddd-and-monorepos-c61</link>
      <guid>https://dev.to/angular/sustainable-angular-architectures-with-tactical-ddd-and-monorepos-c61</guid>
      <description>&lt;p&gt;Business and industrial applications are usually long-lived. These applications include customer-facing applications layered with complex backend services and systems. Many of these applications are now implemented with web frontends using JavaScript. &lt;/p&gt;

&lt;p&gt;So how can we build and maintain such software systems?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Domain Driven Design (DDD)&lt;/strong&gt; provides the answer! Best of all, it is especially suitable for complex Angular solutions. &lt;/p&gt;

&lt;p&gt;In this article we will learn:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How &lt;strong&gt;Tactical Design (DDD)&lt;/strong&gt; helps to organize our source code as smaller, manageable, coherent parts.&lt;/li&gt;
&lt;li&gt;How &lt;strong&gt;monorepos&lt;/strong&gt; help implementing them&lt;/li&gt;
&lt;li&gt;How &lt;strong&gt;Facades&lt;/strong&gt; help with isolating your domain logic&lt;/li&gt;
&lt;li&gt;How client-side DDD paves the way to &lt;strong&gt;micro frontends&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;All these topics are also part of our advanced &lt;a href="https://www.softwarearchitekt.at/schulungen/advanced-angular-enterprise-anwendungen-und-architektur/" rel="noopener noreferrer"&gt;Angular Architecture workshop&lt;/a&gt;. Have a look at it if you're implementing business or industrial software with Angular!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As always, the examples used can be found in my &lt;a href="https://github.com/manfredsteyer/angular-ddd" rel="noopener noreferrer"&gt;GitHub account&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Big thanks to &lt;a href="https://twitter.com/ThomasBurleson" rel="noopener noreferrer"&gt;Thomas Burleson&lt;/a&gt; who deeply reviewed this article and contributed to it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Domain Decomposition
&lt;/h2&gt;

&lt;p&gt;Let's consider a consumer travel web application we are building. We have several domains that we can identify: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh4zbl3ptn9yqf33u5628.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh4zbl3ptn9yqf33u5628.png" alt="Domains" width="800" height="96"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To manage complexity of these domains, we should leverage &lt;strong&gt;Domain-Driven Design&lt;/strong&gt; and best practices from the Angular community. &lt;/p&gt;

&lt;p&gt;Domain Driven Design comes with the two types of design&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.softwarearchitekt.at/aktuelles/sustainable-angular-architectures-1/" rel="noopener noreferrer"&gt;Strategic Domain Design&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tactical Design&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While the former one is about identifying domains and the communication between them, tactical design deals with structuring these domains.&lt;/p&gt;

&lt;p&gt;I've already written about the use of &lt;strong&gt;&lt;a href="https://www.softwarearchitekt.at/aktuelles/sustainable-angular-architectures-1/" rel="noopener noreferrer"&gt;Strategic Design&lt;/a&gt;&lt;/strong&gt; in Angular applications. Have a look at this article for foundational understandings. Hence, here, I'll focus on Tactical Domain Design.&lt;/p&gt;

&lt;h2&gt;
  
  
  Applying Tactical Design
&lt;/h2&gt;

&lt;p&gt;Now let's talk about how to structure our application with tactical design.&lt;/p&gt;

&lt;h3&gt;
  
  
  Domain Organization using Layers
&lt;/h3&gt;

&lt;p&gt;For domains we use column subdivisions ("swimlanes"). Moreover, those domains can be organized with layers of libraries which leads to row subdivisions:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsax1qkb4ttrkw8vqxkk5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsax1qkb4ttrkw8vqxkk5.png" width="800" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note how each layer could consists one or more &lt;strong&gt;libraries&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;While using layers is quite a traditional way of organizing an domain, there are also alternatives like hexagonal architectures or clean architecture.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  What about shared functionality?
&lt;/h4&gt;

&lt;p&gt;For those aspects that are to be &lt;em&gt;shared&lt;/em&gt; and used across domains, an additional &lt;code&gt;shared&lt;/code&gt; swimlane is used. Shared libraries can be quite useful. Consider - for example - shared libraries for authentication or logging.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: the &lt;code&gt;shared&lt;/code&gt; swimlane corresponds to the Shared Kernel proposed by DDD and also includes technical libraries to share.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  How to prevent high coupling?
&lt;/h4&gt;

&lt;p&gt;Access constrains define which libraries can use/depend upon other libraries. Typically, each layer is only allowed to communicate with underlying layers. Cross-domain access is allowed only with the &lt;code&gt;shared&lt;/code&gt; area. The benefit of using these restrictions can result in loose coupling and thus increased maintainability. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;To prevent too much logic to be put into the &lt;code&gt;shared&lt;/code&gt; area, the approach presented here also uses APIs that publish building blocks for other domains. This corresponds to the idea of Open Services in DDD.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Regarding the shared part, one can see the following two characteristics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; As the grayed-out blocks indicate, most &lt;code&gt;util&lt;/code&gt; libraries are in the &lt;code&gt;shared&lt;/code&gt; area, especially as aspects such as authentication or logging are used across systems. &lt;/li&gt;
&lt;li&gt; The same applies to general UI libraries that ensure a system-wide look and feel.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  What about feature-specific functionality?
&lt;/h4&gt;

&lt;p&gt;Notice that domain-specific &lt;code&gt;feature&lt;/code&gt; libraries, however, are not in the &lt;code&gt;shared&lt;/code&gt; area. Feature-related code should be placed within its own domain. &lt;/p&gt;

&lt;p&gt;While developers may elect to share feature code (between domains), this practice can lead to shared responsibilities, more coordination effort, and breaking changes. Hence, it should only be shared sparingly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code Organization
&lt;/h3&gt;

&lt;p&gt;Based on Nrwl.io's &lt;a href="https://go.nrwl.io/angular-enterprise-monorepo-patterns-new-book" rel="noopener noreferrer"&gt;Enterprise MonoRepository Patterns&lt;/a&gt;, I distinguish between five categories of layers or libraries:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Exemplary content&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;feature&lt;/td&gt;
&lt;td&gt;Contains components for an use case.&lt;/td&gt;
&lt;td&gt;search-flight component&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ui&lt;/td&gt;
&lt;td&gt;Contains so-called "dumb components" that are use-case agnostic and thus reusable.&lt;/td&gt;
&lt;td&gt;datetime-component, address-component, adress-pipe&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;api&lt;/td&gt;
&lt;td&gt;Exports building blocks from the current subdomain for others.&lt;/td&gt;
&lt;td&gt;Flight API&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;domain&lt;/td&gt;
&lt;td&gt;Contains the &lt;strong&gt;domain models&lt;/strong&gt; (classes, interfaces, types) that are used by the domain (swimlane)&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;util&lt;/td&gt;
&lt;td&gt;Include general utility functions&lt;/td&gt;
&lt;td&gt;formatDate&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This complete architectural matrix is initially overwhelming. But after a brief review, almost all developers I've worked with agreed that the code organization facilitates code reuse and future features. &lt;/p&gt;

&lt;h3&gt;
  
  
  Isolate the Domain
&lt;/h3&gt;

&lt;p&gt;To isolate the domain logic, we hide it behind facades which represent it in an use-case specific way:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe6mzszcdzzikueyt37n0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe6mzszcdzzikueyt37n0.png" alt="Isolating the Domain Layer" width="800" height="364"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This facade can also deal with state mangement. Two excellent articles are available for deep dives into those areas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://medium.com/@thomasburlesonIA/ngrx-facades-better-state-management-82a04b9a1e39" rel="noopener noreferrer"&gt;Ngrx + Facades: Better State Management&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@thomasburlesonIA/push-based-architectures-with-rxjs-81b327d7c32d" rel="noopener noreferrer"&gt;Push-based Archtectures with RxJS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While Facades are currently quite popular in the Angular environment, this idea also correlates wonderfully with DDD (where they are called application services). &lt;/p&gt;

&lt;p&gt;It is important to architecturally separate &lt;em&gt;infrastructure requirements&lt;/em&gt; from the actual domain logic. &lt;/p&gt;

&lt;p&gt;In an SPA, infrastructure concerns are -- at least most of the time -- asynchronous communication with the server and data exchanges. Maintaining this separation results in three additional layers: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the application services/ facades, &lt;/li&gt;
&lt;li&gt;the actual domain layer, and &lt;/li&gt;
&lt;li&gt;the infrastructure layer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Of course, these layers can now also be packaged in their own libraries. For the sake of simplicity, it is also possible to store them in a single library, which is subdivided accordingly. This decision makes sense if these layers are usually used together and only need to be exchanged for unit tests.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementations in a Monorepos
&lt;/h3&gt;

&lt;p&gt;Once the components of our architecture have been determined, the question arises of how they can be implemented in the world of Angular. A very common approach also used by Google itself is using a monorepo. It is a code repository that contains all the libraries of a software system.&lt;/p&gt;

&lt;p&gt;While a project created with the Angular CLI can nowadays be used as a monorepo, the popular tool &lt;a href="https://nx.dev/" rel="noopener noreferrer"&gt;Nx&lt;/a&gt; offers some additional possibilities which are especially valuable for large enterprise solutions. These include the previously discussed ways to introduce &lt;a href="https://www.softwarearchitekt.at/aktuelles/sustainable-angular-architectures-2/" rel="noopener noreferrer"&gt;access restrictions between libraries&lt;/a&gt;. This prevents each library from accessing each other, resulting in a highly coupled overall system.&lt;/p&gt;

&lt;p&gt;To create a library in a monorepo, one instruction is enough:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ng generate library domain --directory boarding
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;As you just use &lt;code&gt;ng generate library&lt;/code&gt; instead of &lt;code&gt;ng generate module&lt;/code&gt; there is not more effort for you. However, you get a cleaner structure, improved maintainability, and less coupling.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The switch &lt;code&gt;directory&lt;/code&gt; provided by Nx specifies an optional subdirectory where the libraries are to be put. This way, they can be &lt;strong&gt;grouped by domain&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5mxi90jqqlnaj24popji.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5mxi90jqqlnaj24popji.png" alt="Monorepo with domains" width="189" height="327"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The names of the libraries also reflect the layers. &lt;br&gt;
If a layer has several libraries, it makes sense to use these names as a prefix. This results in names such as &lt;code&gt;feature-search&lt;/code&gt; or &lt;code&gt;feature-edit&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In order to isolate the actual domain model, the example shown here divides the domain library into the three further layers mentioned:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5mxi90jqqlnaj24popji.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5mxi90jqqlnaj24popji.png" width="189" height="327"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Builds within a Monorepo
&lt;/h4&gt;

&lt;p&gt;By looking at the git commit log, Nx can also identify which libraries are &lt;em&gt;affected by the latest code changes&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;This change information is used to recompile only the &lt;strong&gt;affected&lt;/strong&gt; libraries or just run their &lt;strong&gt;affected&lt;/strong&gt; tests. Obviously, this saves a lot of time on large systems that are stored in a repository as a whole.&lt;/p&gt;


&lt;h3&gt;
  
  
  Entities and your Tactical Design
&lt;/h3&gt;

&lt;p&gt;Tactical Design provides many ideas for structuring the domain layer. At the center of this layer, there are &lt;strong&gt;entities&lt;/strong&gt; the reflecting real world domain and constructs.  &lt;/p&gt;

&lt;p&gt;The following listing shows an enum and two entities that conform to the usual practices of object-oriented languages such as Java or C#.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;BoardingStatus&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="no"&gt;WAIT_FOR_BOARDING&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="no"&gt;BOARDED&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="no"&gt;NO_SHOW&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BoardingList&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;flightId&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;BoardingListEntry&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;entries&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;completed&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// getters and setters&lt;/span&gt;

  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setStatus&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;passengerId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;BoardingStatus&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Complex logic to update status&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BoardingListEntry&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="n"&gt;boarding&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// getters and setters&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As usual in OO-land, these entities use information hiding to ensure that their state remains consistent. You implement this with private fields and public methods that operate on them. &lt;/p&gt;

&lt;p&gt;These entities not only encapsulate data, but also business rules. At least the method &lt;code&gt;setStatus&lt;/code&gt; indicates this circumstance. Only for cases where business rules can not be meaningfully accommodated in an entity, DDD defines so-called domain services.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Entities that only represent data structures are frowned upon in DDD. The community calls them devaluing &lt;a href="https://martinfowler.com/bliki/AnemicDomainModel.html" rel="noopener noreferrer"&gt;bloodless (anemic)&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Tactical DDD with Functional Programming
&lt;/h3&gt;

&lt;p&gt;From an object-oriented point of view, the previous approach makes sense. However - with languages such as JavaScript and TypeScript - object-orientation is less important. &lt;/p&gt;

&lt;p&gt;Typescript is a multi-paradigm language in which Functional Programming plays a big role. Books dealing with Functional DDD can be found here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://pragprog.com/book/swdddf/domain-modeling-made-functional" rel="noopener noreferrer"&gt;Domain Modeling Made Funcitonal&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.amzn.com/1617292249" rel="noopener noreferrer"&gt;Functional and Reactive Domain Modeling&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With functional programming, the previously considered entity model would therefore be separated into a data part and a logic part. &lt;a href="https://www.amzn.com/0134434420" rel="noopener noreferrer"&gt;Domain-Driven Design Distilled&lt;/a&gt; which is one of the standard works for DDD and primarily relies on OOP, also admits that this rule change is necessary in the world of FP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;BoardingStatus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;WAIT_FOR_BOARDING&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;BOARDED&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;NO_SHOW&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;BoardingList&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;flightId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;BoardingListEntry&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;completed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;BoardingListEntry&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;passengerId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;BoardingStatus&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;updateBoardingStatus&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
                   &lt;span class="nx"&gt;boardingList&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;BoardingList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                   &lt;span class="nx"&gt;passengerId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                   &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;BoardingStatus&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;BoardingList&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="c1"&gt;// Complex logic to update status&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here the entities also use public properties. This practice is quite common in FP; the excessive use of getters and setters, which only delegate to private properties, is often ridiculed!&lt;/p&gt;

&lt;p&gt;Much more interesting, however, is the question of how the functional world avoids inconsistent states. The answer is amazingly simple: data structures are preferably &lt;strong&gt;immutable&lt;/strong&gt;. The keyword &lt;code&gt;readonly&lt;/code&gt; in the example shown emphasizes this.&lt;/p&gt;

&lt;p&gt;A part of the program that wants to change such objects has to clone it, and if other parts of the program have first validated an object for their own purposes, they can assume that it remains valid.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A wonderful side-affect of using immutable data structures is that change detection performance is optimized. No longer are &lt;em&gt;deep-comparisons&lt;/em&gt; required. Instead, a &lt;em&gt;changed&lt;/em&gt; object is actually a new instance and thus the object references will no longer be the same.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Tactial DDD with Aggregates
&lt;/h3&gt;

&lt;p&gt;To keep track of the components of a domain model, Tactical DDD combines entities into aggregates. In the last example, &lt;code&gt;BoardingList&lt;/code&gt; and &lt;code&gt;BoardingListEntry&lt;/code&gt; form such an aggregate.&lt;/p&gt;

&lt;p&gt;The state of all components of an aggregate must be consistent as a whole. For example, in the example outlined above, one could specify that &lt;code&gt;completed&lt;/code&gt; in &lt;code&gt;BoardingList&lt;/code&gt; may only be set to &lt;code&gt;true&lt;/code&gt; if no &lt;code&gt;BoardingListEntry&lt;/code&gt; has the status &lt;code&gt;WAIT_FOR_BOARDING&lt;/code&gt; .&lt;/p&gt;

&lt;p&gt;In addition, different aggregates may not reference each other through object references. Instead, they can use IDs. This should prevent unnecessary coupling between aggregates. Large domains can thus be broken down into smaller groups of aggregates.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://www.amzn.com/0134434420" rel="noopener noreferrer"&gt;Domain-Driven Design Distilled&lt;/a&gt; suggests making aggregates as small as possible. First of all, consider each entity as an aggregate and then merge aggregates that need to be changed together without delay.&lt;/p&gt;
&lt;/blockquote&gt;



&lt;h2&gt;
  
  
  Facades
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://go.nrwl.io/angular-enterprise-monorepo-patterns-new-book" rel="noopener noreferrer"&gt;Facades&lt;/a&gt;&lt;/strong&gt; (aka Applications Services) are used to represent the domain logic in an use case specific way. The provide several advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Encapsulating complexity&lt;/li&gt;
&lt;li&gt;Taking care about state management&lt;/li&gt;
&lt;li&gt;Simplified APIs &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Independent of DDD, this idea has been very popular in the world of Angular for some time. &lt;/p&gt;

&lt;p&gt;For our example, we could create the following Facade:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;providedIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FlightFacade&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;notifier&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;BehaviorSubject&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Flight&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;    
    &lt;span class="k"&gt;public&lt;/span&gt;  &lt;span class="nx"&gt;flights$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;notifier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;asObservable&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;flightService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FlightService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;urgent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;flightService&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;urgent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
              &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;flights&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;notifier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;flights&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
              &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;err&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the use of RxJS and observables in the facade. This means that the facade can auto-deliver updated flight information when conditions change. Another advantage of Facades is the ability to transparently introduce Redux and &lt;code&gt;@ngrx/store&lt;/code&gt; later when needed. This can be done without affecting any of the external application components. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For the consumer of the Facade it is not relevant whether it manages the state by it self or by delegating to a state management library.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Developers are encouraged to read/watch Thomas Burleson's work about this topic:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Blog article &lt;a href="https://medium.com/@thomasburlesonIA/push-based-architectures-with-rxjs-81b327d7c32d" rel="noopener noreferrer"&gt;Push-based Architectures using RxJS + Facades&lt;/a&gt;, or &lt;/li&gt;
&lt;li&gt;YouTube video &lt;a href="https://www.youtube.com/watch?v=HnNytR32Otk&amp;amp;t=1s" rel="noopener noreferrer"&gt;Push-based Architectures with RxJS&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Stateless Facades
&lt;/h3&gt;

&lt;p&gt;While it is a good practice to make server-side services stateless, often this goal is not performant for services in web/client-tier. &lt;/p&gt;

&lt;p&gt;A web SPA has state and that's what makes it user-friendly!&lt;/p&gt;

&lt;p&gt;To avoid UX issues, Angular applications do not want to reload all the information from the server over and over again. Hence, the Facade outlined holds the loaded flights (within the observable discussed  before).&lt;/p&gt;

&lt;h2&gt;
  
  
  Domain Events
&lt;/h2&gt;

&lt;p&gt;Besides performance improvements, using Observables provide a further advantage. Observables allow further decoupling, since the sender and the receiver do not have to know each other directly. &lt;/p&gt;

&lt;p&gt;This also perfectly fits to DDD, where the use of &lt;strong&gt;domain events&lt;/strong&gt; are now part of the architecture. If something interesting happens in one part of the application, it sends a domain event and other application parts can react to it. &lt;/p&gt;

&lt;p&gt;In the shown example, a domain event could indicate that a passenger is now BOARDED. If this is interesting for other parts of the system they can execute specific logics. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For Angular developers familiar with Redux or Ngrx: Domain events can be represented as &lt;em&gt;dispatched actions&lt;/em&gt;!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Domain-Driven Design and Micro Frontends?
&lt;/h2&gt;

&lt;p&gt;The ideas of Domain-Driven Design are known to pave the way for micro-service architectures. Hence, client-side DDD can be used as a basis for micro frontends.&lt;/p&gt;

&lt;p&gt;Whether a deployment monolith, micro frontends, or anything in between is created, depends on the use of the monorepo. If the monorepo gets an own application for each domain, a big step towards micro frontends is taken:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8higxp503ks5as1s0z1n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8higxp503ks5as1s0z1n.png" alt="DDD on the Client as the Basis for Micro Frontends" width="800" height="314"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The access restrictions discussed above ensure a loose coupling and even allow a later split to multiple repositories. Then you can talk about micro frontends in the classic sense of a micro-service architecture. However, in this case the team has to take care of versioning and distributing shared libraries which is common with micro-services.&lt;/p&gt;

&lt;p&gt;More thoughts about this topic can be found in my blog article &lt;a href="https://www.softwarearchitekt.at/aktuelles/its-about-cutting-your-domain-not-first-and-foremost-about-micro-frontends/" rel="noopener noreferrer"&gt;It’s about cutting your domain, not (first and foremost) about micro frontends!&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Modern single page applications (SPAs) are often more than just recipients of data transfer objects (DTOs). They often contain significant domain logic which adds complexity. Ideas from DDD help developers to manage and scale with the resulting complexity.&lt;/p&gt;

&lt;p&gt;Due to the object-functional nature of TypeScript and prevailing customs, a few rule changes are necessary. For instance, we usually use immutables and separate data structures from the logics operating on them.&lt;/p&gt;

&lt;p&gt;The implementation outlined here bases upon the following ideas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The use of monorepos with multiple libraries grouped by domains helps building the basic structure.&lt;/li&gt;
&lt;li&gt;Access restrictions between libraries prevent coupling between domains. &lt;/li&gt;
&lt;li&gt;Facades prepare the domain model for individual use cases and take care of maintaining the state. &lt;/li&gt;
&lt;li&gt;If needed, Redux can be used behind the facade without the rest of the application noticing. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Besides, a team also creates the conditions for micro frontends by using client-side DDD.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you want to see all these topics in action, checkout our &lt;a href="https://www.softwarearchitekt.at/schulungen/advanced-angular-enterprise-anwendungen-und-architektur/" rel="noopener noreferrer"&gt;Angular Architecture workshop&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>angular</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Architecture with Angular Ivy - Part 1: A possible future without NgModules?</title>
      <dc:creator>Manfred Steyer</dc:creator>
      <pubDate>Fri, 16 Aug 2019 10:23:09 +0000</pubDate>
      <link>https://dev.to/angular/a-possible-future-without-ngmodules-4i2d</link>
      <guid>https://dev.to/angular/a-possible-future-without-ngmodules-4i2d</guid>
      <description>&lt;p&gt;In this post I want to show:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔭 How a possible future without (with optional) NgModules could look like&lt;/li&gt;
&lt;li&gt;🐹 How we can prepare for this future already today&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;a href="https://github.com/manfredsteyer/angular-without-modules" rel="noopener noreferrer"&gt;source code&lt;/a&gt; used for the examples can be found &lt;a href="https://github.com/manfredsteyer/angular-without-modules" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DISCLAIMER&lt;/strong&gt;: The examples here are an &lt;em&gt;experiment&lt;/em&gt; showing a possible direction Angular might be heading to. Hence, it's not production ready and it &lt;em&gt;does not&lt;/em&gt; reflect the Angular teams's official vision. Nethertheless, it shows what's possible with Ivy and it leads to a conclusion about &lt;em&gt;how we can prepare already today&lt;/em&gt; for a future without &lt;code&gt;NgModules&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  A little history
&lt;/h2&gt;

&lt;p&gt;When Angular -- back than called Angular 2 -- was envisioned, the team didn't plan to implement an own module system. While this was necessary in the times of AngularJS 1.x, the idea for Angular (2+) was to just leverage EcmaScript modules introduced in 2015. &lt;/p&gt;

&lt;p&gt;And so, Angular Modules have been among several AngularJS 1.x aspects that should have been skipped in the upcoming version of Google's SPA flagship. The following graphic, taken out of &lt;a href="https://twitter.com/igorminar?lang=de" rel="noopener noreferrer"&gt;Igor Minar&lt;/a&gt;'s and &lt;a href="https://twitter.com/tbosch1009?lang=de" rel="noopener noreferrer"&gt;Tobias Bosch&lt;/a&gt;'s presentation at ngEurope 2014 in Paris emphasizes this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsnhe96c8y4p9emxrox3h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsnhe96c8y4p9emxrox3h.png" alt="AngularJS 1.0 aspects skipped for Angular" width="274" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, during the development of Angular it became obvious, that Angular Modules can come in handy for several reasons. One reason was lazy loading; another reason was the need to provide context for the Angular compiler. This is because the compiler needs to know which components, directives, and pipes are available within a template.&lt;/p&gt;

&lt;p&gt;On the contrary, Ivy has a different strategy to define the compilation context -- at least under the covers. The next section gives some details about this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compilation Context for Ivy
&lt;/h2&gt;

&lt;p&gt;One of the benefits of Ivy is that it produces simpler code. During compilation, it just adds a static &lt;code&gt;ɵcmp&lt;/code&gt; property to components. This property contains a definition object describing the component for the compiler. &lt;/p&gt;

&lt;p&gt;Similarly, the compiler adds also such a definition to directives and pipes. They are called &lt;code&gt;ɵdir&lt;/code&gt; and &lt;code&gt;ɵpipe&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can even access it at runtime:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;def&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ComponentDef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AppComponent&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;AppComponent&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ɵcmp&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;def&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;def&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The respective console output would look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frvw1uvzg9ae40se06tbs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frvw1uvzg9ae40se06tbs.png" alt="console output of ComponentDef" width="466" height="874"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you see here, these properties contain everything Angular needs to know when executing the component. Perhaps you've noticed the &lt;code&gt;directiveDefs&lt;/code&gt; and &lt;code&gt;pipeDefs&lt;/code&gt; properties. They contain the compilation context for the template we've talked about above. &lt;/p&gt;

&lt;p&gt;The first one points to an array of definitions for directives and components. Saying this, a component definition is just a special kind of a directive definition. Alternatively, &lt;code&gt;directiveDefs&lt;/code&gt; can point to a factory function returning such an array. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;pipeDefs&lt;/code&gt; property does the same for pipe definitions.&lt;/p&gt;

&lt;p&gt;This way, Angular knows which (sub-)components, directives, and pipes are available in a component's template.&lt;/p&gt;

&lt;p&gt;Now, you might wonder how those properties are filled with the right values. In order to prevent breaking changes, the Ivy compiler just looks up the necessary entries in the component's module as well as in all other modules imported there. After this, it adds the found components, directives, and pipes to &lt;code&gt;directiveDefs&lt;/code&gt; or &lt;code&gt;pipeDefs&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;However, if we wanted to use Ivy without modules, we could directly populate these two property. The next section provides some information about this idea.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compilation Context without NgModules
&lt;/h2&gt;

&lt;p&gt;Technically, it's possible to directly add the compilation context to &lt;code&gt;directiveDefs&lt;/code&gt; and &lt;code&gt;pipeDefs&lt;/code&gt;. Unfortunately, these properties are not part of Angular's public API currently. &lt;/p&gt;

&lt;p&gt;This is for a reason: First of all, the Angular team concentrates on making sure Ivy is completely backwards compatible. Only than, they will introduce new features based upon Ivy step by step. &lt;/p&gt;

&lt;p&gt;When that happens, the &lt;code&gt;Component&lt;/code&gt; decorator might get some additional properties for this reason.&lt;/p&gt;

&lt;p&gt;As the next section shows, we can already have a short look into this possible future today. &lt;/p&gt;

&lt;h2&gt;
  
  
  Calming the Angular-Compiler
&lt;/h2&gt;

&lt;p&gt;While this all will work at runtime, it might cause some troubles during compilation due some of the Angular compiler's checks. For instance, it checks whether the used components and pipes are available by looking into &lt;code&gt;NgModules&lt;/code&gt;. Of course, these checks will not work in our case as the goal was to work without them.&lt;/p&gt;

&lt;p&gt;To calm the compiler, we should turn of fullTemplateTypeCheck in &lt;code&gt;tsconfig.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"angularCompilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"fullTemplateTypeCheck"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"strictInjectionParameters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, we should import the &lt;code&gt;NO_ERRORS_SCHEMA&lt;/code&gt; into out &lt;code&gt;AppModule&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;NgModule&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nx"&gt;BrowserModule&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;declarations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nx"&gt;AppComponent&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;schemas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nx"&gt;NO_ERRORS_SCHEMA&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
    &lt;span class="na"&gt;bootstrap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nx"&gt;AppComponent&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppModule&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case study, the &lt;code&gt;AppModule&lt;/code&gt; is the only module used. Technically, we could even get rid of this module.&lt;br&gt;
Instead, we could just bootstrap the &lt;code&gt;AppComponent&lt;/code&gt; using Ivy's &lt;code&gt;ɵrenderComponent&lt;/code&gt; function which is also part of the private API. However, this would make things more complicated as &lt;code&gt;renderComponent&lt;/code&gt; is currently not supporting automatic change detection out of the box.&lt;/p&gt;
&lt;h2&gt;
  
  
  Directly Providing the Compilation Context
&lt;/h2&gt;

&lt;p&gt;As directly providing the compilation context is not possible with public APIs today, this section directly leverages the available private ones. Of course, they can change and hence the techniques outlined here are &lt;strong&gt;not feasible for production&lt;/strong&gt; code. &lt;/p&gt;

&lt;p&gt;Nethertheless, this experiment shows how modern Angular code might look like in the future. It also leads to a conclusion that tells us, how we can prepare for this future. &lt;/p&gt;

&lt;p&gt;To demonstrate how to directly provide the compilation context, I'm using a simple example here. It just contains a &lt;code&gt;tabbed-pane&lt;/code&gt; which displays one of several &lt;code&gt;tab&lt;/code&gt;s at a time:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxrt4uep1xjsg6omkg1xu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxrt4uep1xjsg6omkg1xu.png" alt="Tabbed Pane example" width="627" height="467"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The example's &lt;code&gt;AppComponent&lt;/code&gt; uses them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;tabbed-pane&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;tab&lt;/span&gt; &lt;span class="na"&gt;title=&lt;/span&gt;&lt;span class="s"&gt;"Tab 1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Lorem ipsum ...
  &lt;span class="nt"&gt;&amp;lt;/tab&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;tab&lt;/span&gt; &lt;span class="na"&gt;title=&lt;/span&gt;&lt;span class="s"&gt;"Tab 2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Lorem ipsum ...
  &lt;span class="nt"&gt;&amp;lt;/tab&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;tab&lt;/span&gt; &lt;span class="na"&gt;title=&lt;/span&gt;&lt;span class="s"&gt;"Tab 3"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Lorem ipsum ...
  &lt;span class="nt"&gt;&amp;lt;/tab&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/tabbed-pane&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For showing and hiding the tabs, the &lt;code&gt;TabbedPaneComponent&lt;/code&gt; uses Angular's &lt;code&gt;*ngIf&lt;/code&gt; directive and for displaying the link it uses &lt;code&gt;*ngFor&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If we want to provide the compilation context directly to these components, we need to get hold of the respective definition objects. For this, I've created a helper function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Type&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ɵComponentDef&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;ComponentDef&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;[...]&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getComponentDef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;ComponentDef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ɵcmp&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ɵcmp&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;ComponentDef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;No Angular definition found for &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you might have noticed, the &lt;code&gt;ComponentDef&lt;/code&gt; class is prefixed with the &lt;code&gt;ɵ&lt;/code&gt; sign. This denotes that the class is still part of Angular's private API.&lt;/p&gt;

&lt;p&gt;I've written similar helper functions for getting &lt;code&gt;DirectiveDef&lt;/code&gt;s and &lt;code&gt;PipeDef&lt;/code&gt;s:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getDirectiveDef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;DirectiveDef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ɵdir&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ɵdir&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;DirectiveDef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// A Component(Def) is also a Directive(Def)&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ɵcmp&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ɵcmp&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;ComponentDef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;No Angular definition found for &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getPipeDef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;PipeDef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ɵpipe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ɵpipe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;PipeDef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;No Angular definition found for &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Similarly, I've written helper functions for getting all the definition objects from an array of directives and an array of pipes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getDirectiveDefs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;types&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="nx"&gt;DirectiveDef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getDirectiveDef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getPipeDefs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;types&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="nx"&gt;PipeDef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getPipeDef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Please note that the former one is also respecting component definitions, as a component definition is a special kind of a directive definition. Technically, &lt;code&gt;ComponentDef&lt;/code&gt; even inherits &lt;code&gt;DirectiveDef&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Using these helpers, we can easily add the compilation context to our components:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;[...]&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;demo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Adding compilation context&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;def&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getComponentDef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AppComponent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;def&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;directiveDefs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="nf"&gt;getDirectiveDef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;TabComponent&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
  &lt;span class="nf"&gt;getDirectiveDef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;TabbedPaneComponent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the sake of simplicity, I'm overwriting the &lt;code&gt;directiveDefs&lt;/code&gt; property here. This means that values the compiler placed there after traversing possibly existing modules are overwritten too.&lt;/p&gt;

&lt;p&gt;Of course, adding the same definition objects time and again to different consuming objects is annoying. However, we could group components belonging together using a central array:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;TABBED_PANE_COMPONENTS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;TabbedPaneComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;TabComponent&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To import this array, we can use our &lt;code&gt;getDirectiveDef&lt;/code&gt; helper function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;def&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;directiveDefs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nf"&gt;getDirectiveDefs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;TABBED_PANE_COMPONENTS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Similarly to this, I've written a file exporting all the directives I need from &lt;code&gt;@angular/common&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;COMMON_DIRECTIVES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;NgIf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;NgForOf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// etc.&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This one is used for the &lt;code&gt;TabbedPaneComponent&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;[...]&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TabbedPaneComponent&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;AfterContentInit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;[...]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;def&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getDef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;TabbedPaneComponent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;def&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;directiveDefs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
     &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nf"&gt;getDefs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;COMMON_DIRECTIVES&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Of course, as we have just two components, this is not a big win here but in bigger scenarios with lots of components using such an array comes quite in handy. &lt;/p&gt;

&lt;p&gt;As patching a component after defining it is somewhat brutal, the next section shows a better way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Providing the compilation context with a decorator
&lt;/h2&gt;

&lt;p&gt;To add the compilation context to components in a way we are more used to as Angular developers, I've written a simple decorator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ComponentDepsConfig&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;directives&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="nl"&gt;pipes&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ComponentDeps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ComponentDepsConfig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;def&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getComponentDef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;def&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;directiveDefs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nf"&gt;getDirectiveDefs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;directives&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="nx"&gt;def&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pipeDefs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nf"&gt;getPipeDefs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pipes&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To be more precise, this is a factory for a decorator. It takes a config object containing the compilation context and returns a decorator for a component. This decorator adds the context to the component's definition.&lt;/p&gt;

&lt;p&gt;Now, let's apply this decorator to our components:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;[...]&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;ComponentDeps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;directives&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; 
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;TABBED_PANE_COMPONENTS&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;demo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This looks a lot like the envisioned possible future where the component decorator directly takes the compilation context. Also, Angular's &lt;a href="https://twitter.com/mgechev" rel="noopener noreferrer"&gt;Minko Gechev&lt;/a&gt; created a &lt;a href="https://github.com/mgechev/angular-ivy-demo" rel="noopener noreferrer"&gt;prototype of Angular&lt;/a&gt; which uses this idea. It's Component decorator come with a &lt;code&gt;deps&lt;/code&gt; property that serves the same purpose. One more time, this is all is about showing what's possible and it doesn't reflect the Angular teams's official vision.&lt;/p&gt;

&lt;p&gt;However, now the question is what can we learn from this case study. The next section provides an answer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preparing for a possible future without (with optional) NgModules
&lt;/h2&gt;

&lt;p&gt;In this article, we've seen that we need a compilation context. If we don't have something like &lt;code&gt;NgModules&lt;/code&gt; we could assign it directly to our components. This is already possible by using internal APIs and the respective properties might eventually be exposed a part of Angular's public API.&lt;/p&gt;

&lt;p&gt;We've also seen that even in this case, it's in handy to group components, directives, or pipes belonging together. For this reason we've used a simple array:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;TABBED_PANE_COMPONENTS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;TabbedPaneComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;TabComponent&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Interestingly, this array look like the &lt;code&gt;export&lt;/code&gt; part of an NgModule. However, this is pure EcmaScript which makes its simpler and easier to understand.&lt;/p&gt;

&lt;p&gt;Also, it's obvious that even in a future without &lt;code&gt;NgModules&lt;/code&gt; we need a way to group parts of our code. We will also need some way of information hiding which means we have to define public and private parts of our APIs. Fortunately, this can also be accomplished with pure EcmaScript by using barrels.&lt;/p&gt;

&lt;p&gt;For instance, in my case study, the &lt;code&gt;tabbed-pane&lt;/code&gt; folder has the following &lt;code&gt;index.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./tab.component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./tabbed-pane.component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// array with components&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./components&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;app.component.ts&lt;/code&gt; imports this barrel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;TABBED_PANE_COMPONENTS&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./tabbed-pane&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can even go one step further and use a monorepo with different libraries. Each library gets a barrel which defines the public API. Thanks to the Angular CLI creating libraries to group your code is very easy. It's just a matter of one command (&lt;code&gt;ng generate lib my-lib&lt;/code&gt;) and it also makes your code more reusable. &lt;/p&gt;

&lt;p&gt;Furthermore, when using &lt;a href="https://nx.dev" rel="noopener noreferrer"&gt;Nrwl's Nx&lt;/a&gt; for creating an Angular CLI based monorepo, you can also &lt;a href="https://www.softwarearchitekt.at/post/2019/03/04/sustainable-angular-architectures-with-strategic-design-and-monorepos-part-2-implementation.aspx" rel="noopener noreferrer"&gt;define access restrictions between your libraries&lt;/a&gt;. Also, it contains linting rules preventing that someone uses private parts of your APIs by bypassing their barrels.&lt;/p&gt;

&lt;p&gt;This all leads to my advice for preparing for this possible future without (with optional) Angular modules.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;As you have seen here, we can already prepare today for a possible future without (with optional) NgModules. It's as easy as that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Cut your application into libraries and use barrels to define their public APIs.&lt;/li&gt;
&lt;li&gt;When NgModules become optional, replace them with an their &lt;code&gt;export&lt;/code&gt; arrays.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Finally, let me tell you the best: Regardless, if this possible future will happen or not, this advice makes a lot of sense anyway, because cutting your application into tiny libraries with a public and a private part leads to a more robust architecture.&lt;/p&gt;

</description>
      <category>angular</category>
      <category>architecture</category>
      <category>ivy</category>
    </item>
  </channel>
</rss>
