<?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: Narcisa</title>
    <description>The latest articles on DEV Community by Narcisa (@blminami).</description>
    <link>https://dev.to/blminami</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%2F874868%2F4eff35b4-bcdb-4a87-841a-7605fb810944.jpeg</url>
      <title>DEV Community: Narcisa</title>
      <link>https://dev.to/blminami</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/blminami"/>
    <language>en</language>
    <item>
      <title>[Micro frontends] NX + Angular Module Federation + React MFE using ChatGPT</title>
      <dc:creator>Narcisa</dc:creator>
      <pubDate>Fri, 17 Mar 2023 15:36:05 +0000</pubDate>
      <link>https://dev.to/blminami/micro-frontends-nx-angular-module-federation-react-mfe-using-chatgpt-1nkn</link>
      <guid>https://dev.to/blminami/micro-frontends-nx-angular-module-federation-react-mfe-using-chatgpt-1nkn</guid>
      <description>&lt;p&gt;Let's have a quick discussion about the things we've built so far and what's new as part of the micro frontends series.&lt;/p&gt;

&lt;h3&gt;
  
  
  Table of contents
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Recap&lt;/li&gt;
&lt;li&gt;What's new&lt;/li&gt;
&lt;li&gt;Challenges&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Recap &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;We started from the Angular Tour of Heroes and migrated the monolithic architecture to micro frontends, by creating a host and remote applications as part of the same NX workspace. In terms of applications:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the shell application is based on Angular framework&lt;/li&gt;
&lt;li&gt;2 remote applications use Angular&lt;/li&gt;
&lt;li&gt;1 remote application uses Vue.js&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What's new&lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;So far so good, but I also wanted to plug in a React remote application and see how it behaves in terms of integration. Well, instead of going through a step-by-step tutorial, let's see the challenges I faced during the development.&lt;br&gt;
From the code perspective, the entire configuration, app development and deployments can be found here:&lt;br&gt;
&lt;a href="https://github.com/blminami/tour-of-heroes-microfrontends"&gt;https://github.com/blminami/tour-of-heroes-microfrontends&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Considering it's a POC, the react application consists of a single page, where we display the React logo and a message. I'm going to use this app to actual code something in React, but for the purpose of today's article, it's enough.&lt;/p&gt;

&lt;p&gt;Check out the react configuration here: &lt;a href="https://github.com/blminami/tour-of-heroes-microfrontends/tree/master/apps/calendar-microapp"&gt;https://github.com/blminami/tour-of-heroes-microfrontends/tree/master/apps/calendar-microapp&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tour of Heroes App: &lt;a href="https://master--tour-of-heroes-mfe.netlify.app/"&gt;https://master--tour-of-heroes-mfe.netlify.app/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The questions I wanted to answer this week:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How easy is it to create a react application and integrate it as part of the mfe architecture?&lt;/li&gt;
&lt;li&gt;Would ChatGPT help me with this project, considering I have minimal experience with React + Webpack 5 and Module Federation? &lt;/li&gt;
&lt;li&gt;How far can I get without using Stack Overflow or official documentations &lt;em&gt;myself&lt;/em&gt; (using only ChatGPT and my own knowledge)?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Challenges &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;🔸 How easy is it to create a react application and integrate it as part of the mfe architecture?&lt;/p&gt;

&lt;p&gt;Overall, pretty easy, considering that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;NX supports React without custom configuration, there is a &lt;a href="https://nx.dev/packages/react"&gt;plugin&lt;/a&gt; for generating react applications as part of an NX workspace&lt;/li&gt;
&lt;li&gt;I already have experience configuring a Vue.js app as a web-component, and React is no different&lt;/li&gt;
&lt;li&gt;the configuration of the shell application allows the usage of remote modules, no matter the framework / library it's based upon&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔸 What about ChatGPT as part of this experiment?&lt;/p&gt;

&lt;p&gt;Considering I already had a direction, I was curious if ChatGPT would make it even easier for me to do the configuration.&lt;/p&gt;

&lt;p&gt;✨ Short answer: it was not straight-forward and I had to input multiple prompts (which implied some knowledge about the process on my side), but I was able to integrate it from scratch, without using any external resources myself. Which is great, right?&lt;/p&gt;

&lt;p&gt;Let's get into details, shall we?&lt;/p&gt;

&lt;p&gt;ChatGPT would be helpful on its own to some extent, but it'd require some knowledge on the topic and architecture to actually make it work in this context: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There are multiple approaches when it comes to micro frontends. So, prompts like &lt;code&gt;integrate react micro frontend in nx workspace and angular shell app&lt;/code&gt; won't work. 
&lt;em&gt;been there, done that&lt;/em&gt; - in this case, it instructs to create a react application, build and export it, create NX library that uses the application and import the library as part of the Angular shell application. Which is valid, but not at all consistent with the remote modules architecture in place.
&lt;code&gt;integrate react micro frontend in nx workspace and angular shell app with webpack module federation&lt;/code&gt; is more appropriate for this goal, cuz the steps provided are based on webpack and module federation.&lt;/li&gt;
&lt;li&gt;The prompt above generated the steps that one should follow to integrate a react application. Those contained bits of documentation (only relevant parts), code snippets and cli commands. Even though it seemed pretty straight-forward at first glance, some commands generated errors and I had to explicitly request webpack 5 version (some libraries were outdated).&lt;/li&gt;
&lt;li&gt;I continued with requesting a webpack config file that uses the module federation plugin. The one provided was useful, tho quite generic. Great start, but once I ran the app based on that webpack config file, I got errors (OF COURSE, I was expecting them 😈).&lt;/li&gt;
&lt;li&gt;Based on the errors I received, adjustments to use the right paths  + additional configurations and rules for different file formats were required. I could have asked ChatGPT for them (considering I already knew what was missing), but I decided to speed-up the process and add them myself.🙂&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Same thing, just faster. 😄 &lt;br&gt;
Which leads me to the next question.&lt;/p&gt;

&lt;p&gt;🔸 How far can I get without using Stack Overflow or official documentations &lt;em&gt;myself&lt;/em&gt; and using only ChatGPT and my own knowledge?&lt;/p&gt;

&lt;p&gt;Simply said, I made it work solely on ChatGPT and my knowledge, but check my comments above. It was not &lt;em&gt;easy peasy lemon squeezy&lt;/em&gt;, but not that hard either. ☯️&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;In the end, I declare myself satisfied with my experiment, I got what I wanted. My curiosity can take a break now, hehe ^_^. &lt;br&gt;
Next time, I'm going to play a bit with the ChatGPT API.💥&lt;/p&gt;

&lt;p&gt;What are your thoughts and which are your experiences with ChatGPT and coding?&lt;/p&gt;

&lt;p&gt;Until next time, thank you for reading! 🐾&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>chatgpt</category>
      <category>discuss</category>
      <category>programming</category>
    </item>
    <item>
      <title>[Tailwind CSS] From CSS to Tailwind CSS</title>
      <dc:creator>Narcisa</dc:creator>
      <pubDate>Fri, 03 Mar 2023 12:02:12 +0000</pubDate>
      <link>https://dev.to/blminami/tailwindcss-from-css-to-tailwindcss-413m</link>
      <guid>https://dev.to/blminami/tailwindcss-from-css-to-tailwindcss-413m</guid>
      <description>&lt;p&gt;As part of the Micro Frontends series, we developed some micro applications based on Angular (dashboard micro application and heroes micro application). We started from the Angular Tour of Heroes tutorial and until now, we didn't care about anything related to styling.&lt;/p&gt;

&lt;p&gt;Check-out the repository for the source code &lt;a href="https://github.com/blminami/tour-of-heroes-microfrontends" rel="noopener noreferrer"&gt;https://github.com/blminami/tour-of-heroes-microfrontends&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Today, we're going to add Tailwind CSS to our NX workspace and style the dashboard application. Have a look at the screenshots below (before and after) to see what we want to achieve.&lt;/p&gt;

&lt;p&gt;Before&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%2Fmi30glv57pb1k2peup87.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%2Fmi30glv57pb1k2peup87.png" alt=" " width="800" height="161"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After&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%2Fawuejsp8566ftlh5fgqp.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%2Fawuejsp8566ftlh5fgqp.png" alt=" " width="800" height="160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's start by running the following command which will add tailwindcss config to the workspace:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx nx generate @nrwl/angular:setup-tailwind dashboard-microapp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;According to the &lt;a href="https://nx.dev/recipes/other/using-tailwind-css-in-react#automated-setup" rel="noopener noreferrer"&gt;NX documentation&lt;/a&gt;, the command will install the dependencies and add the configuration files.&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;// tailwind.config.js&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createGlobPatternsForDependencies&lt;/span&gt; &lt;span class="p"&gt;}&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;@nrwl/angular/tailwind&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;join&lt;/span&gt; &lt;span class="p"&gt;}&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;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="cm"&gt;/** @type {import('tailwindcss').Config} */&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;content&lt;/span&gt;&lt;span class="p"&gt;:&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;src/**/!(*.stories|*.spec).{ts,html}&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;createGlobPatternsForDependencies&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="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;primary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#E4B363&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;secondary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#074F57&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;cordovan&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#c45663&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;dark-bg&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;#242424&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="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="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As part of &lt;code&gt;tailwind.config.js&lt;/code&gt; file, we can extend the default theme by adding custom colors and other properties. For demo purposes, I updated the color palette to include some new colors.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* dashboard.component.css */&lt;/span&gt;

&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;components&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;utilities&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, we have to import TailwindCSS bases style. In order to work in the micro frontend context, the styles have to be added at component level, instead of &lt;code&gt;styles.css&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Now that the configuration is done, we can switch to the html files and use the pre-defined classes to style the components. &lt;/p&gt;

&lt;p&gt;First thing, let's have a look at the &lt;code&gt;hero-search&lt;/code&gt; component, which exposes the functionality to search a hero by name.&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;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex flex-col items-center mb-4"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt;
    &lt;span class="na"&gt;#searchBox&lt;/span&gt;
    &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"search-box"&lt;/span&gt;
    &lt;span class="na"&gt;(input)=&lt;/span&gt;&lt;span class="s"&gt;"search(searchBox.value)"&lt;/span&gt;
    &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Search for a hero"&lt;/span&gt;
    &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"shadow appearance-none border rounded w-2/5 py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"&lt;/span&gt;
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt;
    &lt;span class="na"&gt;*ngIf=&lt;/span&gt;&lt;span class="s"&gt;"heroes$ | async as heroes; else null"&lt;/span&gt;
    &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"shadow appearance-none border bg-white rounded w-2/5 py-2 px-3 text-gray-700 leading-tight mt-px cursor-pointer"&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;*ngFor=&lt;/span&gt;&lt;span class="s"&gt;"let hero of heroes"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"mt-1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;routerLink=&lt;/span&gt;&lt;span class="s"&gt;"/heroes/detail/{{ hero.id }}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        {{ hero.name }}
      &lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/ul&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;/div&gt;



&lt;p&gt;It consists of an input element and a list of heroes that meet the search criteria. We would like to have the 2 elements on separated rows and centered. To achieve it, we add a div container with the following classes &lt;code&gt;class="flex flex-col items-center mb-4"&lt;/code&gt; which applies flex display, centers the items and add a margin bottom.&lt;br&gt;
Let's also have a look at the input element and the classes &lt;code&gt;class="shadow appearance-none border rounded w-2/5 py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"&lt;/code&gt;&lt;br&gt;
What we got: an element with shadow, rounded border (border-radius: 0.25rem; /* 4px */), width 40%, vertical and horizontal padding (py-2 px-3) and gray-700 text color.&lt;br&gt;
For more details, check out the &lt;a href="https://tailwindcss.com/docs/installation" rel="noopener noreferrer"&gt;Tailwind documentation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, let's give life to our heroes! Instead of displaying boring hero cards, let's have an image, a name and a description of their super powers. We display the top heroes, after all, they deserve some recognition for their powers, right?😄 &lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;in-memory-data.service.ts&lt;/code&gt;, update the heroes array and add the following properties to each object: id, name, description, image. Find the new array of data &lt;a href="https://github.com/blminami/tour-of-heroes-microfrontends/blob/master/libs/core/src/lib/services/in-memory-data.service.ts" rel="noopener noreferrer"&gt;here&lt;/a&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="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;13&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bombasto&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
          &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Telekinesis: The hero can move objects with their mind, allowing them to lift heavy objects or even people&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://i.postimg.cc/3wZMGqn8/11-2-anime-png-picture.png&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;For each hero, we're going to have a container that has rounded corners, box-shadow, cursor pointer and a gradient as background color (you can be creative with the gradients, here is a interesting list of options &lt;a href="https://hypercolor.dev/" rel="noopener noreferrer"&gt;https://hypercolor.dev/&lt;/a&gt;)&lt;br&gt;
&lt;code&gt;class="rounded flex shadow-lg mb-2 mr-2 bg-gradient-to-br from-gray-200 via-gray-400 to-gray-600 cursor-pointer"&lt;/code&gt;. &lt;br&gt;
Also, we're going to display the name, image and description of the hero, in 2 different columns.&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;div&lt;/span&gt;
      &lt;span class="na"&gt;*ngFor=&lt;/span&gt;&lt;span class="s"&gt;"let hero of heroes"&lt;/span&gt;
      &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"rounded flex shadow-lg mb-2 mr-2 bg-gradient-to-br from-gray-200 via-gray-400 to-gray-600 cursor-pointer"&lt;/span&gt;
      &lt;span class="na"&gt;routerLink=&lt;/span&gt;&lt;span class="s"&gt;"/heroes/detail/{{ hero.id }}"&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt;
        &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"object-contain h-52 w-40 self-center"&lt;/span&gt;
        &lt;span class="na"&gt;[src]=&lt;/span&gt;&lt;span class="s"&gt;"hero.image || defaultImage"&lt;/span&gt;
        &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"hero image"&lt;/span&gt;
      &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"px-6 py-4"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"font-bold text-xl mb-2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{ hero.name }}&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-test text-base"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
          {{ hero.description }}
        &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
      &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;/div&gt;



&lt;p&gt;Results:&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%2Fodkoo6nzkue596kt0us5.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%2Fodkoo6nzkue596kt0us5.png" alt=" " width="487" height="251"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Easy-peasy, right? 🥳&lt;/p&gt;

&lt;p&gt;✨Check out the &lt;a href="https://github.com/blminami/tour-of-heroes-microfrontends" rel="noopener noreferrer"&gt;Github repo&lt;/a&gt; for the entire configuration!&lt;/p&gt;

&lt;p&gt;Until next time, thank you for reading! 🐾&lt;/p&gt;

</description>
      <category>resources</category>
    </item>
    <item>
      <title>[Micro frontends] NX + Angular Module Federation + Angular MFE + VueJs MFE</title>
      <dc:creator>Narcisa</dc:creator>
      <pubDate>Fri, 24 Feb 2023 12:42:11 +0000</pubDate>
      <link>https://dev.to/blminami/micro-frontends-nx-angular-module-federation-angular-mfe-vuejs-mfe-13hi</link>
      <guid>https://dev.to/blminami/micro-frontends-nx-angular-module-federation-angular-mfe-vuejs-mfe-13hi</guid>
      <description>&lt;p&gt;This article is part of a micro frontends series and a continuation of &lt;a href="https://dev.to/blminami/getting-started-with-micro-frontends-3g79"&gt;[Micro frontends] Getting Started&lt;/a&gt;, where we covered what we want to build, the application architecture, the initial NX workspace, Angular micro frontends and Angular Module Federation.&lt;/p&gt;

&lt;p&gt;The aim of this article is to create a VueJs micro frontend and integrate it in the NX workspace.&lt;/p&gt;

&lt;p&gt;The starting point is a VueJs application added to our workspace - for the record, NX doesn't support VueJs app generation, so simply generate a web application using webpack and babel compiler and add the vue dependencies (vue/cli, vue-loader, etc.). &lt;/p&gt;

&lt;p&gt;The application is configured on port 4203. By starting the application,  we can see the VueJs application, which uses Webpack and Typescript.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx nx run messages-microapp:serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Source code: &lt;a href="https://github.com/blminami/tour-of-heroes-microfrontends/tree/nx-angular-vue-mfe-css/apps/messages-microapp" rel="noopener noreferrer"&gt;https://github.com/blminami/tour-of-heroes-microfrontends/tree/nx-angular-vue-mfe-css/apps/messages-microapp&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F99mvm94h8ggf81zxvqj2.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F99mvm94h8ggf81zxvqj2.png" alt="Image description" width="621" height="211"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  How do we setup the messages application as a micro frontend?
&lt;/h3&gt;

&lt;p&gt;We're going to wrap our application in Web Components. Check out the code below to see how a VueJs component can be wrapped:&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="c1"&gt;// bootstrap.ts&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;createApp&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;vue&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="nx"&gt;Messages&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;./app/components/Messages.vue&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./styles.css&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;MfeVue&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;HTMLElement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;connectedCallback&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;createApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Messages&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;mount&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="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;customElements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;messages-element&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MfeVue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;main.ts&lt;/code&gt; file, add the following import to bootstrap the application async:&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="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And finally, configure the &lt;code&gt;webpack.config.js&lt;/code&gt; file by adding the &lt;a href="https://webpack.js.org/concepts/module-federation/" rel="noopener noreferrer"&gt;ModuleFederationPlugin&lt;/a&gt;. By doing so, we instruct webpack which files to make available for remote consumption:&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;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;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;messages_microapp&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;library&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;var&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&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="s1"&gt;messages_microapp&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="s1"&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;./messages-wc&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;apps/messages-microapp/src/bootstrap.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="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;dependencies&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;Once the setup is done, run the serve command and navigate to &lt;code&gt;http://localhost:4203/remoteEntry.js&lt;/code&gt;, where the remote module is available and ready to be used.&lt;/p&gt;

&lt;p&gt;Let's setup the shell application, which uses Angular framework and Angular Module Federation. There is a plugin available for loading remote web components:  &lt;a href="https://www.npmjs.com/package/@angular-architects/module-federation-tools" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/@angular-architects/module-federation-tools&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i @angular-architects/module-federation-tools
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For this example, we're going to directly load the messages web component like this:&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;mft-wc-wrapper&lt;/span&gt; &lt;span class="na"&gt;[options]=&lt;/span&gt;&lt;span class="s"&gt;"item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/mft-wc-wrapper&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;where&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;item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;WebComponentWrapperOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;type&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="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:4203/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;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;./messages-wc&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;messages_microapp&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;elementName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;messages-element&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;ul&gt;
&lt;li&gt;
&lt;em&gt;remoteEntry&lt;/em&gt;: where the remote application is deployed (in our case, localhost, port 4203)&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;exposedModule&lt;/em&gt;: configured in Micro Frontend's webpack configuration&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;remoteName&lt;/em&gt;: configured in Micro Frontend's webpack configuration&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;elementName&lt;/em&gt;: configured in Micro Frontend's bootstrap file&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;WebComponentWrapperOptions&lt;/em&gt; - imported from '@angular-architects/module-federation-tools'&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For it to work, add &lt;code&gt;ModuleFederationToolsModule&lt;/code&gt; to &lt;code&gt;app.module.ts&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In case of loading the web component by route, there is an example in the &lt;a href="https://github.com/blminami/tour-of-heroes-microfrontends/blob/master/apps/tour-of-heroes/src/app/app-routing.module.ts" rel="noopener noreferrer"&gt;app-routing.module.ts&lt;/a&gt;, where navigating to &lt;code&gt;/messages&lt;/code&gt; will load the remote web component.&lt;/p&gt;

&lt;p&gt;Let's run the application and see what we got:&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flggob2bp338fhvjf7jh6.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flggob2bp338fhvjf7jh6.png" alt="Image description" width="800" height="444"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;run:all command was updated to start the messages application as well:&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="s2"&gt;"run:all"&lt;/span&gt;: &lt;span class="s2"&gt;"nx run-many --targets=serve  
--maxParallel=4 
--projects=dashboard-microapp,heroes-microapp,messages-microapp,tour-of-heroes"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✨It's super easy to plugin a new Micro-Frontend into an existing workspace by using Module Federation and Webpack 5! &lt;/p&gt;

&lt;p&gt;Check out the &lt;a href="https://github.com/blminami/tour-of-heroes-microfrontends/tree/nx-angular-vue-mfe-css" rel="noopener noreferrer"&gt;Github repo&lt;/a&gt; for the entire configuration! &lt;/p&gt;

&lt;p&gt;Until next time, thank you for reading! 🐾&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>tutorial</category>
      <category>vue</category>
    </item>
    <item>
      <title>[Micro frontends] Resources</title>
      <dc:creator>Narcisa</dc:creator>
      <pubDate>Fri, 17 Feb 2023 09:31:45 +0000</pubDate>
      <link>https://dev.to/blminami/micro-frontends-resources-1338</link>
      <guid>https://dev.to/blminami/micro-frontends-resources-1338</guid>
      <description>&lt;p&gt;As I'm focusing more and more on micro frontends and combining different libraries and frameworks in the same application, I want to share some great resources that I found on the topic:&lt;/p&gt;

&lt;h3&gt;
  
  
  Github repositories:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/Coly010/nx-angular-mf-ssr-example" rel="noopener noreferrer"&gt;Angular MF SSR + NX&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ilya-isupov/multi-framework-module-federation" rel="noopener noreferrer"&gt;Multi framework module federation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/incora-dev/Microfrontend-Angular" rel="noopener noreferrer"&gt;Angular Microfrontend&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/harshmons/micro-front-end-react-application" rel="noopener noreferrer"&gt;React Microfrontend&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nabeel-shakeel/react-vue-microfrontend" rel="noopener noreferrer"&gt;React + Vue + NX Microfrontends&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/angular-architects/module-federation-plugin/blob/main/libs/mf-tools/tutorial/index.md" rel="noopener noreferrer"&gt;Module federation plugin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/manfredsteyer/vue-js" rel="noopener noreferrer"&gt;Vue Js app&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Articles:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.angulararchitects.io/aktuelles/the-microfrontend-revolution-module-federation-in-webpack-5/" rel="noopener noreferrer"&gt;Angular Architects&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nx.dev/more-concepts/micro-frontend-architecture" rel="noopener noreferrer"&gt;NX Microfrontend architecture&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nx.dev/recipes/module-federation/faster-builds" rel="noopener noreferrer"&gt;NX Module Federation Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=s_Fs4AXsTnA" rel="noopener noreferrer"&gt;Micro frontends Module Federation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=EzJF0IUoYhQ" rel="noopener noreferrer"&gt;Angular Module Federation Micro-FE Speed Run&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Courses:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://app.pluralsight.com/library/courses/micro-frontends-architecture/table-of-contents" rel="noopener noreferrer"&gt;Microfrontends Architecture&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'm going to keep this article up-to-date with all the interesting stuff that I'm finding!!!&lt;/p&gt;

&lt;p&gt;Until next time, thank you for reading! 🐾&lt;/p&gt;

</description>
      <category>seo</category>
      <category>marketing</category>
      <category>webdev</category>
      <category>productivity</category>
    </item>
    <item>
      <title>[Micro frontends] Getting Started</title>
      <dc:creator>Narcisa</dc:creator>
      <pubDate>Fri, 10 Feb 2023 08:09:38 +0000</pubDate>
      <link>https://dev.to/blminami/getting-started-with-micro-frontends-3g79</link>
      <guid>https://dev.to/blminami/getting-started-with-micro-frontends-3g79</guid>
      <description>&lt;p&gt;At the beginning of this week, I took a course on micro frontends architecture topic. It's such a buzzword when it comes to frontend development, but I've never attempted anything in practice until this week.&lt;/p&gt;

&lt;h3&gt;
  
  
  Table of contents
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Application architecture&lt;/li&gt;
&lt;li&gt;Prerequisites&lt;/li&gt;
&lt;li&gt;Step-by-step tutorial&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;li&gt;Additional resources&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Introduction &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;When it comes to microservices, the backend services have this architecture in place for several years already. So why not taking advantage of all the benefits and start developing micro applications / micro components that can be owned, developed, managed and maintained by different teams. Of course, that's only one of the advantages (vertical teams that will handle a feature end-to-end), but we can also talk about the ability to scale the product by working on different features / modules in parallel,  speed of delivery, support for innovation and new technologies, more reliable testing and maximum decoupling.&lt;/p&gt;

&lt;p&gt;Let's see how it goes in practice!&lt;/p&gt;

&lt;h3&gt;
  
  
  Application architecture &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;I've decided to start from the well-known Angular Tour of Heroes tutorial and split the codebase into micro apps. There are a few approaches when it comes to splitting monolithic applications into micro frontends, I chose to do it by feature. The application provides two major features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;dashboard:  top heroes + search heroes capability&lt;/li&gt;
&lt;li&gt;heroes: list of heroes + hero management capabilities (view here, add hero, delete hero)&lt;/li&gt;
&lt;/ul&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%2F3i5d5dihb89mq2ua1n1k.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%2F3i5d5dihb89mq2ua1n1k.png" alt="Tour of heroes dashboard page" width="800" height="318"&gt;&lt;/a&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%2F7d4q24ev6mcjsnqn32sl.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%2F7d4q24ev6mcjsnqn32sl.png" alt="Tour of heroes hero page" width="661" height="527"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Considering the split by feature, I've decided on the following architecture of my application:&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%2F0gmi9ddn6ba8o9doepf5.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%2F0gmi9ddn6ba8o9doepf5.png" alt="Tour of heroes architecture" width="663" height="413"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;shell application&lt;/em&gt; is the app that will host all the remote micro applications (dashboard and heroes) and will handle everything related to the navigation (navigation component and routing logic)&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;dashboard micro application&lt;/em&gt; is one of the remote applications, targeting the dashboard feature&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;heroes micro application&lt;/em&gt; is the second remote application, targeting the heroes feature&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Prerequisites for Angular micro frontends: &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;NodeJs 10.13.0+&lt;/li&gt;
&lt;li&gt;Webpack 5&lt;/li&gt;
&lt;li&gt;Angular 12+&lt;/li&gt;
&lt;li&gt;NX&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step-by-step tutorial &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;🔸 download the &lt;a href="https://angular.io/tutorial/tour-of-heroes/toh-pt0" rel="noopener noreferrer"&gt;Angular Tour of Heroes&lt;/a&gt; application &lt;br&gt;
🔸 open terminal to the root directory and run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; nx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔸 transform the Angular cli workspace to an integrated NX monorepository (all the micro frontends will be part of the NX monorepo for simplicity)&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 @nrwl/angular@&amp;lt;version_number&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔸 get rid of all the unused files, configs, packages and components to keep it simple and focus on the micro apps (remove the message component and e2e files)&lt;br&gt;
🔸 run the application locally to check that all the changes made so far didn't affect the app&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx nx build tour-of-heroes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So far, you should be able to navigate to &lt;code&gt;http://localhost:4200&lt;/code&gt; and check the application in the browser.&lt;/p&gt;

&lt;p&gt;Let's keep having fun:&lt;/p&gt;

&lt;p&gt;🔸 generate NX Angular application for dashboard-microapp and hero-microapp using nx cli&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx nx generate @nrwl/angular:app dashboard-microapp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx nx generate @nrwl/angular:app heroes-microapp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔸 add angular module federation plugin to all apps (shell, dashboard, hero)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx nx g @angular-architects/module-federation:init 
&lt;span class="nt"&gt;--project&lt;/span&gt; tour-of-heroes &lt;span class="nt"&gt;--port&lt;/span&gt; 4200 &lt;span class="nt"&gt;--type&lt;/span&gt; host
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx nx g @angular-architects/module-federation:init 
&lt;span class="nt"&gt;--project&lt;/span&gt; dashboard-microapp &lt;span class="nt"&gt;--port&lt;/span&gt; 4201 &lt;span class="nt"&gt;--type&lt;/span&gt; remote
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx nx g @angular-architects/module-federation:init 
&lt;span class="nt"&gt;--project&lt;/span&gt; heroes-microapp &lt;span class="nt"&gt;--port&lt;/span&gt; 4202 &lt;span class="nt"&gt;--type&lt;/span&gt; remote
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;This command will do a couple of things: add webpack.config.js, webpack.prod.config.js, bootstrap.js files and additional configurations (more details &lt;a href="https://nx.dev/recipes/module-federation/dynamic-module-federation-with-angular#what-was-generated" rel="noopener noreferrer"&gt;here&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;apps&lt;/code&gt; folder should 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%2F9ixcy5gd1fj9ioenx0vh.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%2F9ixcy5gd1fj9ioenx0vh.png" alt="Application folder" width="261" height="619"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🔸 let's consider the dashboard-microapp (same will apply to hero-microapp). At this point, in &lt;code&gt;src&lt;/code&gt; folder, you have an Angular app configuration - with app.module, app.component.ts, app.component.html and app.component.css. We're going to create a new component, module and routing for the Dashboard feature&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ng generate module dashboard &lt;span class="nt"&gt;--project&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;dashboard-microapp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔸 move the logic from the initial application (dashboard and hero-search components) to the dashboard application (you can copy paste the components and update the imports in case the IDE doesn't handle it)&lt;br&gt;
🔸 configure the &lt;code&gt;dashboard.module.ts&lt;/code&gt; as follow (by importing modules, declaring routes and components):&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;remoteRoutes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;[]&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="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="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;DashboardComponent&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;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;CommonModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="nx"&gt;HttpClientModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="nx"&gt;FormsModule&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;forChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;remoteRoutes&lt;/span&gt;&lt;span class="p"&gt;),&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;DashboardComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HeroSearchComponent&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;DashboardModule&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔸 expose DashboardModule in &lt;code&gt;webpack.config.js&lt;/code&gt;:&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="p"&gt;{&lt;/span&gt; 
  &lt;span class="nx"&gt;withModuleFederationPlugin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
&lt;span class="p"&gt;}&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;@angular-architects/module-federation/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="nf"&gt;withModuleFederationPlugin&lt;/span&gt;&lt;span class="p"&gt;({&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="s1"&gt;dashboard-microapp&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="s1"&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;./apps/dashboard-microapp/src/app/dashboard/dashboard.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="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔸 now that you got the functionality moved to the micro-app and the module configured for this feature, update the app.module.ts:&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="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;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;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="nx"&gt;HttpClientModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="c1"&gt;// optional: setting in-memory-web-api for microapps so we can test them separately &lt;/span&gt;
    &lt;span class="nx"&gt;HttpClientInMemoryWebApiModule&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="nx"&gt;InMemoryDataService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
      &lt;span class="na"&gt;dataEncapsulation&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="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="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="p"&gt;,&lt;/span&gt; 
          &lt;span class="na"&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;./dashboard/dashboard.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="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;m&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;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DashboardModule&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="na"&gt;initialNavigation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;enabledBlocking&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="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To test everything related to dashboard-microapp, let's run it in the browser and see what we get:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm start dashboard-microapp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;navigate to &lt;a href="http://localhost:4201" rel="noopener noreferrer"&gt;http://localhost:4201&lt;/a&gt; and you should be able to see the dashboard app:&lt;/p&gt;
&lt;/blockquote&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%2Fx37fnfl4r5lfstzqsjfu.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%2Fx37fnfl4r5lfstzqsjfu.png" alt="Image description" width="711" height="259"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🔸 repeat the same steps for hero-microapp (generate module, move functionality, update hero.module.ts file and app.module.ts, run it in browser and check that everything works as expected).&lt;/p&gt;

&lt;p&gt;So far, we have 2 microapps that are running independently in the browser, how do we integrate them into the shell application so we can create the illusion of a single application for the end user? &lt;/p&gt;

&lt;p&gt;🔸 switch to shell application (tour-of-heroes) and adjust webpack.config.js:&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="p"&gt;{&lt;/span&gt; 
  &lt;span class="nx"&gt;shareAll&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;withModuleFederationPlugin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
&lt;span class="p"&gt;}&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;@angular-architects/module-federation/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="nf"&gt;withModuleFederationPlugin&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="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="p"&gt;...&lt;/span&gt;&lt;span class="nf"&gt;shareAll&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="na"&gt;requiredVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;auto&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="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;keep remotes: {} for dynamic consumption of micro applications&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;🔸 load the micro apps lazily when it's routed to:&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;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="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="p"&gt;,&lt;/span&gt; 
    &lt;span class="na"&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:4201/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;type&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="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="p"&gt;)&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;DashboardModule&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;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;heroes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="na"&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:4202/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;type&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="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="p"&gt;)&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;HeroesModule&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;🔸 run all the applications&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run run:all
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and navigate to &lt;a href="http://localhost:4200" rel="noopener noreferrer"&gt;http://localhost:4200&lt;/a&gt;. You should be able to see the Tour of heroes application - same as in the beginning, because nothing changed for the end user. &lt;/p&gt;

&lt;p&gt;Hoooray! That was it! 🥳&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;This is my first attempt at micro frontends, I hope it clarifies the initial steps and configuration of the micro frontend architecture and encourages you to consider it for your future projects. I'll keep playing with it and document my stories while learning new stuff, so stay tuned! ^_^&lt;/p&gt;

&lt;h3&gt;
  
  
  Additional resources: &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://angular.io/tutorial/tour-of-heroes" rel="noopener noreferrer"&gt;Angular Tour of Heroes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://angular.io/tutorial/tour-of-heroes/toh-pt0" rel="noopener noreferrer"&gt;Angular Tour of Heroes code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nx.dev/recipes/adopting-nx/migration-angular#transforming-an-angular-cli-workspace-to-an-integrated-nx-monorepo" rel="noopener noreferrer"&gt;Migrate Angular workspace to Nx monorepo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.angulararchitects.io/en/aktuelles/the-microfrontend-revolution-module-federation-in-webpack-5/" rel="noopener noreferrer"&gt;Angular Module Federation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nx.dev/recipes/module-federation/dynamic-module-federation-with-angular" rel="noopener noreferrer"&gt;Advanced Angular Micro Frontends with Dynamic Module Federation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://app.pluralsight.com/library/courses/micro-frontends-architecture/table-of-contents" rel="noopener noreferrer"&gt;Pluralsight Micro Frontends Architecture&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/blminami/tour-of-heroes-microfrontends" rel="noopener noreferrer"&gt;Github repo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Until next time, thank you for reading! 🐾&lt;/p&gt;

</description>
      <category>angular</category>
      <category>frontend</category>
      <category>discuss</category>
      <category>webdev</category>
    </item>
    <item>
      <title>[Discussion] 5 years of *professional* coding OR how I earn money while having fun</title>
      <dc:creator>Narcisa</dc:creator>
      <pubDate>Wed, 01 Feb 2023 17:47:32 +0000</pubDate>
      <link>https://dev.to/blminami/5-years-of-professional-coding-or-how-i-earn-money-while-having-fun-488b</link>
      <guid>https://dev.to/blminami/5-years-of-professional-coding-or-how-i-earn-money-while-having-fun-488b</guid>
      <description>&lt;p&gt;Considering I've always loved to share my own experiences and stories, it's time to a have a tour down the memory lane and reflect on my past (and first) 5 years of professional coding. If you're at the beginning of your own journey, you might find some useful tips to avoid some mistakes. After all, we're here to learn from one another and I encourage you to reflect on your path as well.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✨ Background ✨
&lt;/h3&gt;

&lt;p&gt;I got my first job right after finishing the second year at university, a summer internship at a company in my town. I still remember the interview, it was on paper and consisted of many questions from object-oriented programming concepts, algorithms, data structure, AI, databases and exercises that required actual coding - quite normal for an internship / entry level position, as it covers general knowledge and logical thinking.&lt;/p&gt;

&lt;p&gt;Once I got the job, I spent the first 2 months learning about the MEAN stack and developing an internal application based on those technologies. Next, I spent 1 year working on different projects (around 6 months each), covering all stages of an application - from the initial discussions with the clients to understand their needs and what should be built, to translating client's needs into technical requirements, choosing the technologies and frameworks, developing, deploying and testing the application. &lt;/p&gt;

&lt;p&gt;Most of my expertise is around web technologies as 4 out of 5 years were spent on this area, but I also worked on server side for 1 year, building microservices using Go language, creating scripts for automating different processes, administrating databases and, generally, having fun in the terminal. It was one of the craziest years of my life: working for a start-up as a junior, as part of a team full of senior engineers and with little to no knowledge about the technologies I was using - deploying services to production for a world-wide application, well, never before, it was intimidating at first - to say the least 😅. &lt;/p&gt;

&lt;p&gt;Once I got bored (yep, bored 💤) of the server side thingy, I switched back to front-end development where I had the chance to work on some legacy applications, while also developing and contributing to some big projects. It was quite different than anything I did before because:&lt;/p&gt;

&lt;p&gt;〰️ I was working within a mixed team of front-end developers, back-end developers, designers and QA engineers;&lt;br&gt;
〰️ there were many standards and quality checks in place to make sure everything is properly delivered;&lt;br&gt;
〰️ tons of meetings (cuz hey, out of nowhere, I was part of the corporate life).&lt;/p&gt;

&lt;p&gt;So, I got from working for some small clients as a full-stack developer, to working as a back-end engineer for a start-up (did I mention the extra extra extra hours ☠️), to being part of the corporate life as a senior software engineer. Pretty fun, right?&lt;/p&gt;




&lt;h3&gt;
  
  
  ✨ What would I do the same? ✨
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;everything except some things, of course 🤣&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Considering I was following tech courses at university and I was preparing for a career in the IT field, the fact that I got my first job as a developer helped me a lot (instead of spending time doing some other jobs).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip #1&lt;/strong&gt;: if you know what you want, go and work hard for it, don't let yourself get distracted.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;🔸start on smaller projects (chance to get first-hand experience on a software development cycle). In order to develop great software, it's important to understand every step of the process;&lt;br&gt;
🔸work for a start-up  - other than learning new things extremely fast and using the latest technologies, I was constantly out of my comfort zone as I was performing under pressure;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip #2&lt;/strong&gt;: start as part of a small team, small project or dynamic environment to speed up the learning process&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;🔸struggle with some technical tasks on my own, before asking for help. When you're a junior (and not only), everything feels new, different and hard. It's easier to ask for help, especially if you're surrounded by people willing to guide you, but sometimes it's better to solve bugs on your own. Not only it'll force you to read and learn more, but it'll boost your confidence as well;&lt;br&gt;
🔸give 100% of myself at the job, not because I'm asked to, but because of my mindset and the things I want to achieve;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip #3&lt;/strong&gt;:  go all the way&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;🔸mentor other people. Something I've always valued - give back and help others whenever you can.&lt;/p&gt;




&lt;h3&gt;
  
  
  ✨ What would I do differently? ✨
&lt;/h3&gt;

&lt;p&gt;🔸I would stress less and set some healthy boundaries at work. I didn't do it while working for the start-up (everyone knows that such a project requires a lot of dedication), though I maintain a reasonable workload nowadays;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip #4&lt;/strong&gt;: Set boundaries at work to achieve a great work-life balance&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;🔸I would take more time off. Guess what, the projects will go on, even if you take a holiday every trimester for example. Also, I would disconnect entirely, no applications on my phone, no notifications, no messages during that time. It might sound extreme, but it's important for the mental health on the long run;&lt;br&gt;
🔸I would say &lt;strong&gt;no&lt;/strong&gt; more often. Just because you can do something or you have the time and resources, it doesn't mean you have to;&lt;br&gt;
🔸I would document the technical challenges I face. Write articles, quick snippets of code or quick notes about everything and contribute to open-source;&lt;br&gt;
🔸I would take part in more hackathons as it's a great opportunity to learn new technical skills, play with new technologies, network and meet people with similar interests.&lt;/p&gt;




&lt;h3&gt;
  
  
  ✨ Recommendations ✨
&lt;/h3&gt;

&lt;p&gt;🔸All tips above should be considered recommendations😉;&lt;br&gt;
🔸Don't neglect open-source and writing about your journey, tech challenges and topics. Share as much as you can with others. You can bring huge contribution to the community while forcing yourself to get out of your comfort zone. This is how you grow;&lt;br&gt;
🔸Challenge yourself with new projects, new technologies and keep learning new skills that will help you reach your goals. You're the one responsible for your own career, don't let it in the hands of someone else;&lt;br&gt;
🔸Take guidance from your team and have mentors, but don't expect every challenge you face to be solved by others;&lt;br&gt;
🔸Read a lot (no matter the topic) and take notes. Everything connects, and you never know how you wake up one day with an idea. Knowledge is power nowadays;&lt;br&gt;
🔸Meet deadlines, learn how to prioritize tasks and how to estimate effort, maintain high code quality standards;&lt;br&gt;
🔸Test your code ‼️;&lt;br&gt;
🔸Read the documentation before attempting any implementation. It'll save you hours / days 📄;&lt;br&gt;
🔸Be aware of every step in the process, even if it doesn't fall within your responsibilities;&lt;br&gt;
🔸Stay curious and be resourceful.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✨ Conclusion ✨
&lt;/h3&gt;

&lt;p&gt;I plan on continuing this series yearly, as I'll do a lot of growing meanwhile. If you have any recommendations or additional tips (and I'm sure there are plenty of things that can be mentioned), let's hear it in the comments section.&lt;/p&gt;

&lt;p&gt;Until next time, thank you for reading! 🐾&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>productivity</category>
      <category>writing</category>
      <category>motivation</category>
    </item>
    <item>
      <title>[NestJs] Resolve Request rate is large - Azure CosmosDB error 16500</title>
      <dc:creator>Narcisa</dc:creator>
      <pubDate>Mon, 14 Nov 2022 15:17:10 +0000</pubDate>
      <link>https://dev.to/blminami/resolve-request-rate-is-large-azure-cosmosdb-error-16500-in-nestjs-51o1</link>
      <guid>https://dev.to/blminami/resolve-request-rate-is-large-azure-cosmosdb-error-16500-in-nestjs-51o1</guid>
      <description>&lt;p&gt;If you're familiar with Azure CosmosDB, you may have heard of / encountered the &lt;strong&gt;16500 error - Request rate is large&lt;/strong&gt;. Well, I knew about it, but I don't remember fixing it in the past, at least not using NestJS. What is it about? This error occurs when the request rate to the database is too high. In my case, I tried to populate a collection with some seed data (around 200 new records).&lt;/p&gt;

&lt;p&gt;What's the solution? There are a couple of ways to solve it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Increase the Request Unit (RU) value in Azure CosmosDB&lt;/strong&gt;  - which, of course, implies additional costs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Batch requests&lt;/strong&gt; - instead of making individual requests, you can batch your requests together. This will reduce the overall request rate and help resolve the issue.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement some sort of &lt;strong&gt;retry mechanism&lt;/strong&gt; -  by configuring the application to automatically retry requests that fail due to the Request rate is large error.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's see how we can implement the third solution. In our case, we're going to insert some data into a collection and retry until a). all records are inserted b). retry count is reached.&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="kr"&gt;private&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;insertManyWithRetry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Model&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TestDocument&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;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;
    &lt;span class="nx"&gt;retries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&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;retries&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Done retrying&lt;/span&gt;&lt;span class="dl"&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="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;insertMany&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&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;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="mi"&gt;16500&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="nx"&gt;InternalServerErrorException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&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;processedRecordsIds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;insertedDocs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;elem&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;elem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&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;unprocessedRecords&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;)&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;processedRecordsIds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;await&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;insertManyWithRetry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;unprocessedRecords&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;retries&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;delay&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;Let's have a look at the function &lt;code&gt;insertManyWithRetry&lt;/code&gt;, it receives the following parameters: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;collection&lt;/code&gt; - where we want to store data&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;data&lt;/code&gt; - array of JSON documents&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;retries&lt;/code&gt; - limit of retries, if none provided, default value is 10&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;delay&lt;/code&gt; - time to wait until next retry, if none provided, default value is 300ms&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;First, we're going to insert data into the collection. This request can be either successful or generate an error, which will be caught by the error block. &lt;/p&gt;

&lt;p&gt;According to the &lt;a href="https://www.mongodb.com/docs/manual/reference/method/db.collection.insertMany/"&gt;MongoDB documentation&lt;/a&gt;, the &lt;code&gt;insertMany&lt;/code&gt; method will return this sort of document in case of write error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BulkWriteError({
   "writeErrors" : [
      {
         "index" : 24,
         "code" : 16500,
         "errmsg" : "Response status code does not indicate success: TooManyRequests (429)",
         "op" : {
            "_id" : 13,
         }
      }
   ],
   "writeConcernErrors" : [ ],
   "insertedDocs": [ ],
   "nInserted" : 1,
   "nUpserted" : 0,
   "nMatched" : 0,
   "nModified" : 0,
   "nRemoved" : 0,
   "upsert
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tells us all we need to know about our request - what's the error message, error code and which operation / document generated the error. It also provides some stats about the documents (how many were modified or upserted, etc.) and the array of the documents that were inserted.&lt;/p&gt;

&lt;p&gt;In case of error: &lt;br&gt;
1). if the error code is not 16500 =&amp;gt; log and throw an internal server error exception. &lt;br&gt;
2). if the error code is 16500 =&amp;gt; make another attempt at inserting data, once the documents that were already inserted are filtered out. &lt;br&gt;
In our case, unprocessed records are stored in the &lt;code&gt;unprocessedRecords&lt;/code&gt; variable. We can invoke the function again, with the new values: &lt;code&gt;await this.insertManyWithRetry(collection, unprocessedRecords, retries - 1);&lt;/code&gt;, which: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;can be successful and insert all the remaining documents&lt;/li&gt;
&lt;li&gt;can generate a new 16500 error =&amp;gt; re-apply the same mechanism (check the error, filter out inserted documents and retry with a delay of 300 ms)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's it. The implementation can be enhanced by logging more information, errors and retry attempts and using promises, but the logic remains the same.&lt;/p&gt;

&lt;p&gt;Any thoughts?&lt;/p&gt;

&lt;p&gt;Additional resources on the topic:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.mongodb.com/docs/manual/reference/method/db.collection.insertMany/"&gt;MongoDB documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/cosmos-db/mongodb/prevent-rate-limiting-errors"&gt;Prevent rate-limiting errors for Azure Cosmos DB for MongoDB operations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/cosmos-db/mongodb/error-codes-solutions"&gt;Common issues in Azure Cosmos DB&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thank you for reading! 🐾&lt;/p&gt;

</description>
      <category>programming</category>
      <category>mongodb</category>
      <category>node</category>
      <category>typescript</category>
    </item>
    <item>
      <title>[NestJs] Intercept axios responses and throw built-in HTTP errors for the exception filter</title>
      <dc:creator>Narcisa</dc:creator>
      <pubDate>Tue, 25 Oct 2022 10:11:08 +0000</pubDate>
      <link>https://dev.to/blminami/nestjs-intercept-axios-responses-and-throw-built-in-http-errors-for-the-exception-filter-1dd3</link>
      <guid>https://dev.to/blminami/nestjs-intercept-axios-responses-and-throw-built-in-http-errors-for-the-exception-filter-1dd3</guid>
      <description>&lt;h6&gt;
  
  
  Context
&lt;/h6&gt;

&lt;p&gt;How do we intercept the external http calls made by our NestJs server, so we can log and better handle the errors?&lt;br&gt;
&lt;code&gt;NestJs Interceptors&lt;/code&gt; are able to process the requests and the responses made via the controllers, not the external http calls that we might need as part of a controller request. &lt;/p&gt;
&lt;h6&gt;
  
  
  Solutions
&lt;/h6&gt;

&lt;p&gt;One solution would be to add a &lt;code&gt;catchError&lt;/code&gt; on the http call. &lt;a href="https://docs.nestjs.com/techniques/http-module#full-example"&gt;NestJs documentation&lt;/a&gt; provides a full example and extensive information on &lt;code&gt;HttpModule&lt;/code&gt; and &lt;code&gt;HttpService&lt;/code&gt; from &lt;code&gt;@nestjs/axios package&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;What if we already have a couple of axios requests and we don't want to add catchError block on each request? Here comes the second solution: &lt;strong&gt;axios response interceptors&lt;/strong&gt; and &lt;strong&gt;exception filters&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;First, let's consider this call as part of our service, where (hypothetically) our http call will throw an error:&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;//app.service.ts&lt;/span&gt;
&lt;span class="nx"&gt;getCats&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;Observable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&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="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;httpService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&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:3001/cats&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;data&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Do something&lt;/span&gt;&lt;span class="dl"&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;data&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;Let's configure the &lt;code&gt;axios response interceptor&lt;/code&gt;. We're going to add this snippet as part of the bootstrap function. All &lt;code&gt;HttpService&lt;/code&gt; methods return an &lt;code&gt;AxiosResponse&lt;/code&gt; wrapped in an &lt;code&gt;Observable&lt;/code&gt; object, responses that we're going to intercept via this code:&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;// main.ts&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;NestFactory&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;@nestjs/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;AppModule&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;./app.module&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;HttpService&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;@nestjs/axios&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;InternalServerErrorException&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;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;bootstrap&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;httpService&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;HttpService&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;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;NestFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AppModule&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;httpService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;axiosRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;interceptors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&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;return&lt;/span&gt; &lt;span class="nx"&gt;response&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;error&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&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;Internal server error exception&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&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="nx"&gt;InternalServerErrorException&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;await&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&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;Responses with status 2** will be handled by the first function, where we simply return the response. In case of error, we log the error and throw a built-in HTTP exception,  &lt;code&gt;InternalServerErrorException&lt;/code&gt;. Of course, we can implement more advanced error handling here, throwing exceptions depending on the error that we get from the axios code and so on.&lt;/p&gt;

&lt;p&gt;Next, what happens with our exception? It's going to be caught by the global http exception filter.&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;//http-exception.filter.ts&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;ArgumentsHost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Catch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ExceptionFilter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HttpException&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;@nestjs/common&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;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Response&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;express&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;Catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;HttpException&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="nx"&gt;HttpExceptionFilter&lt;/span&gt; &lt;span class="kr"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;ExceptionFilter&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;exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HttpException&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ArgumentsHost&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;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;switchToHttp&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;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Response&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;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getRequest&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Request&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;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getStatus&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nx"&gt;response&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;status&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;statusCode&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="na"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;toISOString&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="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&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;Now that we have the code for the exception filter, let's make the adjustments so we can use it:&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;//app.module.ts&lt;/span&gt;
&lt;span class="nx"&gt;providers&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;provide&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;APP_FILTER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;useClass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HttpExceptionFilter&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 javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;//main.ts&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;NestFactory&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;@nestjs/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;AppModule&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;./app.module&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;HttpService&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;@nestjs/axios&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;HttpExceptionFilter&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;./http-exception.filter&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;InternalServerErrorException&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;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;bootstrap&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;httpService&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;HttpService&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;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;NestFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AppModule&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;//http-exception as global filter&lt;/span&gt;
  &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;useGlobalFilters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;HttpExceptionFilter&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

  &lt;span class="nx"&gt;httpService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;axiosRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;interceptors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&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;return&lt;/span&gt; &lt;span class="nx"&gt;response&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;error&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&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;Internal server error exception&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&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="nx"&gt;InternalServerErrorException&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;await&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&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;What we learned as part of this blogpost:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;how to make an external http call via the &lt;code&gt;HttpService&lt;/code&gt; from &lt;code&gt;@nestJs/axios&lt;/code&gt; package&lt;/li&gt;
&lt;li&gt;how to intercept the responses of the http calls and throw built-in http exceptions in case of error&lt;/li&gt;
&lt;li&gt;how to intercept the http exceptions via the global http exception filter&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In-depth documentation on error handling, axios interceptors and exception filters can be found here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.nestjs.com/exception-filters"&gt;NestJS Exception filters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.nestjs.com/interceptors"&gt;NestJS Interceptors&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.nestjs.com/techniques/http-module"&gt;NestJs HttpModule&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/axios/axios#interceptors"&gt;Axios Interceptors&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;✨&lt;a href="https://github.com/blminami/nestjs-axios-interceptor"&gt;Github repo&lt;/a&gt; with the NestJs setup, exception filter and axios interceptor!&lt;/p&gt;

&lt;p&gt;Thank you for reading! 🐾&lt;/p&gt;

</description>
      <category>node</category>
      <category>typescript</category>
      <category>nestjs</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
