<?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: Dmitry Ruban</title>
    <description>The latest articles on DEV Community by Dmitry Ruban (@roderekh).</description>
    <link>https://dev.to/roderekh</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%2F92241%2F7aeb71b0-2ec5-4e5b-9a9b-535f2ac0b3db.png</url>
      <title>DEV Community: Dmitry Ruban</title>
      <link>https://dev.to/roderekh</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/roderekh"/>
    <language>en</language>
    <item>
      <title>Web-Essentials Reminder</title>
      <dc:creator>Dmitry Ruban</dc:creator>
      <pubDate>Sun, 23 Apr 2023 22:21:37 +0000</pubDate>
      <link>https://dev.to/roderekh/web-essentials-reminder-3fn5</link>
      <guid>https://dev.to/roderekh/web-essentials-reminder-3fn5</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This is a simple reminder to help refresh your knowledge or prepare for a Junior position interview.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  JavaScript Engine
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Data Types&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;number&lt;/code&gt;: for any kind of numbers, integer or floating-point.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;string&lt;/code&gt;: for strings. A string may have one or more characters; there’s no separate single-character type.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;boolean&lt;/code&gt;: for true/false values.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;null&lt;/code&gt;: for unknown values – a standalone type with a single value null.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;undefined&lt;/code&gt;: for unassigned values – a standalone type with a single value undefined.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;object&lt;/code&gt;: for more complex data structures.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;symbol&lt;/code&gt;: for unique identifiers. &lt;a href="https://javascript.info/symbol"&gt;Learn more&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Boxing/Unboxing&lt;/strong&gt;: &lt;a href="https://stackoverflow.com/a/34067647/2902988"&gt;Learn more&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Variables&lt;/strong&gt;: const, let, and var. &lt;a href="https://javascript.info/variables"&gt;Learn more about const&lt;/a&gt;, &lt;a href="https://javascript.info/var"&gt;Learn more about var&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Closures&lt;/strong&gt;: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures"&gt;MDN&lt;/a&gt;, &lt;a href="https://javascript.info/closure"&gt;JavaScript.info&lt;/a&gt;, &lt;a href="https://medium.com/dailyjs/i-never-understood-javascript-closures-9663703368e8"&gt;Medium&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Arrow functions vs regular functions&lt;/strong&gt;: &lt;a href="https://www.vinta.com.br/blog/2015/javascript-lambda-and-arrow-functions/"&gt;Vinta&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions"&gt;MDN&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Objects&lt;/strong&gt;: &lt;a href="https://javascript.info/object"&gt;Learn more&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prototypes&lt;/strong&gt;: &lt;a href="https://javascript.info/prototype-inheritance"&gt;JavaScript.info (Inheritance)&lt;/a&gt;, &lt;a href="https://javascript.info/function-prototype"&gt;JavaScript.info (Function Prototype)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Property flags and descriptors&lt;/strong&gt;: &lt;a href="https://javascript.info/property-descriptors"&gt;Learn more&lt;/a&gt; - value, writable, enumerable, configurable&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decorators&lt;/strong&gt;: &lt;a href="https://www.typescriptlang.org/docs/handbook/decorators.html"&gt;TypeScript Documentation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generators (yield)&lt;/strong&gt;: &lt;a href="https://javascript.info/generators"&gt;Learn more&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Promises&lt;/strong&gt;: &lt;a href="https://javascript.info/promise-basics"&gt;Learn more&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory allocation&lt;/strong&gt;: &lt;a href="https://hashnode.com/post/does-javascript-use-stack-or-heap-for-memory-allocation-or-both-cj5jl90xl01nh1twuv8ug0bjk"&gt;Learn more&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  TypeScript
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Basic concepts&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Node.js
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Overview&lt;/li&gt;
&lt;li&gt;Dependencies and npm&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Event loop&lt;/strong&gt;: &lt;a href="https://blog.insiderattack.net/event-loop-and-the-big-picture-nodejs-event-loop-part-1-1cb67a182810"&gt;Learn more&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Streams&lt;/strong&gt;: &lt;a href="https://medium.com/devschacht/stefan-baumgartner-the-definitive-guide-to-object-streams-in-nodejs-ab983b819eae"&gt;Medium&lt;/a&gt;, &lt;a href="https://www.youtube.com/watch?v=GpGTYp_G9VE"&gt;YouTube&lt;/a&gt;, &lt;a href="https://www.freecodecamp.org/news/node-js-streams-everything-you-need-to-know-c9141306be93/"&gt;freeCodeCamp&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Google V8 and Libuv&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Garbage collector&lt;/strong&gt;: &lt;a href="https://blog.risingstack.com/node-js-at-scale-node-js-garbage-collection/"&gt;Learn more&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Pros and cons of Node.js&lt;/li&gt;
&lt;li&gt;Express and other frameworks&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Browser
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Web APIs, JavaScript runtime, browser event loop, and browser promises&lt;/strong&gt;: &lt;a href="https://itnext.io/how-javascript-works-in-browser-and-node-ab7d0d09ac2f"&gt;ITNEXT (1)&lt;/a&gt;, &lt;a href="https://itnext.io/javascript-promises-and-async-await-as-fast-as-possible-d7c8c8ff0abc"&gt;ITNEXT (2)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Web Workers&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Document Object Model (DOM)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Virtual DOM&lt;/strong&gt;: &lt;a href="https://reactjs.org/docs/faq-internals.html"&gt;React.js Documentation&lt;/a&gt;, &lt;a href="https://habr.com/ru/post/448048/"&gt;Habr (Russian)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shadow DOM&lt;/strong&gt;: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM"&gt;Learn more&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  SQL
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Database design&lt;/li&gt;
&lt;li&gt;Indexes&lt;/li&gt;
&lt;li&gt;N + 1 problem&lt;/li&gt;
&lt;li&gt;Joins&lt;/li&gt;
&lt;li&gt;ACID properties&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  NoSQL
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Overview&lt;/li&gt;
&lt;li&gt;Sharding&lt;/li&gt;
&lt;li&gt;Comparing with SQL databases&lt;/li&gt;
&lt;li&gt;CAP theorem: &lt;a href="https://en.wikipedia.org/wiki/CAP_theorem"&gt;Wikipedia&lt;/a&gt;, &lt;a href="https://www.quora.com/Which-is-better-Redis-cluster-or-Cassandra"&gt;Quora&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  REST API
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Overview&lt;/li&gt;
&lt;li&gt;API design&lt;/li&gt;
&lt;li&gt;Examples&lt;/li&gt;
&lt;li&gt;Bulk operations&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Authentication and Authorization
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Cookies&lt;/li&gt;
&lt;li&gt;Session&lt;/li&gt;
&lt;li&gt;LocalStorage&lt;/li&gt;
&lt;li&gt;JWT&lt;/li&gt;
&lt;li&gt;OAuth 2&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  HTTPS
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Protocol&lt;/li&gt;
&lt;li&gt;Methods &amp;amp; Status codes&lt;/li&gt;
&lt;li&gt;Limitations&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Testing
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Behavior-Driven Development (BDD)&lt;/li&gt;
&lt;li&gt;Test-Driven Development (TDD)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Object-Oriented Programming (OOP)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Fundamentals&lt;/li&gt;
&lt;li&gt;Examples&lt;/li&gt;
&lt;li&gt;SOLID principles&lt;/li&gt;
&lt;li&gt;Design patterns&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Build tools and preprocessors
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Webpack&lt;/li&gt;
&lt;li&gt;Sass&lt;/li&gt;
&lt;li&gt;Less&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>interview</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Micro-frontends communication approaches</title>
      <dc:creator>Dmitry Ruban</dc:creator>
      <pubDate>Wed, 22 Mar 2023 12:37:04 +0000</pubDate>
      <link>https://dev.to/roderekh/micro-frontends-communication-approaches-1n93</link>
      <guid>https://dev.to/roderekh/micro-frontends-communication-approaches-1n93</guid>
      <description>&lt;h2&gt;
  
  
  Micro-frontends
&lt;/h2&gt;

&lt;p&gt;The engineering world tries to simplify and decompose big elements to separated pieces. Big classes can be decomposed to dedicated elements using different concepts such as SOLID and others. Applications can use libraries. Backend services can be sliced to modules or micro-services. &lt;/p&gt;

&lt;p&gt;In Frontend sphere we hear more often about the concept to decompose big Single Page Application (SPA) to modules working as micro-services, they got the name “Micro-Frontends”. We have the one orchestrator managing and playing services - micro-apps by helping to launch and connect them together. &lt;/p&gt;

&lt;p&gt;One of the most critical aspects of micro-frontends is &lt;strong&gt;the communication layer&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Communication challenges
&lt;/h2&gt;

&lt;p&gt;Let's consider a scenario where a user wants to use an Instagram-like application with albums, photos, and related functionality. &lt;/p&gt;

&lt;p&gt;The user opens the main domain URL, and the browser loads the orchestrator, which then initiates the process of loading the remaining dependencies.&lt;br&gt;
The application can be divided into frames or based on business logic. The second approach is more efficient for creating a pluggable system. As the user opens the first micro-app with the home page, user can see own profile with an empty album. By clicking the "Upload Photo" button, the system asks the orchestrator to mount a new micro-app, such as an uploader popup with prerequisites or context.&lt;br&gt;
Let’s keep in mind the first queue of questions: how to ask orchestrator to delivery these prerequisites such as popup position, user context?&lt;/p&gt;

&lt;p&gt;Once the user uploads a photo through the popup, the system needs to unmount the popup, refresh the profile photos, and update the album counters on the screen.&lt;/p&gt;

&lt;p&gt;Without a long-polling mechanism or websockets, the question remains: How can we deliver an event about a new photo from one isolated micro-app to another?&lt;/p&gt;

&lt;p&gt;Although it's a simple scenario, choosing the right concept for exchanging events between micro-apps or designing their input/outputs is the challenge.&lt;br&gt;
There is no silver bullet solution, but various architectures can help address these questions such as utility modules and the centralised event manager.&lt;/p&gt;
&lt;h3&gt;
  
  
  Utility modules
&lt;/h3&gt;

&lt;p&gt;In the context of the photo uploader module, we can identify several APIs and events, such as opening the application, uploading a photo, and closing the application. By using existing MFE frameworks like &lt;code&gt;single-spa&lt;/code&gt;, we can handle mounting and unmounting issues. The main challenge is to communicate between micro-apps to notify them of an event like a photo upload.&lt;/p&gt;

&lt;p&gt;An observable mechanism can be beneficial in this scenario. We can create a simple class that encapsulates an observable, allowing us to emit events specified by an interface and subscribe to them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;UploaderManagerUtils&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nx"&gt;newPhotoSbj&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;Subject&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Photo&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nx"&gt;newPhoto$&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;Photo&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;UploaderManagerUtils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;newPhotoSbj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asObservable&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nx"&gt;createPhoto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;photo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Photo&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;UploaderManagerUtils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;newPhotoSbj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;photo&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;Another visual component can import this module from my lib and handle updates:&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;UploaderManagerUtils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;newPhoto$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;photo&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;this&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;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;photo&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;And another component can trigger this event:&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;UploaderManagerUtils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createPhoto&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;blob&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 a result, we can send uploading events with payloads without any event management systems, and all consumers can utilize them without limitations. For delivery purposes, &lt;code&gt;UploaderManagerUtils&lt;/code&gt; should be wrapped in an independent npm package to request webpack to import a single class instance for all micro-applications. This approach is called "&lt;strong&gt;Utility modules&lt;/strong&gt;".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Framework-agnostic solution.&lt;/li&gt;
&lt;li&gt;Supports any event implementation under the hood. The utility module should support two interfaces: one to emit and one to subscribe to payloads.&lt;/li&gt;
&lt;li&gt;Easy to test by mocking modules.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each micro-app requires an additional library to manage events, leading to logistical issues like maintaining multiple libraries, updating them for all micro-apps, and handling delivery issues.&lt;/li&gt;
&lt;li&gt;No specification. Theoretically, different and inefficient solutions could be used under the hood.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The centralised event manager
&lt;/h3&gt;

&lt;p&gt;The micro-apps concept emphasises isolation, but at the same time, we can imagine our own specification or API for them. We can create a simple wrapper for our micro-apps, which takes all external context and uses our libraries and API to integrate internal events with the external world, and vice versa. This is achieved by passing one event manager instance that transfers events and optionally helps with state management.&lt;/p&gt;

&lt;p&gt;While we lose some isolation because our micro-app relies completely on external parameters, we gain a robust communication layer. For example, if you want to communicate that a user uploads a photo, you don't need to create a new utility; you can just dispatch your command with the payload to the channel, and all external consumers can fetch your event. Additionally, your app can subscribe to external actions (e.g., Logout) to stop uploading properly.&lt;/p&gt;

&lt;p&gt;The one from the most popular system helping to organise it - &lt;code&gt;Redux&lt;/code&gt;. It seriously was recommended by any SPA framework, has the big community, materials, solutions. Official &lt;code&gt;single-spa&lt;/code&gt; shares the tip to use it if we want to simplify our application. &lt;br&gt;
So our app doesn’t need any additional libs and classes, I can take &lt;code&gt;dispatch&lt;/code&gt; function for the global store or use store API manually:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Redux&lt;/code&gt; is one of the most popular systems that can help organise this centralised event manager. It is widely recommended by many SPA frameworks and has a large community, materials, and solutions. The official &lt;code&gt;single-spa&lt;/code&gt; guide suggests using Redux if you want to simplify your application. So your app doesn't need any additional libraries and classes, and you can use the dispatch function for the global store or use the store API manually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; 
    &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UPLOADER__NEW_PHOTO&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;blob&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;After that I can subscribe to &lt;code&gt;this.store&lt;/code&gt; and filter actions or use reducers approach and work with my states.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Popular solution having many articles from React world.&lt;/li&gt;
&lt;li&gt;Can be easily integrate with any system.&lt;/li&gt;
&lt;li&gt;Provides a robust, consistent environment for all micro-apps.&lt;/li&gt;
&lt;li&gt;Avoiding many external dependencies.&lt;/li&gt;
&lt;li&gt;Easy to test my mocking events or using existing test redux frameworks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Micro-app will have a bottleneck and strict relationships by using the one communication stream.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Micro-frontends have emerged as a popular approach to simplifying complex applications by breaking them down into smaller, more manageable modules. When implementing micro-frontends, the communication layer is the cornerstone for seamless interaction between micro-apps.&lt;/p&gt;

&lt;p&gt;Consider the following solutions for efficient communication between micro-apps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Utility modules offer a framework-agnostic solution that supports emitting and subscribing to payloads. However, they may require additional libraries for each micro-app, leading to logistical challenges. Utility modules are ideal when you're uncertain about the future development of your product and need flexibility to balance requirements and needs.&lt;/li&gt;
&lt;li&gt;Centralised event managers, such as Redux, provide a consistent environment for all micro-apps and simplify communication. However, they may introduce a bottleneck and strict relationships between micro-apps. Centralised event managers are suitable when you want to focus on a single foundation and grow your product by adding new functionality, delivering modules, and providing continuous updates.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ultimately, the choice between utility modules and centralsed event managers depends on the specific requirements and constraints of your project. Carefully evaluate your project's needs to determine the most appropriate solution for efficient communication between micro-apps in your micro-frontend architecture.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>microfrontends</category>
      <category>frontend</category>
      <category>redux</category>
    </item>
    <item>
      <title>Yarn workspaces and change detection</title>
      <dc:creator>Dmitry Ruban</dc:creator>
      <pubDate>Wed, 23 Feb 2022 18:17:56 +0000</pubDate>
      <link>https://dev.to/roderekh/yarn-workspaces-and-change-detection-4428</link>
      <guid>https://dev.to/roderekh/yarn-workspaces-and-change-detection-4428</guid>
      <description>&lt;p&gt;Hello dev.to community!&lt;/p&gt;

&lt;p&gt;Perviously I wrote a short article about “&lt;a href="https://dev.to/cherypick/custom-modern-yarn-bundle-29no"&gt;How to create your own modern yarn cli bundle&lt;/a&gt;” where I explained how we can build own CLI containing our plugins set. The one important plugin from my own &lt;a href="https://github.com/RuBAN-GT/yarn-ultimate-cli"&gt;CLI&lt;/a&gt; - &lt;a href="https://github.com/RuBAN-GT/yarn-plugin-enhanced-workspaces"&gt;enhanced workspace plugin&lt;/a&gt; which can help to provide more predictable and controllable change detection mechanism helping to optimise CI/CD and reduce additional operations on developer machines. But before…a short history and motivation to create another one bicycle in npm repo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Motivation
&lt;/h2&gt;

&lt;p&gt;The long time ago in the one Galaxy my R&amp;amp;D team where I’m participating decided to choose Node.js + TypeScript as the main platform for FE &amp;amp; BE Web products in order to have the one efficient and scalable environment. Good idea! But after creation the many product our ecosystem we faced to the problem: we have many repositories and is really time consuming thing to manage all PRs over them, link them between each other, organise version management, request our CI/CD sequently and etc. &lt;br&gt;
The one obvious solution is to reduce repositories count and group them by the one monorepo. Fortunately we have many tools solving this problem: Bazel, Lerna, NX, Rush and Yarn. I my third article I have a plan to compare them by details and examples, but for now I just shortly say that after long discussions we decided to start from something quickest, easiest and extendable for us - yarn from the second version which provides flexible and good API for many cases.&lt;/p&gt;

&lt;p&gt;We updated our Jenkins Pipeline to support Yarn V2 workspaces, designed a project transaction plan to monorepos and everything was good except performance. &lt;a href="https://yarnpkg.com/cli/workspaces/foreach"&gt;Yarn workspace plugin&lt;/a&gt; has (till 3.1.1 version) has two critical issues for us:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Wildcard operation has problem with appropriate topological ordering. In rare cases parent dependencies can be built only after children.&lt;/li&gt;
&lt;li&gt;It doesn’t support the partial detection only for changed from some snapshot but it’s really important feature for any environment! (I know that is working from NX under the box)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this time we still wanted to support Yarn and decided to start a creation of our Magic tool doing everything and specially:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Provide robust dependencies tree control for monorepo dependencies.&lt;/li&gt;
&lt;li&gt;Help to determine what workspace was changes after previous commit or specific branch (master/main).&lt;/li&gt;
&lt;li&gt;Build graphs helping to organise parallel CD/CD jobs.&lt;/li&gt;
&lt;li&gt;Speedup development and CI/CD life by above points.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Great ambitious! And I can say that they were been achieved in this plugin: &lt;a href="https://github.com/RuBAN-GT/yarn-plugin-enhanced-workspaces"&gt;https://github.com/RuBAN-GT/yarn-plugin-enhanced-workspaces&lt;/a&gt;, hope it can help to other developers and make the Yarn more great and popular.&lt;/p&gt;

&lt;p&gt;And for now more details how does it work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enhanced workspace plugin details
&lt;/h2&gt;

&lt;p&gt;First of all sorry for the code, if you’ll find any moments that can be improved, feel free to open issues or your PRs.&lt;br&gt;
And for now about organisation.&lt;/p&gt;

&lt;p&gt;When I started to design core principles of my plugin I marked the several key moments:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Tree manager - the tool helping to build a workspace dependency tree with dependencies chunks &amp;amp; breadcrumbs that should forecasts appropriate ordering and allow the group nodes by groups in the future.&lt;/li&gt;
&lt;li&gt;Change detection manager - the tool which can distinguish necessary/unnecessary nodes by following specific config parameters, diffs from commits or branches or other rules.&lt;/li&gt;
&lt;li&gt;Group manager - the tool allows to combine tree nodes by groups with configurable limitations and ordering, it also ranks them in order to solve problems with the following dependency ordering (parent should be utilised before children).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Following these concepts the plugin exposes commands allowing to get nodes in different variants and provide operations over them like original &lt;code&gt;yarn workspaces foreach&lt;/code&gt; but with own logic and configuration. &lt;/p&gt;

&lt;p&gt;Instead of copy-pasting README I’ll show how to start to work with this plugin.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to work
&lt;/h2&gt;

&lt;p&gt;To get started everything whatever you need is to execute the command from your project:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;yarn plugin import https://raw.githubusercontent.com/RuBAN-GT/yarn-plugin-enhanced-workspaces/master/bundles/%40yarnpkg/plugin-enhanced-workspaces.js&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It should import plugin into your project.&lt;/p&gt;

&lt;p&gt;After it, for example, we have a common frontend monorepo where we have publishable packages as libraries and a one application.&lt;/p&gt;

&lt;p&gt;Is better to have a convention for your project in order to keep consistent infrastructure. For example you decided to provide build script from each project and package. We decided to use root &lt;code&gt;package.json&lt;/code&gt; and ask our pipeline to try to execute &lt;code&gt;build&lt;/code&gt; script:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;yarn workspaces changed foreach -p --ancestors --ignored-ancestors-markers="dist" run build&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This command tells: &lt;br&gt;
“Please, look on changed workspaces from previous master/main commit, perform for them &lt;code&gt;build&lt;/code&gt; command in parallel, if some of them require parent workspace, build it as well BUT if it already has &lt;code&gt;dist&lt;/code&gt; directory on package folder - skip it.”&lt;/p&gt;

&lt;p&gt;Simple but efficient. Moreover we can setup incremental builds using default TypeScript if we use set appropriate paths for example.&lt;/p&gt;

&lt;p&gt;You can play with already configured environment at &lt;a href="https://github.com/RuBAN-GT/monorepo-demo/tree/master/yarn.%E2%80%A8"&gt;https://github.com/RuBAN-GT/monorepo-demo/tree/master/yarn. &lt;/a&gt;&lt;br&gt;
In our case, our pipeline after all builds and tests will try to publish public packages (workspaces) using &lt;code&gt;yarn workspaces changed list --no-private&lt;/code&gt; by gathering all not private changed packages and using default &lt;code&gt;yarn --cwd=workspace_path npm publish --tolerate-republish&lt;/code&gt; to publish them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;I hope this solution can help to organise your development and CI/CD environment and speed up your processes. It doesn’t solve issues with watchers or caching but from the other hand is better that nothing) Moreover it may be can help somehow to the yarn community.&lt;/p&gt;

&lt;p&gt;If you have any questions, ideas, suggestions, feel free to ask!&lt;/p&gt;

&lt;p&gt;Good code everyone!&lt;/p&gt;

</description>
      <category>yarn</category>
      <category>npm</category>
      <category>javascript</category>
      <category>monorepo</category>
    </item>
    <item>
      <title>How to create your own modern yarn cli bundle</title>
      <dc:creator>Dmitry Ruban</dc:creator>
      <pubDate>Sun, 20 Feb 2022 18:40:12 +0000</pubDate>
      <link>https://dev.to/roderekh/custom-modern-yarn-bundle-29no</link>
      <guid>https://dev.to/roderekh/custom-modern-yarn-bundle-29no</guid>
      <description>&lt;p&gt;Hello dev.to community! &lt;br&gt;
This is my first post so I'm happy to start to share my experience (hope this will be useful for somebody) with monorepos and yarn tool here.&lt;/p&gt;

&lt;p&gt;In my current job I work with the big infrastructure of Node.js multiple repos such as single codebase or monorepos in different customer domains (Angular projects, pure JS, Node.js backends, etc) therefore is so critical to provide better developer and CI/CD experience when we need to work with hundreds projects by the one strategy.&lt;/p&gt;

&lt;p&gt;As a package manager we chose yarn berry (I believe I’ll prepare another one post where I’ll compare monorepo tools) because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pluggable system where we can extend existing functionality using JS.&lt;/li&gt;
&lt;li&gt;Efficient strategies to work with dependencies.&lt;/li&gt;
&lt;li&gt;New features from plugins such as modern workspaces like Lerna.&lt;/li&gt;
&lt;li&gt;Is easily to start to use yarn from any project without specific code base changes.&lt;/li&gt;
&lt;li&gt;We had experience with this tool.&lt;/li&gt;
&lt;li&gt;The way to control consistent client for all environments (CI, developers) with the one client version. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And in this post I want to focus about latest point and how I enhanced it.&lt;/p&gt;
&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;As I said above Yarn allows to add many really useful plugins to any project, all its binaries and extensions are stored at repository, it provides benefit that each developer or CI/CD environment uses the one consistent environment but from the other had we can face to the problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Yarn doesn’t provide any plugin version manager, I can’t verify that I have latest plugin version and therefore is more difficult that my plugin in specific project has needed version.&lt;/li&gt;
&lt;li&gt;If we have hundreds projects developer have to copy the one plugins set from one to one projects and is more pain to update them one by one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And when I read yarn API documentation I found very interesting part of it: &lt;a href="https://yarnpkg.com/builder/cli/build/bundle"&gt;yarn builder build&lt;/a&gt; bundle which helps to build own yarn cli clients having my own custom set of all required plugins with specific versions with my own version mark - this is solution!&lt;br&gt;
When I use it I can organise my own plugins manifest in package.json and commit their versions using simple dependencies versions where plugins work as simple npm packages.&lt;/p&gt;

&lt;p&gt;But this API has the one restriction - is internal building API. I didn’t find an appropriate way to use this builder in my clean project without additional artefacts but this is not a big problem and for now I can share a simple solution of it.&lt;/p&gt;
&lt;h2&gt;
  
  
  How to create CLI environment
&lt;/h2&gt;

&lt;p&gt;First of all you should initialise your project using yarn cli:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;yarn init&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After you should to set yarn berry in order to work with appropriate API:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;yarn set version berry&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the next step you should think about what you want to archive into your CLI: what plugins, versions, etc. You can take as example official yarn berry cli: &lt;a href="https://github.com/yarnpkg/berry/blob/master/packages/yarnpkg-cli/package.json"&gt;https://github.com/yarnpkg/berry/blob/master/packages/yarnpkg-cli/package.json&lt;/a&gt;&lt;br&gt;
This &lt;code&gt;package.json&lt;/code&gt; has several important sections:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;@yarnpkg/builder&lt;/code&gt; key where you can define profile with buildable plugins (it can be any local or custom plugins), if you don’t need to variate different plugins sets just define “standard” profile from example.&lt;/li&gt;
&lt;li&gt;In your dependencies (or dev) section set related from plugins list packages. It requires by builder to put sources into your cli.&lt;/li&gt;
&lt;li&gt;Add dev dependencies relying to your yarn version:

&lt;ul&gt;
&lt;li&gt;@yarnpkg/builder&lt;/li&gt;
&lt;li&gt;@yarnpkg/cli&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;version&lt;/code&gt; - this is your own version printed by “yarn --version”.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Additionally you can add build script for your CI/CD or just for simplifying:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;builder build bundle &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Looks easy? Ok, let’s try to execute:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;yarn builder build bundle&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But for now this is the problem of internal APIs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;➤ YN0000: ┌ Building the CLI
➤ YN0001: │ Error: Build failed with 1 error:
error: Could not resolve “/sources/cli.ts" 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yarn bundle builder is oriented to original berry repository and some internal scripts. I didn’t find any ways to solve this problems without fetching these files, therefore you should copy &lt;a href="https://github.com/yarnpkg/berry/tree/master/packages/yarnpkg-cli/sources"&gt;https://github.com/yarnpkg/berry/tree/master/packages/yarnpkg-cli/sources&lt;/a&gt; directory to your project/sources directory.&lt;/p&gt;

&lt;p&gt;If you’ll retry build command you should see a new one &lt;code&gt;bundles/yarn.js&lt;/code&gt; file - this is your bundle.&lt;/p&gt;

&lt;p&gt;As another one example, you can look on my bundle: &lt;a href="https://github.com/RuBAN-GT/yarn-ultimate-cli"&gt;https://github.com/RuBAN-GT/yarn-ultimate-cli&lt;/a&gt; having my own plugin helping to work with workspaces and determine their changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to use your CLI
&lt;/h2&gt;

&lt;p&gt;From 2-3.1.1 yarn versions yarn doesn’t support fetching external yarn clients from CDN but my simple enhancement was merged recently (&lt;a href="https://github.com/yarnpkg/berry/pull/4089"&gt;https://github.com/yarnpkg/berry/pull/4089&lt;/a&gt;) and we’ll can simply set our versions using &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;yarn set version &lt;a href="https://your_address/yarn.js"&gt;https://your_address/yarn.js&lt;/a&gt; &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But while yarn team didn’t published a new one minor release we can take the next workaround using availability to fetch yarn clients from file system:&lt;/p&gt;

&lt;p&gt;Fetch yarn js bundle using curl like: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt; curl -L '&lt;a href="https://raw.githubusercontent.com/RuBAN-GT/yarn-ultimate-cli/master/bundles/yarn.js"&gt;https://raw.githubusercontent.com/RuBAN-GT/yarn-ultimate-cli/master/bundles/yarn.js&lt;/a&gt;' &amp;gt; '/tmp/yarn.js'&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Set local fs version:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;yarn set version berry &amp;amp;&amp;amp; yarn set version /tmp/yarn.js&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you’ll execute &lt;code&gt;yarn --version&lt;/code&gt; you should to see your own version name. &lt;br&gt;
My congratulations!&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;I hope my post can help to know more about awesome Node.js package manager - Yarn and its API and ways to enhance your infrastructure. If you’ll face to issues with configurations of your bundles, feel free to ask from comments.&lt;/p&gt;

&lt;p&gt;Good code everyone!&lt;/p&gt;

</description>
      <category>yarn</category>
      <category>node</category>
      <category>javascript</category>
      <category>npm</category>
    </item>
  </channel>
</rss>
