<?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: Samim Pezeshki</title>
    <description>The latest articles on DEV Community by Samim Pezeshki (@psamim).</description>
    <link>https://dev.to/psamim</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%2F158985%2Fb886068e-aff6-4eb8-93b5-f6dadeba7947.jpeg</url>
      <title>DEV Community: Samim Pezeshki</title>
      <link>https://dev.to/psamim</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/psamim"/>
    <language>en</language>
    <item>
      <title>Micro Frontends: After one year with Single-SPA</title>
      <dc:creator>Samim Pezeshki</dc:creator>
      <pubDate>Sun, 23 Jan 2022 09:00:42 +0000</pubDate>
      <link>https://dev.to/psamim/micro-frontends-after-one-year-with-single-spa-1eoo</link>
      <guid>https://dev.to/psamim/micro-frontends-after-one-year-with-single-spa-1eoo</guid>
      <description>&lt;h2&gt;
  
  
  Why did we choose micro frontend architecture?
&lt;/h2&gt;

&lt;p&gt;We have a codebase that was originally written using AngularJS. After some years and when finally the news about AngularJS end of life came around, we started migrating to Angular (actually hybrid Angular/AngularJS). Finally, two years ago we successfully migrated to Angular (You can read the details in &lt;a href="https://dev.to/psamim/steps-for-upgrading-angularjs-to-angular-9-5508"&gt;another post&lt;/a&gt;) having high hopes that by migrating to it we can leverage a new ecosystem. But after some months it became evident that Angular and AngularJS are so different that we need to rewrite everything, which is not very pleasant. Also, the React ecosystem and talent pool seemed much more vibrant so investing again in Angular for new upcoming features seemed like a non-optimal long-term solution. Over the years there were more experienced React developers in our teams so developing features in React would be much faster than having them in Angular.&lt;/p&gt;

&lt;p&gt;So we were looking for options to be able to keep our current Angular app while being able to add new upcoming features and sections using React or other frameworks. After some search, we found out that micro frontends were the solution we were looking for! Using Single-SPA one can have multiple frameworks, Angular and React, running side by side. Single-SPA is composed of so-called apps each being a SystemJS or ES module. Each app can use a different framework and technology and it only needs to mount itself somewhere on the page. Apps are mounted and unmounted based on the page route. All of this happens client-side. As a side note, I was thinking if we had known about micro frontends, maybe we would never have migrated to hybrid Angular and would have chosen Single-SPA from the beginning.&lt;/p&gt;

&lt;p&gt;Micro frontends are created for various purposes. Mainly it is discussed as a solution for keeping release cycles, deployments, and decisions in each team independent of others, like microservices but for frontend. In our case, we settled on micro frontends to be able to extend the lifetime of a legacy codebase by being able to take advantage of newer frameworks alongside old ones.&lt;/p&gt;

&lt;p&gt;We also assessed some other micro frontend frameworks and solutions, even using iframes and server-side routing, but finally, we decided to go with SignleSPA as it is less opinionated, simple and the best fit for our current codebase. The website is fully static (Angular/AngularJS) and is served from a CDN, so using server-side routing was out of options.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits
&lt;/h2&gt;

&lt;p&gt;The main benefit was improving the developer experience. Each Single-SPA app is developed separately, so when a developer starts to work on a React app (Single-SPA app) he/she does not need to install all the dependencies for other apps, like Angular, or to know how other apps are configured. Also because each app is small the development cycle of local builds, hot-reloads, and tests are much shorter in time. Developers can build features (Single-SPA apps) truly independently and separately. So now we could use all the experiences of our React developers in our legacy website.&lt;/p&gt;

&lt;p&gt;Each app in single-SPA is bundled separately. Using different apps for different features results in multiple small chunks, instead of a big fat bundle. Splitting the bundle can also be done by configuring Webpack without Single-SPA, but here we got it for free.&lt;/p&gt;

&lt;p&gt;Apart from smaller chunks and bundles we got lazy loading too. Some features are not used frequently, so their bundle can be loaded separately in the background after the initial load.&lt;/p&gt;

&lt;p&gt;As new feature apps are developed using React, even after migration to a whole new framework like NextJS in the future, those parts can be re-used without the need to rewrite everything from scratch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Issues
&lt;/h2&gt;

&lt;p&gt;One &lt;a href="https://github.com/angular-microfrontends/navbar/issues/1"&gt;issue&lt;/a&gt; I had was that I could not generate source maps for Angular when it was built as a SystemJS module. I did not dig deep into the issue as it did not have a great impact on the project. But it is was nice to have source maps.&lt;/p&gt;

&lt;p&gt;Another issue was the integration between the apps. We used local storage, global events, and shared modules for this and they all worked pretty well. But deciding on the best option was sometimes challenging.&lt;/p&gt;

&lt;p&gt;Also as the whole concept is new, it took some time for the new developers to learn how to get on track, although this was negligible and even sometimes exciting to learn about new trends.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code structure and deployment pipelines
&lt;/h2&gt;

&lt;p&gt;All Single-SPA apps are put into a single repository. Each app has its own &lt;code&gt;package.json&lt;/code&gt; file and is developed and built separately. There is also the root app which contains the main router responsible for mounting and unmounting other apps.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── apps
│   ├── root
│   │   ├── node_modules
│   │   ├── package.json
│   │   └── src
│   │       └── index.html
│   ├── feature-one (Angular)
│   │   ├── node_modules
│   │   └── package.json
│   └── feature-two (React)
│       ├── node_modules
│       └── package.json
└── scripts
    ├── build.sh
    ├── deploy.sh
    └── start.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;During deployment, there is a shell script that installs and builds each app and assembles them by copying the built files into a final build directory. Then it uses AWS Cloudformation to create a static website on S3, CloudFront, and Route53.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ROOT_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$PWD&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;4.0-&lt;span class="si"&gt;$(&lt;/span&gt;git log &lt;span class="nt"&gt;-1&lt;/span&gt; &lt;span class="nt"&gt;--pretty&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"%h"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;BUILD_NUMBER&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;-&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="nt"&gt;--iso&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;d &lt;span class="k"&gt;in&lt;/span&gt; ./apps/&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$d&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;" * Installing dependencies for &lt;/span&gt;&lt;span class="nv"&gt;$d&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nb"&gt;echo
    cd&lt;/span&gt; &lt;span class="nv"&gt;$d&lt;/span&gt;
    npm &lt;span class="nb"&gt;install
    &lt;/span&gt;npm run build
    &lt;span class="nb"&gt;mv &lt;/span&gt;dist &lt;span class="nv"&gt;$ROOT_PATH&lt;/span&gt;/dist/&lt;span class="nv"&gt;$d&lt;/span&gt;
    &lt;span class="nb"&gt;cd&lt;/span&gt; -
  &lt;span class="k"&gt;fi
done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As a single deployment pipeline and repository is used for all the apps, we are not gaining from one of the main benefits of using micro frontends architecture which is independent release cycles for each app. But by putting everything in a single repository we could achieve what we were looking for without dealing with the complexity of managing multiple repositories and deciding on how to update import maps (solutions like &lt;a href="https://github.com/single-spa/import-map-deployer"&gt;import-map-deployer&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Development Experience
&lt;/h2&gt;

&lt;p&gt;There are two ways to start developing. One is using the single-spa-inspector browser extension. This way the developer opens the fully-deployed live website (not localhost:3000 or any local address) and overrides the import maps to make the live website connect to the Single-SPA app running locally. This way the developer only runs the one feature app he/she is working on while running it inside the live deployed website. It frees the developer from running the whole website locally and even has the side benefit of seeing and developing the feature app in the context of the deployed website connected to the live database. This way of development was personally very unique and new to me, it was amazing.&lt;/p&gt;

&lt;p&gt;Another approach is to start all Single-SPA apps locally. This approach is sometimes needed for debugging the integration between the apps. The below script is used to run all apps:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;SCRIPT_ENV&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;dev&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3000

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"⚜    Starting &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SCRIPT_ENV&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;..."&lt;/span&gt;
&lt;span class="nb"&gt;echo
echo&lt;/span&gt; ⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"📡   Listening on https://localhost:&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PORT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; ⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽
&lt;span class="nb"&gt;echo

echo&lt;/span&gt; &lt;span class="s2"&gt;"⚠    Ignore if the below single-spa apps report about their ports! root app is served on port &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PORT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;."&lt;/span&gt;
&lt;span class="nb"&gt;echo

&lt;/span&gt;npx concurrently &lt;span class="nt"&gt;--names&lt;/span&gt; &lt;span class="s2"&gt;"ROOT,FEATURE1,FEATURE2"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"#E0E0E0,#26C6DA,#FFA726"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"cd apps/root &amp;amp;&amp;amp; env PORT=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PORT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; npm run start:&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SCRIPT_ENV&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"cd apps/feature-one &amp;amp;&amp;amp; env PORT=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;expr&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PORT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; + 1&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; npm run start:&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SCRIPT_ENV&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"cd apps/feature-two &amp;amp;&amp;amp; env PORT=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;expr&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PORT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; + 2&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; npm run start:&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SCRIPT_ENV&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Road ahead
&lt;/h2&gt;

&lt;p&gt;Adopting micro frontend architecture (Single-SPA) enabled us to further keep our legacy website while utilizing more trendy technologies to deliver new features. Otherwise, we had to rewrite the whole website or stick to what we had. Now that new features are delivered on time and we are on schedule plans can be made to rewrite the whole website without a rush. &lt;/p&gt;

&lt;p&gt;With new trends, frameworks, and ideas popping up in the web development space every day, like server-side rendering, statically generated dynamic content, edge serverless workers, etc., I am not sure if we would again choose Single-SPA for a project creating from scratch. But for our use case, the micro frontend architecture served us well. If you have any framework or architecture in mind to suggest for our next project, please share, I would appreciate it.&lt;/p&gt;

</description>
      <category>singlespa</category>
      <category>microfrontend</category>
      <category>react</category>
      <category>angular</category>
    </item>
    <item>
      <title>Steps for upgrading AngularJS to hybrid Angular 9</title>
      <dc:creator>Samim Pezeshki</dc:creator>
      <pubDate>Thu, 18 Jun 2020 08:02:15 +0000</pubDate>
      <link>https://dev.to/psamim/steps-for-upgrading-angularjs-to-angular-9-5508</link>
      <guid>https://dev.to/psamim/steps-for-upgrading-angularjs-to-angular-9-5508</guid>
      <description>&lt;p&gt;Update:  What happened a year after, &lt;a href="https://dev.to/psamim/micro-frontends-after-one-year-with-single-spa-1eoo"&gt;read this&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AngularJS end of life is near. Its LTS version will end on June 2021. So many projects using AngularJS have started considering the options. One option is to migrate to ReactJS, but some choose to ``upgrade and continue using Angular.&lt;/p&gt;

&lt;p&gt;Recently I had to upgrade a 5-year-old codebase from AngularJS 1.4 to Angular 9. It took some effort as I had forgotten the tools which were popular in the olden times! The project used Gulp, Sass, and server-side Jade (Pug). &lt;/p&gt;

&lt;p&gt;These are the steps to upgrade.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install Angular
&lt;/h3&gt;

&lt;p&gt;The first step was to install Angular CLI and bootstrap a new project right next to the old AngularJS app files inside the same repository.&lt;/p&gt;

&lt;h3&gt;
  
  
  Remove Gulp
&lt;/h3&gt;

&lt;p&gt;Gulp was used to compile Sass files and concatenate JS files. Angular 9 uses Webpack to do this and it is configured by default. I removed gulp and its related files.&lt;/p&gt;

&lt;p&gt;Sass files had a single entry. I added the entry file to the Angular's &lt;code&gt;src/styles.scss&lt;/code&gt; so that all existing styles are compiled now.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;`scss&lt;br&gt;
@import "app/main";&lt;br&gt;
...&lt;br&gt;
`&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;JS concatenation is not needed anymore because AngularJS is bootstrapped inside Angular and all dependent files are linked and bundled using the &lt;code&gt;import&lt;/code&gt; syntax. I will discuss how to bootstrap AngularJS inside Angular in the next step.&lt;/p&gt;

&lt;p&gt;If any files outside Angular needs concatenation or Sass compilation, Angular's Webpack can be customized and extended using &lt;a href="https://github.com/just-jeb/angular-builders/tree/master/packages/custom-webpack"&gt;custom Webpack configurations&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bootstrap AngularJS
&lt;/h3&gt;

&lt;p&gt;Following &lt;a href="https://angular.io/guide/upgrade#how-ngupgrade-works"&gt;documentations here&lt;/a&gt; I used &lt;code&gt;ngUpgrade&lt;/code&gt; to bootstrap the AngularJS module. &lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;app.module.ts&lt;/code&gt; file:&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;ts&lt;br&gt;
import { UpgradeModule } from "@angular/upgrade/static";&lt;br&gt;
import { angularJsModule } from "../ajs/app";&lt;/p&gt;

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

&lt;p&gt;export class AppModule {&lt;br&gt;
  constructor(private upgrade: UpgradeModule) {}&lt;/p&gt;

&lt;p&gt;ngDoBootstrap() {&lt;br&gt;
    this.upgrade.bootstrap(document.body, [angularJsModule.name], {&lt;br&gt;
      strictDi: true&lt;br&gt;
    });&lt;br&gt;
  }&lt;br&gt;
}&lt;br&gt;
&lt;code&gt;&lt;/code&gt;`&lt;/p&gt;

&lt;p&gt;You can see that I have imported &lt;code&gt;angularJsModule&lt;/code&gt;. For it to work I had to refactor the AngularJS app a little bit. I created a new file to define the AngularJS module as &lt;code&gt;angularJsModule&lt;/code&gt; and export it to use it in the code above for bootstrapping. Also in the process of refactoring, I decided to put all AngularJS code into a separate directory called &lt;code&gt;ajs&lt;/code&gt; inside &lt;code&gt;src&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;`&lt;code&gt;&lt;/code&gt;ts&lt;br&gt;
import * as angular from "angular";&lt;br&gt;
import ngStorage from "ngstorage";&lt;br&gt;
import ngSanitize from "angular-sanitize";&lt;br&gt;
import ngMaterial from "angular-material";&lt;/p&gt;

&lt;p&gt;export const angularJsModule = angular&lt;br&gt;
  .module("MyApp", [&lt;br&gt;
    ngStorage.name,&lt;br&gt;
    ngSanitize,&lt;br&gt;
    ngMaterial,&lt;br&gt;
  ])&lt;br&gt;
  .service("toaster", ["$mdToast", ToasterService])&lt;br&gt;
 ...&lt;br&gt;
&lt;code&gt;&lt;/code&gt;`&lt;/p&gt;

&lt;p&gt;It is better to define all services or directives you have in this file. If you have other JS files where you have defined services or directives you have to import them too so that they end up in the final bundle.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;`ts&lt;br&gt;
import "./components/date-tools.svc.js";&lt;br&gt;
import "./components/toaster.svc.ts";&lt;br&gt;
import "./payment/currency-tools.svc.js";&lt;br&gt;
...&lt;br&gt;
`&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It is better to import all needed dependencies in the same file where they are going to be used and avoid globally scoped variables like &lt;code&gt;moment&lt;/code&gt; or &lt;code&gt;lodash&lt;/code&gt;. If you have correctly imported dependencies they all will be in the final bundle. But sometimes refactoring the code and adding &lt;code&gt;import lodash from 'lodash'&lt;/code&gt; to many files takes time so I added them to global scope temporarily to mitigate the issue for now.&lt;/p&gt;

&lt;p&gt;`&lt;code&gt;&lt;/code&gt;ts&lt;br&gt;
import * as lodash from "lodash";&lt;br&gt;
import * as moment from "moment";&lt;/p&gt;

&lt;p&gt;(window as any).moment = moment;&lt;br&gt;
(window as any)._ = lodash;&lt;br&gt;
&lt;code&gt;&lt;/code&gt;`&lt;/p&gt;

&lt;p&gt;There were remaining scripts that did not work with the above method and which I needed to have in the global scope or need something like HTML script tag so I added them to &lt;code&gt;angular.json&lt;/code&gt; file's &lt;code&gt;scripts&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;`json&lt;br&gt;
...&lt;br&gt;
      "architect": {&lt;br&gt;
        "build": {&lt;br&gt;
         ...&lt;br&gt;
            "scripts": [&lt;br&gt;
              "node_modules/dropzone/dist/min/dropzone.min.js",&lt;br&gt;
              "node_modules/d3/d3.min.js"&lt;br&gt;
            ]&lt;br&gt;
          },&lt;br&gt;
...&lt;br&gt;
`&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Previously the project did not use npm to manage the dependencies. It used gulp to concatenate and bundle JS files and they were not pulled from &lt;code&gt;node_modules&lt;/code&gt;. The library files were just copied into the project. In the process of removing gulp I also removed all library files from the project and let Webpack and npm manage those.&lt;/p&gt;

&lt;p&gt;At this point, the app should have worked.&lt;/p&gt;

&lt;p&gt;But I had one specific problem here. Many templates were compiled on the server-side by Jade (Pug) template engine using &lt;code&gt;express&lt;/code&gt;'s view engine feature. The main problem was the &lt;code&gt;index.html&lt;/code&gt; file. Angular and in particular Webpack needs to create &lt;code&gt;index.html&lt;/code&gt; to inject scripts and styles. I had to manually edit and convert this file from Jade to pure client-side HTML. Some variables were being injected from the server-side using Jade templates. I had to find other ways to access those variables. I ended up using Handlebars template engine instead of Jade because Handlebars is valid HTML and can be given to Angular. So I created &lt;code&gt;index.html&lt;/code&gt; having Handlebar variables. Then Angular injects scripts and styles into it on build time and this file is finally served by &lt;code&gt;express&lt;/code&gt; injecting server-side variables through Handlebars template variables. Ideally, I would like to not use Handlebars and passing variables this way seems not clean to me.&lt;/p&gt;

&lt;p&gt;Here I configured Angular to use my Handlebars template file:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;`json&lt;br&gt;
...&lt;br&gt;
      "architect": {&lt;br&gt;
        "build": {&lt;br&gt;
         ...&lt;br&gt;
            "options": {&lt;br&gt;
               "index": "client/main/src/ajs/index.handlebars",&lt;br&gt;
            }&lt;br&gt;
          },&lt;br&gt;
...&lt;br&gt;
`&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Migrate Routes
&lt;/h3&gt;

&lt;p&gt;The old AngularJS app used &lt;code&gt;ui-router&lt;/code&gt; for routing. The good news was that &lt;code&gt;ui-router&lt;/code&gt; can share routes between AgnularJS and Angular using &lt;a href="https://github.com/ui-router/angular-hybrid"&gt;angular-hybrid&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;app.module.ts&lt;/code&gt;:&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;ts&lt;br&gt;
import { UIRouterUpgradeModule } from "@uirouter/angular-hybrid";&lt;br&gt;
import { routerStates } from "./router-states";&lt;/p&gt;

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

&lt;p&gt;@NgModule({&lt;br&gt;
  imports: [&lt;br&gt;
    UIRouterUpgradeModule.forRoot(routerStates),&lt;br&gt;
  ],&lt;br&gt;
 ...&lt;br&gt;
})&lt;br&gt;
export class AppModule {}&lt;br&gt;
&lt;code&gt;&lt;/code&gt;`&lt;/p&gt;

&lt;p&gt;And in the &lt;code&gt;router-states.ts&lt;/code&gt; file one route is using AngularJS and another route is using Angular:&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;ts&lt;br&gt;
import { VisaComponent } from "./trip-details/visa/visa.component";&lt;/p&gt;

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

&lt;p&gt;export const routerStates = {&lt;br&gt;
  states: [&lt;br&gt;
    {&lt;br&gt;
      name: "documents",&lt;br&gt;
      url: "/documents",&lt;br&gt;
      templateUrl: "/views/documents",&lt;br&gt;
      controller: "DocumentsController",&lt;br&gt;
      redirectTo: "documents.manage"&lt;br&gt;
    },&lt;br&gt;
    {&lt;br&gt;
      name: "trip-details.visa",&lt;br&gt;
      url: "/visa",&lt;br&gt;
      component: VisaComponent,&lt;br&gt;
    }&lt;br&gt;
...&lt;br&gt;
&lt;code&gt;&lt;/code&gt;`&lt;/p&gt;

&lt;h3&gt;
  
  
  Change Deployment Scripts
&lt;/h3&gt;

&lt;p&gt;Finally, I had to change deployment scripts used by npm and CI/CD pipelines to use &lt;code&gt;ng build&lt;/code&gt; command.&lt;/p&gt;

&lt;h3&gt;
  
  
  Development Server
&lt;/h3&gt;

&lt;p&gt;There was still one specific problem to this project setup. In this project &lt;code&gt;express&lt;/code&gt; server was set up in the same repository for both serving the front-end (and its server-side Jade templates) and also serving the back-end API endpoints. Angular has its own server used in development mode with hot-reload and specific configurations. For development, I wanted to have both the old &lt;code&gt;express&lt;/code&gt; server (for APIs and legacy Jade templates) and the new Angular development server running at the same time.&lt;/p&gt;

&lt;p&gt;So I used &lt;a href="https://github.com/chimurai/http-proxy-middleware"&gt;http-proxy-middleware&lt;/a&gt;. &lt;code&gt;express&lt;/code&gt; can serve the APIs as before and also proxy requests to Angular development server running on port 4200 only in development mode.&lt;/p&gt;

&lt;p&gt;in &lt;code&gt;express-app.ts&lt;/code&gt;:&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;ts&lt;br&gt;
import { createProxyMiddleware } from "http-proxy-middleware";&lt;/p&gt;

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

&lt;p&gt;if (process.env.NODE_ENV === "development") {&lt;br&gt;
    app.use(&lt;br&gt;
      ["/client", "/sockjs-node", "/assets"],&lt;br&gt;
      createProxyMiddleware({&lt;br&gt;
        target: "&lt;a href="http://localhost:4200"&gt;http://localhost:4200&lt;/a&gt;",&lt;br&gt;
        ws: true,&lt;br&gt;
        pathRewrite: {&lt;br&gt;
          "^/assets": "/client/assets"&lt;br&gt;
        }&lt;br&gt;
      })&lt;br&gt;
    );&lt;br&gt;
  } else {&lt;br&gt;
    app.use("/client", express.static(path.join(&lt;strong&gt;dirname, "..", "public")));&lt;br&gt;
    app.use(&lt;br&gt;
      "/assets",&lt;br&gt;
      express.static(path.join(&lt;/strong&gt;dirname, "..", "public", "assets"))&lt;br&gt;
    );&lt;br&gt;
  }&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`&lt;/p&gt;

&lt;p&gt;The ideal setup would be to separate concerns and put the back-end code into its own separate repository but that is a separate issue.&lt;/p&gt;

&lt;p&gt;So, in the end, the development setup is something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3JQehM5M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/jpdi4fofp3mabdblzy97.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3JQehM5M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/jpdi4fofp3mabdblzy97.png" alt="Alt Text" width="880" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the production setup, there is no Angular dev server.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sharing Services and Components
&lt;/h3&gt;

&lt;p&gt;To use a service or component from Angular in AngularJS we need to downgrade those services and components. In the same file that I defined the &lt;code&gt;angularJsModule&lt;/code&gt;:&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;ts&lt;br&gt;
import {&lt;br&gt;
  downgradeComponent,&lt;br&gt;
  downgradeInjectable&lt;br&gt;
} from "@angular/upgrade/static";&lt;/p&gt;

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

&lt;p&gt;.module("GlobalWorldApp", [&lt;br&gt;
   ...&lt;br&gt;
   ])&lt;br&gt;
  .directive(&lt;br&gt;
    "nextPaymentPlans",&lt;br&gt;
    downgradeComponent({ component: PlansComponent })&lt;br&gt;
  )&lt;br&gt;
  .factory("nextPayment", downgradeInjectable(PaymentService) as any);&lt;br&gt;
&lt;code&gt;&lt;/code&gt;&lt;code&gt;&lt;br&gt;
So&lt;/code&gt;nextPayment&lt;code&gt;is accessible as an AngularJS service and&lt;/code&gt;` can be used in AngularJS templates. So now we can start moving components and services from AngularJS to Angular gradually.&lt;/p&gt;

&lt;p&gt;To access the AngularJS's &lt;code&gt;rootScope&lt;/code&gt; from Angular we can inject it as a service, but better to avoid it if possible.&lt;br&gt;
&lt;code&gt;`ts&lt;br&gt;
import { IRootScopeService } from "angular";&lt;br&gt;
...&lt;br&gt;
  constructor(&lt;br&gt;
    @Inject("$rootScope") private _rootScope: IRootScopeService) {}&lt;br&gt;
...&lt;br&gt;
`&lt;/code&gt;&lt;br&gt;
Good to mention that to properly use the &lt;code&gt;rootScope&lt;/code&gt; we need to &lt;code&gt;watch&lt;/code&gt; it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Linter
&lt;/h3&gt;

&lt;p&gt;Setting up the linter is a separate issue and process from upgrading AngularJS. But I just want to mention here that I decided to remove &lt;code&gt;tslint&lt;/code&gt; and replace it with &lt;code&gt;eslint&lt;/code&gt;. Mainly because &lt;code&gt;tslint&lt;/code&gt; &lt;a href="https://github.com/palantir/tslint/issues/4534"&gt;is deprecated&lt;/a&gt; and also because of the smoother integration of &lt;code&gt;eslint&lt;/code&gt; with &lt;code&gt;prettier&lt;/code&gt; and other tools. I also love and use &lt;code&gt;prettier&lt;/code&gt; everywhere I can.&lt;/p&gt;

&lt;h3&gt;
  
  
  Upgrade
&lt;/h3&gt;

&lt;p&gt;After all these steps we can just start upgrading the app! I mean now we can let AngularJS and Angular components co-exist. So we can rewrite and move components from AngularJS to Angular gradually. The full upgrade takes months or even may never come. I think we will develop new parts of the app in Angular and only rewrite the AngularJS parts which are buggy or need refactoring.&lt;/p&gt;

&lt;p&gt;I hope this helps others and future me trying to upgrade AngularJS apps.&lt;/p&gt;

</description>
      <category>angular</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Performance tips to have in mind while writing React components</title>
      <dc:creator>Samim Pezeshki</dc:creator>
      <pubDate>Fri, 09 Feb 2018 15:53:47 +0000</pubDate>
      <link>https://dev.to/psamim/performance-tips-to-have-in-mind-while-writing-react-components-4eo</link>
      <guid>https://dev.to/psamim/performance-tips-to-have-in-mind-while-writing-react-components-4eo</guid>
      <description>&lt;p&gt;As I was fine-tuning the React components I am working on, I tested and played with different ways I could re-write the code. I am compiling all the tips I learned, the performance tips to have in mind while I am writing the code.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pay attention what you are sending as props into the component. React components trigger a re-render when props or state changes. Send props that change less often. For example, see the code below:&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;The index and selectedNoteIndex are passed to the component as props, this way changing selectedNoteIndex or anything that changes the index, changes the props and it triggers a re-render for all the components created by map! Another way to write the code above would be:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Now only a Boolean (selected) is sent to the component as props and the comparison is performd upper in the hierarchy.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Break large components into smaller ones. &lt;a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself"&gt;DRY&lt;/a&gt;. Big components are hard to maintain and fine-tune. Big components are all rendered at once. Turn the parts inside maps into their own components. For example, even if you have to pass index into the component in the example above, break the component into two parts, one that needs index and one that does not:&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;This way at least a part of the DOM tree is not re-rendered.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Have small states or none at all. Side effects and states are one of the main sources of bugs. Keeping state in sync with the props needs implementing the React life-cycle hooks which takes maintenance time. Try not to copy what is available in the props into the state. For example, to keep track of which row is selected in a table, you can save the entire row (as a big object) in the state or just save its index (as a number). Saving the entire row is tempting, you may think it is easier to access the row by this.state.selectedRow instead of this.props.rows[this.state.selectedRowIndex]. But the first approach leads to unknown consequences down the road. This may not totally be a performance tip, but having it in mind helps to reduce unwanted consequences tremendously..&lt;/li&gt;
&lt;li&gt;Use &lt;a href="https://github.com/cssinjs/jss"&gt;JSS&lt;/a&gt; (or its one of its derivatives like &lt;a href="https://material-ui-next.com/customization/css-in-js/#withstyles-styles-options-higher-order-component"&gt;withStyles&lt;/a&gt; in material-ui) instead of inline styles. Whenever you are using inline styles, you are creating a JS object. It &lt;em&gt;might&lt;/em&gt; be OK for one-time usage. But for example, using inline styles in maps would be a terrible idea. Extract inline styles into their own object and reuse them, or better, use JSS for even more &lt;a href="https://github.com/cssinjs/jss/blob/master/docs/performance.md"&gt;performance&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Reuse functions just like other objects. For example, when you want to pass a function and use it inside a map, instead of creating the function inline, like submit={() =&amp;gt; doSomething(note.id)} , create the function in the class and pass the reference like submit={this.doSomething}. If you create the function inline, you are changing the component’s prop each time (because the newly created function has a new reference) and a useless render will be triggered.&lt;/li&gt;
&lt;li&gt;Now that the component is small and the props are well known and documented (use flow or prop-types), you can easily implement &lt;a href="https://reactjs.org/docs/optimizing-performance.html#shouldcomponentupdate-in-action"&gt;shouldComponentUpdate&lt;/a&gt; and boost performance.&lt;/li&gt;
&lt;li&gt;You can use PureComponent instead of Component wherever possible. Use it with care and enough test as the last resort. Make sure shallow comparison of all props is what you want. If all props are known you can implement shouldComponentUpdate yourself instead of using PureComponent.&lt;/li&gt;
&lt;li&gt;UPDATE: Avoid having states up in the hierarchy. Use redux. When you have a state up in hierarchy, updating it will cause a render across the whole tree. You can store this state in the redux and connect it only to the component which needs it. So only the component will get updated when the state in redux changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the end, always &lt;a href="https://reactjs.org/docs/optimizing-performance.html#profiling-components-with-the-chrome-performance-tab"&gt;analyze the performance in Dev Tools&lt;/a&gt; while fine-tuning. Sometimes it surprises you by showing that the things that you may have considered beneficial for performance actually have made it worse.&lt;/p&gt;

</description>
      <category>react</category>
      <category>performance</category>
    </item>
    <item>
      <title>How I transfer my vocabs from my Kindle Paperwhite to Anki</title>
      <dc:creator>Samim Pezeshki</dc:creator>
      <pubDate>Fri, 03 Mar 2017 08:47:59 +0000</pubDate>
      <link>https://dev.to/psamim/how-i-transfer-my-vocabs-from-my-kindle-paperwhite-to-anki-1f4d</link>
      <guid>https://dev.to/psamim/how-i-transfer-my-vocabs-from-my-kindle-paperwhite-to-anki-1f4d</guid>
      <description>&lt;p&gt;I read a lot on my Kindle Paperwhite and it really amazes me how many words can homo sapiens invent. When I look up a new word in the dictionary and see the equivalent in my mother tongue I wonder where I have learned this rare word or even when was the last time I heard it. Despite that I totally comprehend the word and the concept behind. Homo sapiens are amazing.&lt;/p&gt;

&lt;p&gt;I want to read uninterrupted, save new words for later and add them to my &lt;a href="https://apps.ankiweb.net/"&gt;Anki&lt;/a&gt; deck so that I can review them on my phone in my free time, or at the gym.&lt;/p&gt;

&lt;p&gt;This is how I do it.&lt;/p&gt;

&lt;p&gt;As you know when you look up a word in Kindle it is automatically saved in something called the “Vocabulary Builder” which is accessible from the upper right menu on the device. The words are actually saved in an SQLite database on the device along with its surrounding sentence. If you connect the device via USB the database file is located at &lt;code&gt;system/vocabulary/vocab.db&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then &lt;a href="https://github.com/psamim/kindle2anki"&gt;I have a Python script&lt;/a&gt; to read this database, ask about the words’ meanings interactively and add them to an Anki deck. Occasionally I copy the database file to my PC and run the script below in terminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash

KINDLE=~/Backup/vocab.db
COLLECTION=~/Documents/Anki/User\ 1/collection.anki2
DECK=Words

kindle2anki --kindle $KINDLE --collection $COLLECTION --deck $DECK --clipboard
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I have put the script on &lt;a href="https://aur.archlinux.org/packages/kindle2anki-git/"&gt;AUR&lt;/a&gt; if you are of that tribe.&lt;/p&gt;

</description>
      <category>anki</category>
      <category>kindle</category>
      <category>whitepaper</category>
      <category>ebook</category>
    </item>
  </channel>
</rss>
