<?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: Burhanuddin Udaipurwala</title>
    <description>The latest articles on DEV Community by Burhanuddin Udaipurwala (@burhanuday).</description>
    <link>https://dev.to/burhanuday</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%2F252808%2F70e2d493-2eef-4a54-adcb-265dcf628b07.png</url>
      <title>DEV Community: Burhanuddin Udaipurwala</title>
      <link>https://dev.to/burhanuday</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/burhanuday"/>
    <language>en</language>
    <item>
      <title>Module Federation in Production: architecture, development workflow, and deployments</title>
      <dc:creator>Burhanuddin Udaipurwala</dc:creator>
      <pubDate>Fri, 10 Mar 2023 05:56:25 +0000</pubDate>
      <link>https://dev.to/burhanuday/module-federation-in-production-architecture-development-workflow-and-deployments-3ahf</link>
      <guid>https://dev.to/burhanuday/module-federation-in-production-architecture-development-workflow-and-deployments-3ahf</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Micro-frontends are an architectural pattern that breaks a web application into smaller, loosely coupled, and independently deployable parts. Each part of the application is owned by a separate team and can be developed and deployed independently, allowing teams to work more efficiently and without interfering with each other&lt;/p&gt;

&lt;p&gt;This article focuses on optimising developer experience in a micro-frontend built with Module Federation while achieving team independence in deployments. A general understanding of Module Federation is assumed; if you need an introduction, you can watch my talk on Module Federation and how it works &lt;a href="https://www.youtube.com/watch?t=89&amp;amp;v=54RtNLMNkj8"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Module Federation
&lt;/h2&gt;

&lt;p&gt;Module federation is a feature of webpack 5 that enables developers to share code between multiple webpack builds, allowing them to communicate with each other and build distributed applications with greater scalability and flexibility.&lt;/p&gt;

&lt;p&gt;Module Federation has emerged as a powerful tool for enterprise-scale applications. It is easy to configure and allows code to scale horizontally rather than vertically, by distributing the code between different builds&lt;/p&gt;

&lt;h2&gt;
  
  
  Building a shell based architecture
&lt;/h2&gt;

&lt;p&gt;Module Federation is un-opinionated but my suggestion is to use a shell-based architecture, where the shell is a lightweight base that handles routing between micro-apps, initialisation of shared data stores, and lazy loading of each app. The shell is initialised first, and then, based on the route, it lazy loads the apps to be rendered.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dbEAOAqV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.burhanuday.com/static/images/blog/2023/devx-deployments-in-a-module-federated-micro-frontend/shell-based-architecture.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dbEAOAqV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.burhanuday.com/static/images/blog/2023/devx-deployments-in-a-module-federated-micro-frontend/shell-based-architecture.png" alt="Diagram showing a shell based architecture with three micro apps" width="880" height="416"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ideally, the shell should not contain any business logic and should only bring in the micro-apps that perform the actual work. However, routing between apps is one exception where some business logic may be required.&lt;/p&gt;

&lt;p&gt;The shell should not use any front-end framework, since the micro-apps themselves could be built with different frameworks. Additionally, any code added to the shell should be independent of any specific framework.&lt;/p&gt;

&lt;p&gt;To keep the shell lightweight, it's important to minimise the amount of code added to it. Adding code that is not required by all apps will unnecessarily increase the bundle size of the shell. Therefore, it's best to add only the necessary code and avoid adding anything that is not essential for its functionality.&lt;/p&gt;

&lt;p&gt;You could store common code, such as component libraries that are shared between all apps, in the shell. Alternatively, your micro-apps could be either "apps" or "packages". Packages are pieces of code that are imported by apps but can be deployed independently of them. The component library/ design system can be a “package” which is independent from other apps and can be also deployed independently.&lt;/p&gt;

&lt;p&gt;Micro apps should avoid direct communication with each other to prevent creating an implicit dependency between them. When one app changes its stored data, other apps that depend on it are affected, which adds undesired complexity.&lt;/p&gt;

&lt;p&gt;As an extension of above, one could build an architecture where there are multiple shells, and each shell is its own product. The shells load micro-apps which are required by the product&lt;/p&gt;

&lt;h2&gt;
  
  
  Optimising for developer experience
&lt;/h2&gt;

&lt;p&gt;A great developer experience in a micro-frontend would involve the ability to build an app in isolation. Unfortunately, this is not always possible due to the need for libraries or shared code that is imported from the shell at runtime. This can cause problems when the development server for the shell breaks because it tries to load code from another app whose development server is not started.&lt;/p&gt;

&lt;p&gt;To address this issue, you may have to spin up multiple development servers for different apps, even if you only want to work on one. While tools like &lt;a href="https://nx.dev/"&gt;Nx&lt;/a&gt; and &lt;a href="https://turbo.build/repo"&gt;Turborepo&lt;/a&gt; can help reduce this pain by allowing developers to share build cache between machines using the cloud, it would be even better if you didn't have to run those development servers at all. In the following section, I will explain how to achieve this.&lt;/p&gt;

&lt;p&gt;The goal is to only start the development server for the app you are working on. Other code should always be loaded from either a CDN or an already running server elsewhere. This ensures that you always get the latest code for apps developed by other teams. Additionally, which apps to be loaded from the local dev server and which ones to be loaded from the CDN should be granular and easy to switch between, like the press of a button.&lt;/p&gt;

&lt;p&gt;This is the system we'll be looking at: you can switch between a local development server and an already-built bundle of the micro-app with just the press of a button.&lt;/p&gt;

&lt;p&gt;In this example, we will use a client-rendered app. We will primarily use two tools: a browser plugin called &lt;a href="https://einaregilsson.com/redirector/"&gt;Redirector&lt;/a&gt; and a CDN like AWS's &lt;a href="https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Introduction.html"&gt;CloudFront&lt;/a&gt;. If you prefer serving static files or if the app is server-rendered, you can even use an &lt;a href="https://nginx.org/en/"&gt;NGINX&lt;/a&gt; reverse-proxy. However, for this example, we will only be using CloudFront.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--02mXiSjE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.burhanuday.com/static/images/blog/2023/devx-deployments-in-a-module-federated-micro-frontend/full-architecture.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--02mXiSjE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.burhanuday.com/static/images/blog/2023/devx-deployments-in-a-module-federated-micro-frontend/full-architecture.png" alt="Architecture diagram showing use of redirector extension" width="880" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Switch between pre-built bundles and the development server using the Redirector extension
&lt;/h3&gt;

&lt;p&gt;Let's discuss the switch that enables us to granularly switch between a local build and a cloud build. This switch is essentially the &lt;a href="https://einaregilsson.com/redirector/"&gt;Redirector browser extension&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The advantage of using this browser plugin instead of passing arguments on the command line interface (CLI) is that you do not need to restart the webpack development server.&lt;/p&gt;

&lt;p&gt;The way the redirector extension works is by using a regex pattern. It examines all outgoing requests and redirects any request whose path matches the regex pattern to another URL specified by you. This URL can be the path of the local development server.&lt;/p&gt;

&lt;p&gt;The extension allows us to add multiple regex patterns, each representing the URL of a micro-app. These can be easily enabled or disabled with the click of a button.&lt;/p&gt;

&lt;p&gt;Since we expect to be building many micro apps, it is important to establish a naming scheme. A possible scheme is to include a path in the middle, such as &lt;code&gt;/federated/&lt;/code&gt;. This way, each app can have a unique URL like &lt;code&gt;/federated/my-micro-app/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So lets say the CDN is at the URL &lt;code&gt;https://my-federated-app.com&lt;/code&gt; and the remote entry file for the micro-app is at &lt;code&gt;https://my-federated-app.com/federated/my-micro-app/remoteEntry.js&lt;/code&gt;. Then, if I want to work on this app using a local development server, I can redirect any request containing the pattern &lt;code&gt;/federated/my-micro-app/&lt;/code&gt; to &lt;code&gt;http://localhost:3000&lt;/code&gt; , where the development server is running. Here’s an example of the configuration that does the above job:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mLeUpZDj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.burhanuday.com/static/images/blog/2023/devx-deployments-in-a-module-federated-micro-frontend/redirector-example-config.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mLeUpZDj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.burhanuday.com/static/images/blog/2023/devx-deployments-in-a-module-federated-micro-frontend/redirector-example-config.png" alt="Example of redirector configuration" width="880" height="742"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This way, I can have multiple apps running locally, each development server running on a different port. I can switch between their local and cloud builds using the Redirector browser extension by enabling or disabling this rule&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Sz4pQ-qx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.burhanuday.com/static/images/blog/2023/devx-deployments-in-a-module-federated-micro-frontend/switch-micro-app.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Sz4pQ-qx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.burhanuday.com/static/images/blog/2023/devx-deployments-in-a-module-federated-micro-frontend/switch-micro-app.png" alt="Switch for my-micro-app" width="880" height="169"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The CloudFront configuration
&lt;/h3&gt;

&lt;p&gt;The configuration will be similar to that of the Redirector plugin. The idea is to use CloudFront's “behaviors” option to route requests appropriately to the folder in S3 where the app is stored.&lt;/p&gt;

&lt;p&gt;For example, let's consider the following structure for storing builds in S3 for all of your apps.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;|--&lt;/span&gt; &lt;span class="err"&gt;shell&lt;/span&gt;
&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="s"&gt;---- remoteEntry.js&lt;/span&gt;
&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="s"&gt;---- (other js assets)&lt;/span&gt;
&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="s"&gt;-- my-micro-app&lt;/span&gt;
&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="s"&gt;---- remoteEntry.js&lt;/span&gt;
&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="s"&gt;---- (other js assets)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, you can configure the default behavior of CloudFront to fetch files from the &lt;code&gt;shell&lt;/code&gt; folder.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8wHQP66i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.burhanuday.com/static/images/blog/2023/devx-deployments-in-a-module-federated-micro-frontend/request-flow-cdn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8wHQP66i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.burhanuday.com/static/images/blog/2023/devx-deployments-in-a-module-federated-micro-frontend/request-flow-cdn.png" alt="Diagram showing redirection based on path in CloudFront" width="880" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If your domain is &lt;code&gt;my-federated-app.com&lt;/code&gt;, by default, all requests will go to the shell folder. In the CDN configuration, you can add a behavior to redirect any request that contains the path &lt;code&gt;/federated/my-micro-app/&lt;/code&gt; to the corresponding “my-micro-app” folder using the pattern &lt;code&gt;federated/my-micro-app/*&lt;/code&gt;. You will need to configure this for each micro app that you build.&lt;/p&gt;

&lt;p&gt;Note: An important thing to keep in mind for client-side rendered apps is cache busting of remote entry files. Since you can't use content hash to name these files, they will get cached at the CDN and in the user's browser, which can cause problems when builds are out of sync. One way to fix this issue is to invalidate the CDN cache after every app deployment.&lt;/p&gt;

&lt;p&gt;Note 2: Alternatively, you can create a "federated" folder inside the "shell" folder. However, this is not recommended as a simple mistake could override all the files inside the "federated" folder or even delete that folder.&lt;/p&gt;

&lt;p&gt;Note 3: Depending on the size of your team and organisation, you could use the same CloudFront configuration to serve apps from different buckets. Each micro-app would have its own S3 bucket, allowing for even more separation. For even larger scale, each app could have its own CloudFront CDN with a dedicated sub-domain to serve assets from.&lt;/p&gt;

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

&lt;p&gt;In conclusion, Module Federation is a powerful tool for building large-scale micro-frontend architectures. By breaking up a web application into smaller, independently deployable micro-apps, teams can work more efficiently and without interfering with each other. Using a shell-based architecture and minimising direct communication between micro-apps can further optimise the scalability and flexibility of these architectures. Finally, optimising for developer experience can be achieved by using tools such as the Redirector browser extension and AWS's CloudFront CDN.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This is the first article in a new series I am writing on micro-frontends with Module Federation. In the next article, I will discuss state management strategies to be used in a micro-frontend. If you'd like to be notified when I next publish an article, you can subscribe to the newsletter at &lt;a href="https://burhanuday.com"&gt;burhanuday.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Monolith to Module Federation at RazorpayX</title>
      <dc:creator>Burhanuddin Udaipurwala</dc:creator>
      <pubDate>Sat, 18 Feb 2023 10:23:12 +0000</pubDate>
      <link>https://dev.to/burhanuday/monolith-to-module-federation-at-razorpayx-3e8p</link>
      <guid>https://dev.to/burhanuday/monolith-to-module-federation-at-razorpayx-3e8p</guid>
      <description>&lt;h2&gt;
  
  
  Growing fast at RazorpayX
&lt;/h2&gt;

&lt;p&gt;RazorpayX is a neobank for businesses that combines the best of B2B SaaS and B2B Banking, to make finance simpler and more efficient. Its state-of-the-art Current Account combined with award-winning Payroll, Corporate Cards, Vendor Payments, Tax Filing and Accounting solutions, helps businesses manage all their financial activities from one place&lt;/p&gt;

&lt;p&gt;We experienced exponential growth at RazorpayX during the pandemic when online payments became the norm. With more businesses going online, business owners saw RazorpayX as their one-stop shop for all of their banking needs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---Vmcq9hK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/800/0%2A8Td3oas-pCXQLAkR" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---Vmcq9hK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/800/0%2A8Td3oas-pCXQLAkR" alt="products offered by RazorpayX before and after Covid19" width="800" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As a result, RazorpayX’s frontend developer count has more than doubled. Simultaneously, to serve a broader range of businesses, we introduced significant products such as the Chartered Accountant Portal and Vendor Portal. Our codebase had become a giant monolith and developer productivity as well as the speed of delivery of features was taking a hit.&lt;/p&gt;

&lt;p&gt;To give you an idea of how challenging it had become to maintain the monolith, the upgrade from React 16 to React 17 took more than two weeks to complete. Due to the large codebase, we had to upgrade React all at once for the whole dashboard, which meant fixing all breaking changes between the two React versions in one go and risking regression when pushing such a large change.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why did we reach such a stage?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Lack of a reusable Auth&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The authentication system was not designed to be reusable and support multiple apps.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Inability to quickly spin up infra for projects&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Creating new codebases required the creation of CI pipelines and other deployment infrastructure on AWS. This was not a priority during a time when getting the product to market quickly was critical.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Lack of a reusable component library&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We had UI components built in the same repo rather than a library. As a result, we were unable to easily share UI component code between products.&lt;/p&gt;

&lt;h3&gt;
  
  
  Issues due to the monolith
&lt;/h3&gt;

&lt;p&gt;We began to encounter some issues as the codebase grew in size:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Long build times&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As the size of the codebase increased, it took longer to start the development server and for HMR to reflect developer changes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Long-running unit tests&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Time to execute Unit tests grew exponentially with more and more apps being powered by RazorpayX’s repo.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;High cognitive load&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since code for multiple apps resides in the same repository, it increased the surface area of code a developer needs to understand thereby increasing the cognitive load on a developer.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Lack of independent CI/CD&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because the same codebase that powers the RazorpayX dashboard for merchants, also powered the dashboard for vendors, chartered accountants and tax payments, any small change in one app required the deployment of all the apps.&lt;/p&gt;

&lt;p&gt;So we began to consider what we could do about it: can we break our codebase into smaller independent modules, where each module could be developed, tested, and also deployed independently from the others?&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding the right way to do it
&lt;/h2&gt;

&lt;p&gt;The first project to be moved away from the X Dashboard codebase was &lt;strong&gt;Vendor Portal.&lt;/strong&gt; We chose Vendor Portal because, if not for the above explained constraints, it would have been an independent project. It was less coupled with other code in the codebase and would serve well as an experimentation project.&lt;/p&gt;

&lt;p&gt;Before adopting a potential solution, we devised a set of criteria that it must meet.&lt;/p&gt;

&lt;h3&gt;
  
  
  The criteria for the solution
&lt;/h3&gt;

&lt;p&gt;In addition to solving the above discussed pain points, the ideal solution would check all of the following boxes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Should have good developer experience.&lt;/li&gt;
&lt;li&gt;Should not require drastic changes to the codebase.&lt;/li&gt;
&lt;li&gt;Should be relatively easy to configure.&lt;/li&gt;
&lt;li&gt;Should have a gradual learning curve for developers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Potential solutions
&lt;/h3&gt;

&lt;p&gt;After a lot of brainstorming around the problem statement, we came up with a few things that could be implemented:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Publish each app as an NPM package&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each app could be published as a package to NPM. The package version in the host can then be updated, and the host must be redeployed&lt;br&gt;
   The limitation of this approach is that we would have to redeploy the host every time we published a new version of a micro app. This method works for libraries that require versioning, but it slows down deployments for projects that require continuous delivery&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Bundle each micro-app individually and load with a Script tag&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each micro-app is bundled and uploaded to S3 or a similar store. The host app loads the script via the URL&lt;br&gt;
   This method is very crude. Deduplication of dependencies, for example, is completely manual and must be configured for each project so that a dependency is loaded only once. In the case of some packages, such as React, the library should only be instantiated once as a singleton which adds more complexity&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Using micro frontend frameworks&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There are numerous micro-frontend frameworks like &lt;a href="https://single-spa.js.org/"&gt;Single SPA&lt;/a&gt;, &lt;a href="https://opencomponents.github.io/"&gt;Open Components&lt;/a&gt;, &lt;a href="https://www.mosaic9.org/"&gt;Mosaic&lt;/a&gt;, and so on&lt;br&gt;
   The configuration for these tools can get complex and difficult to manage as we add more apps since they require configuration at each layer — routing, dependency management, and development. This would complicate our tooling and hence, would not work for us.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Using Module Federation with webpack 5&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Module federation is a webpack5 feature that allows a JavaScript application to run code from another build. It allows us to reference code from a different project at runtime. You can read more about the concept &lt;a href="https://webpack.js.org/concepts/module-federation/#root"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Module Federation is a run-time concept, and other tools, like Jest and Typescript, lack the same functionality. Making other tooling operate with Module Federation is complicated and requires a lot of configuration&lt;/p&gt;

&lt;p&gt;Among the solutions we tried, &lt;strong&gt;Module Federation&lt;/strong&gt; turned out to be the solution that ticked all the boxes.&lt;/p&gt;
&lt;h2&gt;
  
  
  What is Module Federation?
&lt;/h2&gt;

&lt;p&gt;In simple words — it allows you to share code between different webpack builds at runtime. It enables you to expose files from one build and consume them in another. It is a method of achieving a micro frontend architecture.&lt;/p&gt;

&lt;p&gt;Module Federation creates a very thin but well-defined contract layer between apps. It allows you to be flexible with what you want to slice out of the codebase and if the transition doesn’t work well, it also makes it easy to bring the application piece back in.&lt;/p&gt;
&lt;h3&gt;
  
  
  Our proposed architecture
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--B4pHQdoG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/800/0%2A4lQs6FGMLIAvhVL3" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--B4pHQdoG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/800/0%2A4lQs6FGMLIAvhVL3" alt="shell based architecture with three apps that are a part of the shell" width="800" height="266"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The architecture we are aiming to build is a shell driven federation. The shell contains the logic for navigation, lazy loading of routes, instantiates a common Redux store to be shared between all apps, and exposes code shared between all micro apps. Each team can deploy their changes independently.&lt;/p&gt;

&lt;p&gt;An important thing to note here is that we do not want to share any code between apps. This can create a mesh of dependencies which might result in future bugs.&lt;/p&gt;

&lt;p&gt;After the migration of the Vendor Portal to a federated bundle, the system currently looks like this (simplified)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8ESwrxTg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/800/0%2AmsOl1zOmKJ_5mxMM" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8ESwrxTg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/800/0%2AmsOl1zOmKJ_5mxMM" alt="simplified deployment flow after module federation with shell based architecture" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The monolith (shell) exposes UI components that are used in the Vendor Portal codebase. The shell and Vendor Portal have their own independent deployment pipelines and are stitched together at run-time by webpack in the browser.&lt;/p&gt;
&lt;h2&gt;
  
  
  Migration and Challenges
&lt;/h2&gt;

&lt;p&gt;Moving to a federated architecture wasn’t easy. It took us a little less than 3 months to properly migrate Vendor Portal completely. We faced a few hurdles along the way and built tooling and processes that worked for our teams.&lt;/p&gt;

&lt;p&gt;As a part of the migration process, we also migrated the Vendor Portal code to a monorepo because it makes solving the below challenges easier.&lt;/p&gt;

&lt;p&gt;Now, let’s deep dive into some of the challenges we faced and how we solved them.&lt;/p&gt;
&lt;h3&gt;
  
  
  Sharing dependencies
&lt;/h3&gt;

&lt;p&gt;A common problem with all micro frontends is how to de-duplicate dependencies. This is important because we don’t download the same dependency twice&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;MomentJS: Both, X Dashboard and Vendor Portal, use moment for date and time, and we want it to be loaded only once in the browser. At the same time, we want to ensure that the version loaded is compatible with the modules that rely on it.&lt;/li&gt;
&lt;li&gt;React: Dependencies that have an internal state, like React, should be instantiated only once and then reused across all federated modules as a singleton.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We wrote a utility function to solve this problem:&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;dependencies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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;../package.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;dependencies&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getSharedDependencies&lt;/span&gt; &lt;span class="o"&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="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;singletonPackages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// other singleton dependencies here&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;sharedDependencies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;keys&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="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;dependencyName&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;sharedDependencies&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;dependencyName&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="na"&gt;singleton&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;singletonPackages&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;dependencyName&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="nx"&gt;dependencies&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;dependencyName&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;return&lt;/span&gt; &lt;span class="nx"&gt;deps&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then in the configuration for Module Federation plugin:&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;new&lt;/span&gt; &lt;span class="nx"&gt;ModuleFederationPlugin&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
   &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="na"&gt;shared&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;getSharedDependencies&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;h3&gt;
  
  
  Testing in federated modules
&lt;/h3&gt;

&lt;p&gt;We run tests on the pre-commit hook using Husky. Since the code in Vendor Portal is dependent on UI code from X Dashboard, it must be present when tests are run (this is not an issue if the code is in a monorepo).&lt;/p&gt;

&lt;p&gt;We leveraged jest’s &lt;em&gt;moduleNameMapper&lt;/em&gt; to rewrite certain imports by Jest. This allows us to use actual code for running tests and not mocks as mock code in our tests would mean that tests will pass even after a breaking change if the dev forgot to update the mocks.&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;xRepoBasePath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;rootDir&amp;gt;/../../razorpayx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="na"&gt;moduleNameMapper&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="c1"&gt;// module federation related config&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;^razorpayx/store&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;xRepoBasePath&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/src/js/store`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;^razorpayx/ui&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;xRepoBasePath&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/src/js/ui/index`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;^razorpayx/views&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;xRepoBasePath&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/src/js/views/index`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;^razorpayx/model&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;xRepoBasePath&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/src/js/model/index`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;^razorpayx/modules&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;xRepoBasePath&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/src/js/modules/index`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;^razorpayx/api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;xRepoBasePath&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/src/js/api/api`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Type-checking
&lt;/h3&gt;

&lt;p&gt;At RazorpayX, we have been migrating towards Typescript and want to be able to use the types defined for our UI code. We want type safety and auto-completion for developers writing their code locally. On CI, we want to run type checks to make sure that there are no TS errors.&lt;/p&gt;

&lt;p&gt;For this, we use &lt;strong&gt;Typescript’s Project References feature&lt;/strong&gt;. It enables a project to reference types from a different project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"paths"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"razorpayx/ui"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;razorpayx&amp;gt;/src/js/ui/index"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"razorpayx/views"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;razorpayx&amp;gt;/src/js/views/index"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"razorpayx/model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;razorpayx&amp;gt;/src/js/model/index"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"razorpayx/modules"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;razorpayx&amp;gt;/src/js/modules/index"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"razorpayx/api"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;razorpayx&amp;gt;/src/js/api/api"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"razorpayx/store"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;razorpayx&amp;gt;/src/js/store"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"references"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;razorpayx&amp;gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above example is tsconfig.json file of Vendor Portal. In the references array, we add a path to the RazorpayX Dashboard codebase. It tells TypeScript about which other projects to reference for types. In the paths property, we assign types to the code exported from the RazorpayX dashboard using their path. This does require you to have both codebases on your local machine as well as CI, although this is not a challenge if your code resides in a monorepo.&lt;/p&gt;

&lt;p&gt;Note: If your code is not inside a monorepo, you could take a look at the recently open-sourced &lt;a href="https://github.com/module-federation/typescript"&gt;Types Federation Plugin&lt;/a&gt;. One drawback of this plugin is having to manually add types to imports which the above approach does not suffer from.&lt;/p&gt;

&lt;h3&gt;
  
  
  CI actions with multiple repositories
&lt;/h3&gt;

&lt;p&gt;We use GitHub actions for running tests and type-checking on PRs. Since not all of our code is in a single repository, for the time being, we clone both the repositories we need in the workflow. Checking out code is fast on GitHub actions so it has not affected the CI times in a significant manner.&lt;/p&gt;

&lt;p&gt;We then run the tests command and type-checking on the Vendor Portal codebase on every push to the repo against the master branch of the RazorpayX Dashboard codebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  What has this effort resulted in?
&lt;/h2&gt;

&lt;p&gt;After the migration, vendor portal has its own codebase, independent CI/CD pipelines, independent dependency management. All this has led to the following improvements:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Before (entire dashboard)&lt;/th&gt;
&lt;th&gt;After (independent module)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Build time&lt;/td&gt;
&lt;td&gt;180+ seconds&lt;/td&gt;
&lt;td&gt;14 seconds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Starting development server&lt;/td&gt;
&lt;td&gt;90+ seconds&lt;/td&gt;
&lt;td&gt;12 seconds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Running tests&lt;/td&gt;
&lt;td&gt;8-10 minutes&lt;/td&gt;
&lt;td&gt;~2 minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deployments&lt;/td&gt;
&lt;td&gt;The entire codebase has to be built and all apps will be deployed.&lt;/td&gt;
&lt;td&gt;Only Vendor Portal code is built and a single app is deployed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cognitive load on developers&lt;/td&gt;
&lt;td&gt;High cognitive load owing to the large codebase size&lt;/td&gt;
&lt;td&gt;Limited codebase size ensures faster onboarding and ease of development&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dependency management&lt;/td&gt;
&lt;td&gt;Change in dependency version affects all apps powered by the codebase&lt;/td&gt;
&lt;td&gt;Dependency versions can be scoped to apps which ensures that each app loads its supported versions&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Where do we go from here…?
&lt;/h2&gt;

&lt;p&gt;Overall, Module Federation has solved a lot of problems for us and we are migrating towards a federated architecture to enable developers to ship faster.&lt;/p&gt;

&lt;p&gt;We are working on solving the developer experience hurdles that a distributed micro frontend can create and at the same time, ensuring that the code we ship is resilient.&lt;/p&gt;

&lt;p&gt;Having infrastructure pieces that support this architecture has been of tremendous help. Check out &lt;a href="https://github.com/razorpay/devstack"&gt;Devstack on GitHub&lt;/a&gt; which allows us to use different commits when we develop Vendor Portal.&lt;/p&gt;

&lt;p&gt;If you want to understand our decision-making and reasoning about Module Federation in more detail, you can watch this talk we gave about the same on &lt;a href="https://youtu.be/54RtNLMNkj8?t=89"&gt;YouTube&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This article was originally published at &lt;a href="https://medium.com/p/8c400b4e5646"&gt;Razorpay's Engineering Blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Get updated when I next post, subscribe at &lt;a href="https://burhanuday.com"&gt;burhanuday.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>microservices</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Hitting the tech local maxima</title>
      <dc:creator>Burhanuddin Udaipurwala</dc:creator>
      <pubDate>Wed, 05 Oct 2022 08:31:31 +0000</pubDate>
      <link>https://dev.to/burhanuday/hitting-the-tech-local-maxima-23a2</link>
      <guid>https://dev.to/burhanuday/hitting-the-tech-local-maxima-23a2</guid>
      <description>&lt;h2&gt;
  
  
  What exactly is a local maximum?
&lt;/h2&gt;

&lt;p&gt;I am not using the mathematical definition of the term. For the purpose of this discussion, let’s have two functions of effort spent vs value generated.&lt;/p&gt;

&lt;p&gt;Initially, both functions are linear in nature, where spending more effort generates more value. Spending more effort leads to diminishing returns after the point where the most value is generated.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GcyrvJ1T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://burhanuday.com/static/images/blog/2022/hitting-the-tech-local-maxima/initial-graph.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GcyrvJ1T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://burhanuday.com/static/images/blog/2022/hitting-the-tech-local-maxima/initial-graph.png" alt="graph of effort spent vs value generated" width="880" height="402"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now you have to make a decision about which function you choose:&lt;/p&gt;

&lt;p&gt;The first requires a lot less effort to reach the point where you generate the most value. The caveat is that it does not generate as much value as the other option in the end.&lt;/p&gt;

&lt;p&gt;The other option is a “global maximum”. It is a decision, which if you take it, will need high effort. The advantage of taking this decision is that it will generate more value before you reach the maxima.&lt;/p&gt;

&lt;p&gt;To limit the scope of this discussion, we will limit the functions to the point where the maxima are reached.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ncHCnj6l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://burhanuday.com/static/images/blog/2022/hitting-the-tech-local-maxima/scoped-graph.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ncHCnj6l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://burhanuday.com/static/images/blog/2022/hitting-the-tech-local-maxima/scoped-graph.png" alt="graph of effort spent vs value generated but limited to maxima" width="880" height="392"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s assume that once the maxima are reached, no more effort is spent.&lt;/p&gt;

&lt;p&gt;Also, let’s not argue about where the points are on the graph. The graph is not to scale.&lt;/p&gt;

&lt;p&gt;So you might be thinking “boring problem” or “how does it relate to my job?”. Well, let me give you an example:&lt;/p&gt;

&lt;h2&gt;
  
  
  The library conundrum
&lt;/h2&gt;

&lt;p&gt;Let’s imagine a scenario. You started working on a new greenfield project at your company. You have to architect the frontend, so you start working on how the codebase will be structured and which libraries will be used.&lt;/p&gt;

&lt;p&gt;State management is an important choice to be made. You think about using a server state management library since the dashboard you are building is a UI that displays some data to the end user. You research which server state management libraries are popular at the moment, and you see two of them being talked about a lot — &lt;a href="https://react-query-v3.tanstack.com/"&gt;React Query&lt;/a&gt; and &lt;a href="https://swr.vercel.app/"&gt;SWR&lt;/a&gt;. You also have to keep in mind that nobody in the team for the project has used either of them before.&lt;/p&gt;

&lt;p&gt;You start evaluating the two of them and come to the following conclusions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React Query is a powerful library that can handle both queries and mutations. It has a steeper learning curve compared to SWR. It does a lot more than SWR can, and you’ll be extracting a lot more value from it. But it requires a lot of educational effort to be made&lt;/li&gt;
&lt;li&gt;SWR is a simple data fetching library. It cannot handle mutations, but the learning curve is very gradual and the developers will pick it up quickly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Which brings us to the original conundrum:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You could use React Query. It would have a steep learning curve, and the developers would take more time to get onboard with it. It could also slow down the development a bit in the initial phases. A steep learning curve would also mean that a lot of mistakes would be made before best practises are established.&lt;/li&gt;
&lt;li&gt;Or you could use SWR. It is simple to get onboarded to and does not require a lot of configuration to get working. But the issue with SWR is that it does not handle mutations and might be missing some things. Due to the simplicity of the library, there will be fewer mis-steps and development speed will not be affected.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Concerns
&lt;/h2&gt;

&lt;p&gt;In an ideal world, there would be a right decision to be made with a book explaining why. Since we don’t live in an ideal world, we often have to make decisions based on incomplete information and an optimistic mindset.&lt;/p&gt;

&lt;h3&gt;
  
  
  The time dilemma
&lt;/h3&gt;

&lt;p&gt;Do you know what’s worse than making the wrong decision? Making the right decision but leaving it half done&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FBVdb0xE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://burhanuday.com/static/images/blog/2022/hitting-the-tech-local-maxima/developer-meme.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FBVdb0xE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://burhanuday.com/static/images/blog/2022/hitting-the-tech-local-maxima/developer-meme.png" alt="meme showing developers like new libraries and forget about ongoing migrations" width="750" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.burhanuday.com/blog/2022/07/driving-technical-change"&gt;Making a decision is one thing, but driving it is another&lt;/a&gt;. If the decision you take requires more sustained effort, you have to make sure that the effort is actually put in. Otherwise, even if you commit to the “higher effort, higher final value” option, you will never extract the full value. The incomplete work will live in pieces and cause more problems&lt;/p&gt;

&lt;p&gt;On the other hand, if you have to spend less effort, it might be comparatively easier to get it prioritised. It will also reach its full potential in less time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Post completion shock
&lt;/h3&gt;

&lt;p&gt;Let’s say you chose the "lower effort, lower final value" and then drove it to completion. At the end of it, you are not happy with the value you have extracted. Now that the decision has been made and the work is completed, you can’t do anything about it.&lt;/p&gt;

&lt;p&gt;You feel like you should have taken the other decision, even though it required more effort to be put in. You would have received more value out of it on completion. What if…&lt;/p&gt;

&lt;h2&gt;
  
  
  Making the choice
&lt;/h2&gt;

&lt;p&gt;Looking for an answer? I don’t have one. Ask an experienced engineer and they’ll tell you.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--C8EXVDW6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://burhanuday.com/static/images/blog/2022/hitting-the-tech-local-maxima/tweet.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--C8EXVDW6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://burhanuday.com/static/images/blog/2022/hitting-the-tech-local-maxima/tweet.png" alt="graph of effort spent vs value generated" width="880" height="765"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Have you made a decision? Let me know on &lt;a href="https://twitter.com/burhanuday"&gt;Twitter&lt;/a&gt; or by &lt;a href="//mailto:udaipurwalaburhanuddin@gmail.com"&gt;Email&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>career</category>
    </item>
    <item>
      <title>Driving technical change</title>
      <dc:creator>Burhanuddin Udaipurwala</dc:creator>
      <pubDate>Tue, 05 Jul 2022 03:55:50 +0000</pubDate>
      <link>https://dev.to/burhanuday/driving-technical-change-2fgm</link>
      <guid>https://dev.to/burhanuday/driving-technical-change-2fgm</guid>
      <description>&lt;p&gt;A young engineer just joined your company. They've come straight out of college and have mostly worked on solo projects prior. They discover that the documentation in the codebase is inadequate, so they add a new user-friendly tool to improve the documentation. Nobody cares. The newbie is surprised at how nobody wants to see an improvement made. In the newbie's mind, the tool they added improved the documentation of the codebase. Why would everyone not want to contribute to it?&lt;/p&gt;

&lt;p&gt;A senior engineer then mentors them on how to drive technical change. He tells them:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Implementing something is the first part. Driving change is the next. Like a bus going at high speeds, an engineer has inertia. Until a force is applied, they won't change the direction they're going.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now imagine the newbie is you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is it worth the effort?
&lt;/h2&gt;

&lt;p&gt;Bringing about change requires active work to be done. Before you even start driving it, you must ask yourself the following questions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Do you &lt;em&gt;completely&lt;/em&gt; understand the problem that you're trying to solve?&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Before you even start solving it, make sure you have a deep understanding of the problem. For this, you can speak to your colleagues and ask around if the problem you're trying to solve is being faced by a lot of people. You'll come to understand the challenge and gain a deeper understanding.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Is the problem you're trying to solve "important" enough&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Some problems are just inconveniences that one can live with. Like auto-formatting not working for a file extension. Then some problems are productivity killers. For an example, think how much slower web development would be without Hot Module Reload.&lt;/p&gt;

&lt;p&gt;So it's better first to solve problems that you know are "important" problems that if solved, would have a large impact&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Has someone else tried (and failed) before you?&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If the problem is obvious, then there is bound to be someone who has tried to solve it before you. Ask around if something of the sort has happened. They probably solved it differently, and as the saying goes:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Smart people learn from their mistakes. But the real sharp ones learn from the mistakes of others&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Not only that, knowing the previous solutions and their shortcomings, you'll be able to come up with a better one that caters to your specific requirements.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;What solution do you have in mind?&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So you discussed the problem, and you know it exists, but can you solve it? It's best to come up with multiple ways to solve a challenge and then compare them to figure out which one works best for your particular use case. Not every solution is created equal, after all.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Enforceability&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Is it possible to enforce the change? For example, if you intend to set a standard for code style, you can use a tool like Prettier or Eslint to enforce this. On the other hand, let's say you are proposing that all developers write unit tests. There might not be an easy way to enforce this.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Is the result worth the investment?&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is the most important question to answer. The costs should justify the returns. This again ties back to a previous question—"is it important enough?" You need to weigh the outcomes with the effort you're putting in to solve the problem.&lt;/p&gt;

&lt;p&gt;What if your solution only works for a short term and becomes completely obsolete after that.&lt;/p&gt;

&lt;h2&gt;
  
  
  To pave the way for the future
&lt;/h2&gt;

&lt;p&gt;So you've understood the problem, figured out the solution and are wearing your battle armour ready to mash some buttons on your keyboard. But hold on, you can't do everything alone, right? Not forever, anyway. So you need to convince your peers to help you. But why will they? They have plenty to do on their own. They don't want to do extra work they aren't getting paid for.&lt;/p&gt;

&lt;h3&gt;
  
  
  Convincing the leadership
&lt;/h3&gt;

&lt;p&gt;You decide to talk to your manager about it so your peers can get dedicated bandwidth for it. But how exactly are you going to explain it to them? They are not from the same domain as you are, and even if they are, they haven't written a line of code in years. And god forbid, your manager is not a tech person at all.&lt;/p&gt;

&lt;p&gt;So you build a demo. A simple MVP that demonstrates both the problem and the solution without any other bells and whistles. The manager seems to be impressed with your demo. They speak to the skip manager about the change you are proposing and how it is going to solve a problem. The skip manager then asks -&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Well, our sales numbers for the past year ain't lookin' so good. Can this tool help with that?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hmmm... so how do you convince a company that is working on rapid product development to slow that down and give you, and probably others, bandwidth to work on this pure tech project?&lt;/p&gt;

&lt;p&gt;It's pretty simple really - &lt;strong&gt;Show its business impact.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Can your proposed change reduce the build time by half? Tell them faster deployments equate to better developer productivity, which equates to more stuff being built faster.&lt;/p&gt;

&lt;p&gt;Can your proposed change make documentation more intuitive? Tell them better documentation equates to better developer productivity, which equates to more stuff being built, faster&lt;/p&gt;

&lt;p&gt;Can your proposed change reduce production errors? Tell them it will improve customer delight.&lt;/p&gt;

&lt;p&gt;Every company cares about profits, but companies also care about customer satisfaction, employee productivity, and attrition rates. If you can push any of these metrics in the company's favour, then you will be allocated what is required.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defining a success metric
&lt;/h3&gt;

&lt;p&gt;That alone won't suffice. You need to decide on a metric. A number to push will not only tell leadership that progress is being made, but it will also give confidence that your solution is working.&lt;/p&gt;

&lt;p&gt;When starting, decide on a baseline. Then decide on a short-term goal for the next month and a long-term goal for the next three months. This will give you direction and tell you how slow or fast you are moving.&lt;/p&gt;

&lt;p&gt;There's another thing to keep in mind regarding this number. It should be transparent, easy to compile, and visible to all.&lt;/p&gt;

&lt;p&gt;To give you an example, if the change you are driving is the addition of e2e tests, then maybe your metric can be the number of P0 incidents every month. And your goal is to reduce that number. You can also count how many times e2e tests have prevented a bug from going into production and saved your butts. You could compile this metric at the end of every month and show how e2e tests are helping prevent money loss incidents.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tracking adoption
&lt;/h3&gt;

&lt;p&gt;Another thing to do is report on the progress of your change. It will keep you motivated to achieve your goals. Similar to the success metric, you also need to keep track of the adoption metric.&lt;/p&gt;

&lt;p&gt;For tests, it could be the test coverage of the codebase. If you are migrating to Typescript, it could be the percentage of the files in the codebase that are in Typescript.&lt;/p&gt;

&lt;p&gt;Similar to having transparency in success metrics, it helps to be transparent here as well. It keeps you responsible for delivering on your promises and tells leadership that effort is being put into this migration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Gaining adoption
&lt;/h3&gt;

&lt;p&gt;Now then, coming to the change itself - &lt;strong&gt;you won't be able to drive it alone&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VjDEns3K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bntqd1l66qptt0k78km5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VjDEns3K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bntqd1l66qptt0k78km5.png" alt="motivation vs alignment graph for types of engineers" width="880" height="699"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will need help and contributions from your peers too. Since we have already spoken about managers and leadership, let's talk about your peers. There are different kinds of engineers with different beliefs. From the perspective of driving change, I'll categorise them into the following categories:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;The Skeptics&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;They will question the change you are driving. They are usually experienced engineers who have been burned in the past by incomplete migrations or flimsy tooling that someone else, just like you, built. The way to align them is to first, know your problem, have an approach outlined, and be confident. With some work, a skeptic will turn into one of the other categories&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;The Pilots&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These will be the first contributors to the change. Your focus must be on motivating these people to start contributing to the change. They will provide valuable feedback that will help you&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;The Mentors&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;They will not contribute directly to your project. However, they will help align other engineers, managers, and leadership to your efforts. To give you an example - they will help engineers get allocated sufficient bandwidth to work on the project&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;The Mid Stage Adopters&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Initially, they might or might not know that a change is being driven. They will come into the picture when the project has approached a more stable stage.&lt;/p&gt;

&lt;p&gt;Remember that they are the vast majority. So once you have gained a few early adopters, you can focus on this group. You will need to educate and evangelise them in order to persuade them.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;The Late Adopters&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Like the name suggests, they understand your change but do not want to exert effort towards it. The reason might be that they either don't believe in it or they might be time-crunched. I suggest not spending too much time on this group since they will be a minority&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; There will be overlaps between these groups. They are not strict categories&lt;/p&gt;

&lt;h2&gt;
  
  
  Experiences may differ
&lt;/h2&gt;

&lt;p&gt;Every company is different. So I'm excited to hear about your experiences. Have you driven a change at your organisation? How did you align the stakeholders? What challenges did you face? Let me know on my &lt;a href="https://twitter.com/burhanday"&gt;Twitter&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Did you like what you read? I try to publish two articles a month on this blog. You can subscribe for updates on my site &lt;a href="https://burhanuday.com"&gt;https://burhanuday.com&lt;/a&gt;&lt;/p&gt;




&lt;h4&gt;
  
  
  Credits and attribution
&lt;/h4&gt;

&lt;p&gt;Cover image - &lt;a href="https://www.freepik.com/vectors/industrial-automation"&gt;Industrial automation vector created by pch.vector - www.freepik.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>career</category>
    </item>
    <item>
      <title>Why is there hype around Module Federation</title>
      <dc:creator>Burhanuddin Udaipurwala</dc:creator>
      <pubDate>Fri, 24 Jun 2022 04:35:26 +0000</pubDate>
      <link>https://dev.to/burhanuday/why-is-there-hype-around-module-federation-1cc4</link>
      <guid>https://dev.to/burhanuday/why-is-there-hype-around-module-federation-1cc4</guid>
      <description>&lt;p&gt;I joined Razorpay last year on the frontend team building &lt;a href="https://razorpay.com/x/"&gt;RazorpayX&lt;/a&gt;, the neo baking solution for startups and SMEs. Our front-end is very much a complex dashboard with multiple products, each handled by a different team. With multiple frontend devs working on the codebase, I have witnessed the codebase grow at an exponential rate.&lt;/p&gt;

&lt;p&gt;It took longer to start the development server, tests ran for longer, building was slower and CI jobs ran for over an hour. So I asked the question, does every company face this? See their codebase turn into a monolith, with unwanted coupling between apps. And the answer seems to be a yes.&lt;/p&gt;

&lt;p&gt;I want to ship the product faster. I don't want a text change to take 3 hours for deployment. I want deployments to be scoped to individual apps. But I also want to be able to share a common store between apps and share UI code easily. I dont want complex configurations and architectures.&lt;/p&gt;

&lt;p&gt;So I started reading about the possible solutions to this problem. I found out about the following methods:&lt;/p&gt;

&lt;h2&gt;
  
  
  NPM Packages flow
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pE0Rad4f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qpp58gb09syol7q9blzc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pE0Rad4f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qpp58gb09syol7q9blzc.png" alt="A figure showing NPM package flow" width="880" height="520"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each micro app would be an NPM package published to the company package registry. The host app would be a shell that would have all of these packages listed as dependencies. The package versions would only increase by a minor (ie 0.0.x) so that NPM would always resolve to the latest version to download&lt;/p&gt;

&lt;p&gt;To update an app, you would have to only publish a newer version for that particular app. Which is something that can be automated on a merge to master and can be done multiple times a day&lt;/p&gt;

&lt;p&gt;To deploy a newer version of the dashboard, you'd have to run the pipeline for shell again. This can be done as many times as a new deployment was required.&lt;/p&gt;

&lt;p&gt;There was still a problem here, I'd have to migrate all library code (or common UI code) into its own package to be shared between apps. I would also have to manually depulicate these dependencies myself for each package. This would be a major migration effort for a pretty sizeable codebase. Hard pass.&lt;/p&gt;

&lt;p&gt;There was still another problem here. When I wanted to deploy a newer version for an app, I would have to trigger two deployments sequentially. First, publish the app itself. Then remember to also rerun the shell pipeline so that the latest app goes into production. All that effort would not be worth it for a minor improvement&lt;/p&gt;

&lt;h2&gt;
  
  
  Microfrontend frameworks
&lt;/h2&gt;

&lt;p&gt;Then I started looking at the existing microfrontend frameworks. I went through the docs of the popular ones - SingleSPA, Open Components, and Mosaic.&lt;/p&gt;

&lt;p&gt;In each of them, I found that it required a lot of configuration to set them up. Configuration would be required to handle routing, state sharing, code sharing, dependency deduplication.&lt;/p&gt;

&lt;p&gt;Each project would have to be configured manually to deduplicate the dependencies between them. Each solution had its tradeoffs that I was either not comfortable making, or couldn't make due to the architecture of the existing dashboard that we have.&lt;/p&gt;

&lt;h2&gt;
  
  
  Module Federation
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2RZHSUKq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x3sxuja7wskxsvhstxms.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2RZHSUKq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x3sxuja7wskxsvhstxms.png" alt="A figure showing module federation architecture" width="880" height="470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The new kid on the block. Module federation in the words of its creator:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Webpack 5 Module Federation aims to solve the sharing of modules in a distributed system, by shipping those critical shared pieces as macro or as micro as you would like. It does this by pulling them out of build pipeline and out of your apps.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Translated to simple words:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Module federation allows you to use code from other projects in your project, at runtime&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It allows you to share code at runtime, as opposed to build time. This is the major difference between Module Federation and mono-repos. But then, Module Federation is not a microfrontend framework, it is simply a tool that allows you to share code at runtime.&lt;/p&gt;

&lt;p&gt;The Module Federation plugin for Webpack 5 simplifies a lot of configuration that would otherwise be required to be done for the above-mentioned solutions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It simplifies dependency deduplication by allowing you to pass a list of dependencies via the &lt;code&gt;shared&lt;/code&gt; parameter.&lt;/li&gt;
&lt;li&gt;Exposing code and using it is simple, it looks something like this
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Remote App&lt;/span&gt;
&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&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="s2"&gt;microapp1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;microapp1.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="s2"&gt;./index&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/index&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="c1"&gt;// Host App&lt;/span&gt;
&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&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="s2"&gt;host&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;host.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;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;microapp1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;microapp1@http://localhost:3001/microapp1.remoteEntry.js&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="c1"&gt;// Usage in host&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Remote&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;microapp1&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 so, code sharing is pretty simple. Does not require you to make any changes to how your codebase is structured&lt;/p&gt;

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

&lt;p&gt;So to conclude, I see the value proposition of Module Federation. It fits right into the build toolchain since its a part of Webpack. The configuration required is little and the learning curve is non existent. It does not seem to require any drastic changes to the codebase. If you are interested in trying out Module Federation hands-on, I have a demo available here - &lt;a href="https://github.com/burhanuday/module-federation-with-webpack5"&gt;Module Federation with Webpack5&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Did you like what you read? I try to publish two articles a month on this blog. You can subscribe for updates at &lt;a href="https://burhanuday.com"&gt;https://burhanuday.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webpack</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Don't over-engineer it</title>
      <dc:creator>Burhanuddin Udaipurwala</dc:creator>
      <pubDate>Wed, 26 Jan 2022 05:08:26 +0000</pubDate>
      <link>https://dev.to/burhanuday/dont-over-engineer-it-1013</link>
      <guid>https://dev.to/burhanuday/dont-over-engineer-it-1013</guid>
      <description>&lt;p&gt;Of course you should write your new side project with the newest fad in trend.&lt;/p&gt;

&lt;p&gt;Of course it must be server-side rendered with the smallest JS bundle and the most optimised user interactions.&lt;/p&gt;

&lt;p&gt;Of course it has to be served from the Edge in under 120ms.&lt;/p&gt;

&lt;p&gt;Of course it's fine if it takes 6 more months to build.&lt;/p&gt;

&lt;p&gt;Of course it's fine if the competition takes the lead.&lt;/p&gt;

&lt;p&gt;Your site is the best because you are using the best new framework recommended by everyone on YouTube.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No! you don't need to do the above because no one is going to use your shitty product anyway.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To nobody's surprise - &lt;a href="https://davemart.in/2018/11/23/resistance/"&gt;10xer discovers that side projects move slowly when you rewrite them in a new JavaScript framework every 3 months&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You might think I'm being mean and I might be. However, this is something that every engineer needs to hear from time to time. You are spending too much time thinking of optimisation when you don't even have a product-market fit.&lt;/p&gt;

&lt;p&gt;Does it really matter if your habit tracker runs at 120 FPS if nobody uses it?&lt;/p&gt;

&lt;p&gt;In the early days of your product, performance shouldn't be the top of your priorities. Finding a market fit and a user base should be. That will only happen if you build rapidly and are agile enough to move according to customer demands. Products that fail to understand this, just fail at everything.&lt;/p&gt;

&lt;p&gt;Recently a friend asked me if they should use a combination of React and React Native for their new business idea. I asked them if they had a team of 3 developers working for them. On being told "no", I advised them to just use Capacitor to bundle their web app into an Android and iOS app.&lt;/p&gt;

&lt;p&gt;I expected to hear "Isn't that bad for user experience?" (which I did). Can most users tell the difference between native and non-native apps? No, not really. Before you tell me that hybrid apps are UX nightmares - &lt;a href="https://eliteionic.com/tutorials/ionic-framework-is-fast-but-your-code-might-not-be/"&gt;There is no bad framework, only badly written code&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When building a business, start with something you already know. For tools of convenience, you don't need the best framework in the world. JUST START&lt;/p&gt;

&lt;p&gt;You must prioritise your business requirements over fun-to-do things in the initial phases of your product for the following reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you are going to fail, you'd rather fail fast. Waste less time learning things while building your product. For learning, build smaller side projects with no intention of monetising them&lt;/li&gt;
&lt;li&gt;If you work with what you are already comfortable with, you will build much faster than someone who is still learning&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Last weekend, I met a friend who is working on a proximity-based chat application as a side project. They told me they were using MongoDB as the database with Firebase Cloud Functions (FCF). I asked them the reasoning for not using Firestore (Firebase's NoSQL datastore) since it's much easier to configure and use. They told me it was because MongoDB is more performant than Firestore at geolocation queries. A week later, they came back to me and said they were moving to Firestore because it was easier to use.&lt;/p&gt;

&lt;p&gt;Again, emphasises the point that you should start with whatever you know. When the demand comes, move quickly&lt;/p&gt;

&lt;p&gt;How many of your side projects did you start with a new framework but never finished building. Was it because you were too busy learning that new framework when you should have been actually been focused on building your project.&lt;/p&gt;




&lt;p&gt;I am working on a small utility for readers. If you are someone who reads a lot of blog articles or newsletters, hit me up at &lt;a href="https://twitter.com/burhanuday"&gt;@burhanuday&lt;/a&gt; or email me at &lt;a href="//mailto:udaipurwalaburhanuddin@gmail.com"&gt;udaipurwalaburhanuddin@gmail.com&lt;/a&gt;. I'd love to have a chat!&lt;/p&gt;




&lt;p&gt;To get updated when I write my next article, subscribe to my newsletter at &lt;a href="https://burhanuday.com"&gt;burhanuday.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How not to let social media and your phone destroy your life</title>
      <dc:creator>Burhanuddin Udaipurwala</dc:creator>
      <pubDate>Sun, 16 Jan 2022 14:20:45 +0000</pubDate>
      <link>https://dev.to/burhanuday/how-not-to-let-social-media-and-your-phone-destroy-your-life-3hb6</link>
      <guid>https://dev.to/burhanuday/how-not-to-let-social-media-and-your-phone-destroy-your-life-3hb6</guid>
      <description>&lt;p&gt;Phone addiction is a serious problem across all age ranges. Recently, a friend told me that they went to bed at midnight but were up till 3 AM scrolling Instagram. They said they lost track of time.&lt;/p&gt;

&lt;p&gt;I suffered from the same syndrome and would constantly have the urge to check my phone every few minutes. Even in the middle of work. To the point that my phone and social media apps were distracting me from working&lt;/p&gt;

&lt;p&gt;My average phone usage time would be close to 6 hours a day. I was in a bad mental state and my phone (read social media) addiction was making it worse. I wanted to reduce my usage of Instagram, Twitter, Linkedin, Discord, and Reddit.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to use your phone without being miserable
&lt;/h2&gt;

&lt;p&gt;There are two ways to cure your phone addiction. The first is to take the band-aid-like approach and pull it off in one go. Most people are likely to give up on this. I still recommend that you start with the "Quick and painful" approach and only use the milder method when it doesn't work for you. Regardless of the approach you take, I still think that these techniques are likely to help you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick and painful
&lt;/h2&gt;

&lt;p&gt;The quick and painful method is to uninstall all social media apps from your phone and only open them from the browser&lt;/p&gt;

&lt;h3&gt;
  
  
  Use social media only from the browser
&lt;/h3&gt;

&lt;p&gt;Social media apps like Twitter and Instagram have never-ending feeds and timelines. We get addicted to them because they give us a small dopamine rush every time we scroll the feed.&lt;/p&gt;

&lt;p&gt;I uninstalled social media apps from my phone. I logged into all these apps from my desktop computer. It helped because firstly, it took more effort to go to the browser and type in the URL. And secondly, I could use &lt;a href="https://chrome.google.com/webstore/detail/leechblock-ng/blaaajhemilngeeffpbfkdjjoefldkok"&gt;LeechBlock&lt;/a&gt; to restrict myself from opening social media sites during my work hours&lt;/p&gt;

&lt;p&gt;You can also experiment by logging into these apps from your phone's browser. Since those web apps are not optimised for mobile devices they give you an inferior experience. If you hate the scrolling experience, you wouldn't want to scroll&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--c8DvrmZ_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/la89mg4ls1ov7u12drun.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--c8DvrmZ_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/la89mg4ls1ov7u12drun.jpg" alt="taps head meme" width="700" height="700"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
    If you hate the scrolling experience, you wouldn't want to scroll&lt;br&gt;
 
 &lt;/p&gt;

&lt;p&gt;This is how I got rid of using Instagram because the web version sucks. Try watching a story or two on Instagram web, you don't want to. It is slightly more difficult to uninstall system apps. The method demonstrated by XDA &lt;a href="https://www.xda-developers.com/uninstall-carrier-oem-bloatware-without-root-access/"&gt;here&lt;/a&gt; requires caution. As long as you don't uninstall random things, your phone should be fine. This is how I got rid of YouTube and I still don't have it installed on my phone.&lt;/p&gt;

&lt;h3&gt;
  
  
  Put your phone on silent mode permanently
&lt;/h3&gt;

&lt;p&gt;Sometimes I would get the feeling that my phone was vibrating even when it wasn't. I kid you not, this is a real illness that has been extensively documented and is a sign of mobile phone addiction.&lt;/p&gt;

&lt;p&gt;The easy way out is to put your phone on silent mode and forget. Then when feeling like it is vibrating, you tell yourself that it isn't because it can't be.&lt;/p&gt;

&lt;p&gt;Another way is to put your phone in silent mode and to leave it in a different room. Putting the phone out of your sight will reduce the urge to pick it up again and again because you don't see it that often&lt;/p&gt;

&lt;h2&gt;
  
  
  Mild and slower
&lt;/h2&gt;

&lt;p&gt;A lot of these solutions revolve around using the app &lt;a href="https://play.google.com/store/apps/details?id=com.google.android.apps.wellbeing&amp;amp;hl=en_US&amp;amp;gl=US"&gt;Digital Wellbeing (Play Store)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If it's not available for you on the Play Store, you can side-load the APK from &lt;a href="https://apkpure.com/digital-wellbeing/com.google.android.apps.wellbeing"&gt;APK Pure&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I recommend also using &lt;a href="https://play.google.com/store/apps/details?id=com.teslacoilsw.launcher"&gt;Nova Launcher&lt;/a&gt;. I like it because it is functional, customisable and doesn't do too much. You can also use &lt;a href="https://play.google.com/store/apps/details?id=ch.deletescape.lawnchair.plah"&gt;Lawnchair Launcher&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keep an empty home screen - out of sight, out of mind
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CjX9_x9F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fz1idayh6srt153w1qly.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CjX9_x9F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fz1idayh6srt153w1qly.jpeg" alt="homescreen" width="738" height="1600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The problem was that whenever I turned the screen on, I saw shortcuts to those social media apps on my home screen. I would open them out of muscle memory. I would then forget why I picked my phone up and started scrolling whatever feed I had in front of me. The easy solution was to remove all home screen shortcuts. The only way to open those apps was through the app drawer. That would require extra effort which increased my resistance to opening the app again and again.&lt;/p&gt;

&lt;p&gt;When I started, I built a special launcher for myself that would be boring yet functional. &lt;a href="https://play.google.com/store/apps/details?id=com.appallure.miny"&gt;miny&lt;/a&gt; is still available on the Play Store but I don't use it anymore. You might want to give it a try. I haven't worked on it in a while so expect plenty of bugs&lt;/p&gt;

&lt;h3&gt;
  
  
  Turn off all unnecessary notifications
&lt;/h3&gt;

&lt;p&gt;If you don't want to give up on the installed apps that quickly, another way is to disable notifications. You can go to Instagram's and Twitter's settings to disable alerts. Disable as many as you'd like. If you get fewer notifications, you are less likely to open those apps. I have notifications enabled only for Direct Messages. I have disabled all other notifications&lt;/p&gt;

&lt;p&gt;You can also go to Digital Wellbeing and see which apps send you the most amount of notifications every day. There are also apps available that aggregate notifications for a few hours and send them all at once at times you specify.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QkRjMjz---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i0mm12o9p4x65jctb2sn.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QkRjMjz---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i0mm12o9p4x65jctb2sn.jpeg" alt="notifications counter according to apps" width="738" height="1600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Digital Wellbeing also has a focus mode that blocks notifications for specific apps. It gives you the choice to allow important apps to still send you important alerts. I like this feature a lot and use it while I am working. It prevents me from getting distracted&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TFEnMUmZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2t8fkc97cn9bysjxby0j.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TFEnMUmZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2t8fkc97cn9bysjxby0j.jpeg" alt="digital wellbeing focus mode" width="738" height="1600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also use Android's DND mode and switch off all notifications. You can keep notifications for calls on so if there's anything urgent, someone is likely to call you&lt;/p&gt;

&lt;h3&gt;
  
  
  Use direct shortcuts to features instead of navigating
&lt;/h3&gt;

&lt;p&gt;This is again if you haven't uninstalled social media apps from your phone. The launcher I use, Nova Launcher, has this cool feature that allows me to go to different parts of the app directly. This saves me the effort of navigating through unnecessary parts of the apps and going to where I want directly. For instance, if I want to message someone on Instagram, I can directly go to the chats screen rather than opening the app and getting distracted by the feed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Go8-m1zv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4pbt6rbl96lkdqr5tp2s.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Go8-m1zv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4pbt6rbl96lkdqr5tp2s.jpeg" alt="direct shortcuts from homescreen" width="738" height="1600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I also use a Nova launcher extension called &lt;a href="https://play.google.com/store/apps/details?id=ninja.sesame.app.edge&amp;amp;hl=en_IN&amp;amp;gl=US"&gt;Sesame Shortcuts&lt;/a&gt; (it's a paid app with a free trial) that takes this idea to the extreme and provides a ton of other features. You probably don't need it but it's pretty cool nonetheless&lt;/p&gt;

&lt;h3&gt;
  
  
  Limit usage with digital wellbeing
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BY_spUId--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9fb7pduvjskjfcb4e8r0.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BY_spUId--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9fb7pduvjskjfcb4e8r0.jpeg" alt="an empty phone homescreen" width="738" height="1600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I used Digital Wellbeing to set timers for social media apps. Once the assigned time gets depleted, Digital Wellbeing will restrict your access to those apps. They will appear greyed out and you won't be able to open them. It will also hide the notifications from those apps to prevent any further distraction.&lt;/p&gt;

&lt;p&gt;You can start by allocating larger amounts of time for each app and then reducing the time at the start of the week until you have reached your desired usage.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it has helped me
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--14Y5iiyF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/47115mfkkx6vi5yr9ay0.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--14Y5iiyF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/47115mfkkx6vi5yr9ay0.jpeg" alt="direct shortcuts from homescreen" width="738" height="1600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I used to be glued to my phone for about 5-6 hours a day. I have now brought it to somewhere close to 1.5 hours. That is if you ignore the time spent calling. It's erroneously reported since that's the amount of time I spent talking to people outside of social media.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I don't believe that you should completely go off of social media. I do believe that you should restrict the time you allocate to it.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Connect with me
&lt;/h2&gt;

&lt;p&gt;If you'd like to discuss, DM me on &lt;a href="https://twitter.com/burhanuday"&gt;Twitter&lt;/a&gt;. For updates, subscribe to my newsletter at &lt;a href="https://burhanuday.com"&gt;burhanuday.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>mentalhealth</category>
    </item>
    <item>
      <title>Get the most out of your Root Cause Analysis meetings</title>
      <dc:creator>Burhanuddin Udaipurwala</dc:creator>
      <pubDate>Tue, 21 Dec 2021 14:36:39 +0000</pubDate>
      <link>https://dev.to/burhanuday/get-the-most-out-of-your-root-cause-analysis-meetings-4b6j</link>
      <guid>https://dev.to/burhanuday/get-the-most-out-of-your-root-cause-analysis-meetings-4b6j</guid>
      <description>&lt;p&gt;Whenever something breaks in production, an INCIDENT ticket gets created on Jira. An Engineer/ Developer will figure out what went wrong and attach a document called RCA document to the ticket. This article talks about the process of what happens after the problem is figured out and how you can encourage other developers to learn from mistakes made in the past.&lt;/p&gt;

&lt;p&gt;At RazorpayX, we have a scheduled RCA meet every Thursday. We discuss issues that occurred in the past week and what we learned from them. The environment is of curiosity and the theme is to understand and learn.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;RCA meetings are also called Postmortems at some organisations. They refer to the same thing&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;An RCA meet or Root Cause Analysis meet is a formal meeting where you discuss why and how a particular problem occurred. It is not specific to the tech industry and this practice originated in the medical industry to analyse the cause of patient deaths. However, it is also useful in debugging and educating developers about software related problems.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/9M5jK4GXmD5o1irGrF/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/9M5jK4GXmD5o1irGrF/giphy.gif" alt='a dog sitting in a room on fire. dog says "this is fine" and sips coffee' width="436" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The goal of this exercise
&lt;/h2&gt;

&lt;p&gt;The goal of this exercise is to understand all contributing factors and causes, document the incident for future reference and also create action items to reduce the likelihood of this problem occurring again. This exercise can also be performed async but from what I have seen, most folks prefer scheduling a meeting to discuss the document.&lt;/p&gt;

&lt;p&gt;It could be a frontend bug, backend failure or even a DevOps issue. The goal is to inform and educate other stakeholders about what went wrong and analyse the cause of the problem. These meetings are not to assign blame towards an engineer or interrogate the team on why a particular system failed. If this is what is happening at your RCA meets, you need to restructure how you perform them.&lt;/p&gt;

&lt;p&gt;An engineering leader organises and leads the meeting. The meeting should be conducted with a clear goal and theme in mind and the participants should be pre-informed about the topic. Usually, an RCA document is created to be shared across stakeholders to read up before joining the RCA meet. If the problem has affected parties outside your organisation, a separate external RCA may also be created with relevant information to be sent to the third party.&lt;/p&gt;

&lt;h2&gt;
  
  
  The RCA Document
&lt;/h2&gt;

&lt;p&gt;The RCA document is a story where your bug is the antagonist. It explains their rise to power as well as their eventual downfall and the changes they brought about.&lt;/p&gt;

&lt;p&gt;There are a few things that an RCA document &lt;strong&gt;must&lt;/strong&gt; contain:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Problem Description&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is a no brainer. Every RCA document should succinctly describe the problem at the top of the document and give a brief overview&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Timeline of events&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It should contain all the details about when the issue was discovered, by whom and how was it reported. It should also contain the first response time to the issue as well as every escalation event. If the issue has been fixed, it should contain the timeline events about the fix as well.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. The 5 WHYs&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The 5 WHYs are a great way to explain the issue. It is an interrogative technique where each question forms the basis for the next one. A very simple example would be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why does the Earth have seasons?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ans) because the Earth revolves around the Sun&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why does the Earth revolve around the Sun?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ans) Because of the Sun's gravitational pull&lt;/p&gt;

&lt;p&gt;This is a great tool because it helps you get closer to the root of the problem&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Action Items&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Hurray! you identified the problem... but now what? Every RCA document should contain action items about what is/was done to resolve the issue. These items help the broader audience understand how the problem was mitigated and might help them in the future.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Impact&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;An issue can impact one customer or thousands of customers. It is important to understand the scale at which the problem has occurred and the impact that it has created. This also helps estimate the severity of the problem&lt;/p&gt;

&lt;h2&gt;
  
  
  The meeting
&lt;/h2&gt;

&lt;p&gt;It is a good idea to limit a meeting by time. At RazorpayX, our RCA meets are time-limited to one hour. Sometimes we discuss more than one issue depending on how complex the problem is. This helps you keep discussions on point.&lt;/p&gt;

&lt;p&gt;Ask the participants to pre-read the document before joining the meeting. This will help save time which would have instead gone into explaining the problem during the meeting.&lt;/p&gt;

&lt;p&gt;A team member from the team performing the postmortem of the issue takes the participants through the RCA document. At the start of the meeting, describe the problem and clarify any doubts about the problem itself. After which, you get into the probable causes, discuss the timelines and speak about the action items. Here, participants may give suggestions about the action items and may ask for more information about the issue.&lt;/p&gt;

&lt;p&gt;You should also leave time in the end for questions from the participants of the meeting. Focus on the pointers above in the meeting as you go through the document with the participants.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/3o6ZtchKknm848aLHG/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/3o6ZtchKknm848aLHG/giphy.gif" alt="captain hindsight from South Park being obvious" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What you shouldn't do in the meeting
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Place blame upon someone: as I stated before, these meetings aren't for blaming other people. They are there to offer learnings and help stakeholders understand the problem&lt;/li&gt;
&lt;li&gt;Get sidetracked into side issues: focus on the issue at hand and don't rant about an irrelevant issue&lt;/li&gt;
&lt;li&gt;Become a victim of bias. In hindsight, everything is obvious&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;You will see that in these meetings that resolutions were "common sense" and the problems were all "obvious oversights". You will also encounter many flawed assumptions as well as learn about different systems and how they interact with each other. See these meetings as learning opportunities at your company rather than a way to shift the problem onto someone else. Engineers should not be penalised because, frankly, bugs are expected even with software having years of maturity&lt;/p&gt;

&lt;p&gt;At the end of an RCA meet, you should have the following points clarified:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;How did the issue occur&lt;/li&gt;
&lt;li&gt;How was the issue resolved&lt;/li&gt;
&lt;li&gt;What was the turnaround time for resolution&lt;/li&gt;
&lt;li&gt;What were the process gaps that led to the issue&lt;/li&gt;
&lt;li&gt;Were there any architectural mistakes that led to it&lt;/li&gt;
&lt;li&gt;How can similar problems be mitigated in the future&lt;/li&gt;
&lt;li&gt;What are some suggested changes that could be made to reduce issues like these&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>career</category>
    </item>
    <item>
      <title>7 lessons from a fresher after 3 months at Razorpay</title>
      <dc:creator>Burhanuddin Udaipurwala</dc:creator>
      <pubDate>Tue, 19 Oct 2021 15:44:49 +0000</pubDate>
      <link>https://dev.to/burhanuday/7-lessons-from-a-fresher-after-3-months-at-razorpay-39l</link>
      <guid>https://dev.to/burhanuday/7-lessons-from-a-fresher-after-3-months-at-razorpay-39l</guid>
      <description>&lt;p&gt;&lt;em&gt;Time flies&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I started programming about 6 years ago when I built my first shitty Android app. It was a phone directory of sorts, and I had no idea what I was doing. Fast-forward to 6 years later at Razorpay and I still felt like I had no idea what I was doing&lt;/p&gt;

&lt;p&gt;3 months have passed since I joined Razorpay in July and I feel like I am a full 3 months wiser. Here's some stuff that I have picked up in the past 3 months&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disclaimer&lt;/strong&gt;: There isn't going to be any code whatsoever in this post.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Don't work more, work extra:&lt;/strong&gt; What's the difference? Let's say you have a project that if you worked 7 hours on every day, you'd complete in a month. If you instead worked on it for 8 hours a day, you would complete it 4 days before the deadline. The only person you would be making happy is your product manager. If you instead spent that 1 hour trying to improve your codebase, or automating something or reducing tech debt or even building something that makes life easier, you'd make a team full of developers happy. You'd be creating a much greater impact&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Stick to your deadlines:&lt;/strong&gt; The thing about working at Razorpay is that I decide my own deadlines. The problem with that is that if my timelines are not accurate or are not running on time, everyone else who depended on my tasks being complete to continue their work will also be delayed. This snowballs into the whole project being delayed. Estimation is a skill that comes to you with experience and thought. Only promise what you can deliver. Take into consideration your sick days, holidays, and vacations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Talk to your colleagues:&lt;/strong&gt; This is not so obvious. When I started working, my conversation with my colleagues was limited to work. Your colleagues, especially the ones with more experience, have a lot to share. You will only get their wisdom when you talk to them informally. This is especially difficult due to remote work so it will take effort on your side to form a relationship&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Buy a good chair:&lt;/strong&gt; You will be sitting on a chair for the greater part of your day. Save your back and buy a comfortable chair that has good lower back support. I don't have any recommendations to give but buy something comfortable. It doesn't have to cost 15k, you can get one for around 1.5k that will be just as comfortable. Also, stand up and stretch after every 45mins of work. Backache will be a real problem even for someone in their 20s&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Don't work on the weekends:&lt;/strong&gt; Don't fall for the hustle culture crap. Weekends exist for a reason. They exist because they allow you to rest and take time off of work. Rest rejuvenates your mind and body and allows you to be more productive in the coming week.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Learn outside of work:&lt;/strong&gt; To progress in your career, you will have to do more than is expected of you. You can increase your technical skill by learning new stuff on your own time. Build something with what you have learnt. Take out 30 mins every day in the morning, before starting work to read up about something. What I generally do is make a reading list in a To-Do app and try to read 2 articles every day.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Have a goal in mind:&lt;/strong&gt; You will not progress unless you have a realistic goal in your mind. "Where do I see myself in the next appraisal cycle?" It sounds cringy but appraisals are a record of your performance throughout the year. If you have nothing impactful to show, you won't go far. This point ties well with point 1. Your goal does not have to be limited to the next appraisal cycle either. Ask yourself "do I want to code for the next 20 years?" "Do I want to manage people instead and become an Engineering Manager?" "Do I instead want to talk to customers and become a Product Manager? This choice is difficult but once you think about it and have clarity, it will help you in making decisions.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There's a lot more I'd like to add to this post, and maybe I will. Subscribe to my newsletter at &lt;a href="https://burhanuday.com"&gt;burhanuday.com&lt;/a&gt;,or follow me on DEV and you will be notified when I post my next article. If you want to talk to me, come over at my twitter &lt;a href="https://twitter.com/burhanuday"&gt;@burhanuday&lt;/a&gt;&lt;/p&gt;

</description>
      <category>career</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Bundle a React library with Parcel</title>
      <dc:creator>Burhanuddin Udaipurwala</dc:creator>
      <pubDate>Sun, 17 Oct 2021 14:29:57 +0000</pubDate>
      <link>https://dev.to/burhanuday/bundle-a-react-library-with-parcel-71i</link>
      <guid>https://dev.to/burhanuday/bundle-a-react-library-with-parcel-71i</guid>
      <description>&lt;p&gt;Parcel is a bundler for Javascript and Typescript projects. They recently released version 2 of the project, and it comes with a lot of performance and usage improvements. It automatically installs required dependencies without having to do any complex config or setup. It really lives upto its name when it says it's "The zero configuration build tool".&lt;/p&gt;

&lt;h2&gt;
  
  
  Initialise your project
&lt;/h2&gt;

&lt;p&gt;Create a new project with either &lt;code&gt;npm&lt;/code&gt; or &lt;code&gt;yarn&lt;/code&gt;. For this guide, I will be using &lt;code&gt;yarn&lt;/code&gt;&lt;br&gt;
To create a new project&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then follow through the guide to create your &lt;code&gt;package.json&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Since this is a library, you need to add the following lines to your &lt;code&gt;package.json&lt;/code&gt; file so that the consumers of your library can automatically figure out the build paths&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;source&lt;/code&gt; tells Parcel the entry point of your project&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;main&lt;/code&gt; will be the path for generating your output JS bundle&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;module&lt;/code&gt; path creates an ES Module target
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"src/index.js"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"main"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dist/main.js"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"module"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dist/module.js"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;if you are using Typescript you can change the &lt;code&gt;source&lt;/code&gt; property to &lt;code&gt;src/index.ts&lt;/code&gt; instead and add &lt;code&gt;"types": "dist/types.d.ts"&lt;/code&gt; to tell Parcel where to spit out types for your library&lt;/p&gt;

&lt;p&gt;To generate a &lt;code&gt;tsconfig.json&lt;/code&gt; file for your project, run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx tsconfig.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and select React from the menu. That will generate the appropriate config.&lt;/p&gt;

&lt;p&gt;After that, add the following scripts to your &lt;code&gt;package.json&lt;/code&gt; file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"parcel watch"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"parcel build"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will use these scripts to develop and build your project later&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing dependencies
&lt;/h2&gt;

&lt;p&gt;We need to install Parcel, React and React DOM as dev dependencies&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add &lt;span class="nt"&gt;-D&lt;/span&gt; react react-dom parcel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also add React as a peer dependency in your project. Add to &lt;code&gt;package.json&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"peerDependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"react"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^18.0.0"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tells library consumers what version of React your library supports&lt;/p&gt;

&lt;p&gt;Optionally, if you are using Typescript, you also need to install Typescript&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add &lt;span class="nt"&gt;-D&lt;/span&gt; typescript @types/react @types/react-dom
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating a component
&lt;/h2&gt;

&lt;p&gt;To demonstrate the bundling process. I created two files in the &lt;code&gt;src&lt;/code&gt; directory. Create a directory called &lt;code&gt;src&lt;/code&gt; and add the following files&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Button.tsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;React&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;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;IButton&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;HTMLProps&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HTMLButtonElement&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;Button&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FC&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;IButton&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onClick&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onClick&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;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;index.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Button&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;./Button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your directory structure should now look like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src
    -&amp;gt; index.ts
    -&amp;gt; Button.tsx
package.json
yarn.lock
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Bundling
&lt;/h2&gt;

&lt;p&gt;To build your project, run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will generate the output inside the &lt;code&gt;dist&lt;/code&gt; directory&lt;/p&gt;

&lt;p&gt;You can run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to start a development server and Parcel will listen to changes in your files&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing note
&lt;/h2&gt;

&lt;p&gt;I think Parcel v2 is a fantastic bundler and simplifies project configuration. It automatically detects the framework and language you are using and will install appropriate helper packages&lt;/p&gt;

&lt;p&gt;Checkout the Parcel website (Its pretty cool!) - &lt;a href="https://parceljs.org/"&gt;Parcel&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can follow me on DEV or subscribe to my newsletter at &lt;a href="https://www.burhanuday.com/"&gt;https://www.burhanuday.com/&lt;/a&gt; to get notified when I publish my next article&lt;/p&gt;

</description>
      <category>parcel</category>
      <category>react</category>
    </item>
    <item>
      <title>Build your own styled-components</title>
      <dc:creator>Burhanuddin Udaipurwala</dc:creator>
      <pubDate>Wed, 04 Aug 2021 14:10:54 +0000</pubDate>
      <link>https://dev.to/burhanuday/build-your-own-styled-components-11pg</link>
      <guid>https://dev.to/burhanuday/build-your-own-styled-components-11pg</guid>
      <description>&lt;p&gt;styled-components is a CSS-in-JS library that uses the tagged template syntax in JavaScript and allows you to write actual CSS inside your React components as opposed to the object syntax. If you haven't used styled-components before, the below example from the official documentation should give you a brief idea about what styled-component is:&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;Title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="s2"&gt;`
  font-size: 1.5em;
  text-align: center;
  color: palevioletred;
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why is styled-components important
&lt;/h2&gt;

&lt;p&gt;styled-components does a lot more than just enabling you to write CSS inside your React components. Here are some other advantages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Automatic Vendor Prefixing&lt;/strong&gt;: Since some CSS features need to be prefixed for different vendors like &lt;code&gt;-moz&lt;/code&gt; or &lt;code&gt;-webkit&lt;/code&gt;, styled components handles this for you automatically, so you write styles without having to worry about browser compatibility&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Duplicate class names&lt;/strong&gt;: In large projects, you may run into clashing class names. styled components prevents this by assigning random hashes as part of your class names. So your class names remain readable yet random and prevent clashes at the same time&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simplified dynamic styling&lt;/strong&gt;: The styled-components syntax makes it easier to apply dynamic styles without having to change the class name of components using JavaScript.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There's a lot more that I skipped for brevity's sake. Read more &lt;a href="https://styled-components.com/docs/basics#motivation"&gt;here.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Haven't used styled-components before?
&lt;/h2&gt;

&lt;p&gt;styled components also allow you to pass the same props as you would pass to normal HTML tags.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="s2"&gt;`
  font-size: 1.5em;
  text-align: center;
  color: palevioletred;
`&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;Wrapper&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;section&lt;/span&gt;&lt;span class="s2"&gt;`
  padding: 4em;
  background: papayawhip;
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Wrapper&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      Hello World!
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Wrapper&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above code renders the following&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MIQip1mU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/burhanuday/images/master/2021/07/Screenshot%2520from%25202021-08-01%252010-49-15.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MIQip1mU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/burhanuday/images/master/2021/07/Screenshot%2520from%25202021-08-01%252010-49-15.png" alt="screenshot of above code"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The tagged template syntax
&lt;/h2&gt;

&lt;p&gt;Tagged templates may look weird at first but it is valid JavaScript syntax. I won't go into a lot of details here but you can read more about it at &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#tagged_templates"&gt;MDN&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up the development environment
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;I am going to be using CodeSandbox as my development environment. If you want to publish your library to npm, I'll suggest using method 2 to generate a React library&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Method 1
&lt;/h3&gt;

&lt;p&gt;Using codesandbox.io React template&lt;/p&gt;

&lt;h3&gt;
  
  
  Method 2
&lt;/h3&gt;

&lt;p&gt;Using &lt;a href="https://github.com/transitive-bullshit/create-react-library"&gt;create-react-library&lt;/a&gt; to scaffold a React component library. &lt;/p&gt;

&lt;p&gt;First, create a new JavaScript project with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx create-react-library stylish
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then CD into the folder&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;cd &lt;/span&gt;stylish
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To start the dev servers, open two terminals and use the following commands:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal 1&lt;/strong&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 start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Terminal 2&lt;/strong&gt;&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;cd &lt;/span&gt;example
npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first terminal compiles your JavaScript component. The second terminal starts a Create React App project dev server, which allows you to use the component in a project and makes it easy to visualize your changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's work on the library
&lt;/h2&gt;

&lt;p&gt;We will develop the project in steps&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing necessary libraries
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;stylis&lt;/strong&gt; — stylis is a lightweight CSS preprocessor that handles cross browser compatibility for our library&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;nanoid&lt;/strong&gt; — nanoid is a unique string generator that we will use for randomizing class names and preventing clashes.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Run the following command to install these two libraries only if you have setup your project with Method 2. In CodeSandbox, you can add these libraries from the left sidebar.&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 stylis nanoid
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Basic structure
&lt;/h3&gt;

&lt;p&gt;Let's create a function that returns a React component and export it as the default export from the file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stylish&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Tag&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;styles&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;NewComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&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="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Tag&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Tag&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;NewComponent&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="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;stylish&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you now consumed stylish, you would see that this renders an &lt;code&gt;h1&lt;/code&gt; tag in your DOM. It does not match the exact styled components syntax, but we will fix that later. Also, the styles don't work yet since we aren't using the prop&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;stylish&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./stylish&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;H1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;stylish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;h1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;`
  color: red;
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;H1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello CodeSandbox&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;H1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;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;h3&gt;
  
  
  Styling the component
&lt;/h3&gt;

&lt;p&gt;Right now, we aren't using the styles passed down at all. But before we use them, these styles need to be preprocessed using stylis. To do that,&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;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;serialize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stringify&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;stylis&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;preprocessStyles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;styles&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;serialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This does two things, it first adds vendor prefixes to your CSS code and minifies it so that it takes less memory&lt;/p&gt;

&lt;p&gt;Now we want to generate a unique class name for our component and then inject it into the browser stylesheet. To generate a unique component, we will use nanoid.&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;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;customAlphabet&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nanoid&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;alphabet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nanoid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;customAlphabet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;alphabet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&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;generateUniqueClassname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;styles&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;uniqueId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;nanoid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&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;uniqueId&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 we have generated a unique class name, we want to inject the styles in the browser. To do that:&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;injectCSS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;styles&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;styleSheet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;styleSheets&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// get the browser's stylesheet&lt;/span&gt;
  &lt;span class="nx"&gt;styleSheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;insertRule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`.&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; {&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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 all the utility required for styling our components, it is time for us to use them&lt;br&gt;
We first check if any styles are passed, if no styles have been passed, we return without doing any of the above steps&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;stylish&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Tag&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;styles&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;NewComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&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;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;[&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="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Tag&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;className&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&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="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Tag&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Otherwise&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;preprocessedStyles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;preprocessStyles&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&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;className&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;generateUniqueClassname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;preprocessedStyles&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;injectCSS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;preprocessedStyles&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Tag&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;props&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;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Tag&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your component should now look like this&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;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;serialize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stringify&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;stylis&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;customAlphabet&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nanoid&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;alphabet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nanoid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;customAlphabet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;alphabet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&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;preprocessStyles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;styles&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;serialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;stringify&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;generateUniqueClassname&lt;/span&gt; &lt;span class="o"&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="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;uniqueId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;nanoid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&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;uniqueId&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;injectCSS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;styles&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;styleSheet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;styleSheets&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// get the browser's stylesheet&lt;/span&gt;
  &lt;span class="nx"&gt;styleSheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;insertRule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`.&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; {&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;}`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stylish&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Tag&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;styles&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;NewComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&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;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;[&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="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Tag&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;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Tag&amp;gt;&lt;/span&gt;&lt;span class="err"&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;preprocessedStyles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;preprocessStyles&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&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;className&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;generateUniqueClassname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;preprocessedStyles&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;injectCSS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;preprocessedStyles&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Tag&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;props&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;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Tag&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;NewComponent&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="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;stylish&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see that it now works as expected, and it correctly renders the HTML&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;stylish&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./stylish&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;H1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;stylish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;h1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;`
  color: red;
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;H1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello CodeSandbox&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;H1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;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;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hcRpCL7H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/burhanuday/images/master/2021/07/Screenshot%25202021-08-02%2520at%25208.11.52%2520PM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hcRpCL7H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/burhanuday/images/master/2021/07/Screenshot%25202021-08-02%2520at%25208.11.52%2520PM.png" alt="screenshot of rendered html"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Exporting all HTML tags as components
&lt;/h2&gt;

&lt;p&gt;The API does not yet match the styled-components API exactly. To use the same syntax, we must export all components as a function.&lt;/p&gt;

&lt;p&gt;The styled-components DOM elements list is pretty handy for this — &lt;a href="https://github.com/styled-components/styled-components/blob/main/packages/styled-components/src/utils/domElements.ts"&gt;domElements.ts&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can copy the array and put it in its own file in your codebase. Then export a stylish function for each of the DOM nodes, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;domElements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;domElement&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;stylish&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;domElement&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;stylish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;domElement&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;The API should now be the same as the styled-components API and should work exactly the same way&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;H1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;stylish&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="s2"&gt;`
  color: red;
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  End of Part 1
&lt;/h2&gt;

&lt;p&gt;This is the end of Part 1 of this multipart series. Here's the tentative list of contents of the next articles in the series:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Part 2 — Working with component composition and making reusable styled components&lt;/li&gt;
&lt;li&gt;Part 3 — Optimizing and deduplicating styles&lt;/li&gt;
&lt;li&gt;Part 4 — Global styles and handling multiple themes&lt;/li&gt;
&lt;li&gt;Part 5 — Publishing your library to NPM&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can find the complete code for this part at &lt;a href="https://codesandbox.io/s/stylish-nslns"&gt;CodeSandbox — Part 1&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can follow me on DEV to get updated when I post my next article&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>showdev</category>
    </item>
    <item>
      <title>The const keyword does not create immutable variables</title>
      <dc:creator>Burhanuddin Udaipurwala</dc:creator>
      <pubDate>Wed, 28 Jul 2021 15:25:02 +0000</pubDate>
      <link>https://dev.to/burhanuday/the-const-keyword-does-not-create-immutable-variables-2mbo</link>
      <guid>https://dev.to/burhanuday/the-const-keyword-does-not-create-immutable-variables-2mbo</guid>
      <description>&lt;h2&gt;
  
  
  An introduction to the &lt;code&gt;const&lt;/code&gt; keyword
&lt;/h2&gt;

&lt;p&gt;The value of a variable created with the &lt;code&gt;const&lt;/code&gt; keyword can't be changed. Although this statement is true in the case of primitive values, it is complicated when it comes to objects and arrays.&lt;/p&gt;

&lt;p&gt;For objects and arrays, only the reference to the memory location that contains the data is stored in the variable. So the data underneath can be changed without changing the reference&lt;/p&gt;

&lt;p&gt;Example:&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;foodsILike&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Shwarma&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="nx"&gt;foodsILike&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Jalebi&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;foodsILike&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; ["Shwarma", "Jalebi"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we created an array with the &lt;code&gt;const&lt;/code&gt; keyword and were still able to add items to it&lt;/p&gt;

&lt;h2&gt;
  
  
  What is immutability and why is it important?
&lt;/h2&gt;

&lt;p&gt;Functional programming techniques and design patterns are very common in the Javascript world. We have tools like RxJS which bring reactivity to Javascript. Redux also depends on its state to be immutable. As a JS developer, you must take care that you do not mutate the state directly while updating it. &lt;a href="https://redux.js.org/tutorials/fundamentals/part-3-state-actions-reducers"&gt;In Redux, &lt;strong&gt;our reducers are &lt;em&gt;never&lt;/em&gt; allowed to mutate the original / current state values!&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To prevent issues like these from occurring, you want to make your data immutable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using the &lt;code&gt;Object.freeze()&lt;/code&gt; method
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;Object.freeze()&lt;/code&gt; method &lt;code&gt;freezes&lt;/code&gt; an object (duh!). What does this exactly mean? A frozen object cannot be edited. New properties cannot be added and existing properties cannot be removed or modified in any way.&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use strict&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;freeze&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;33&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; TypeError: "prop" is read-only&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; will fail silently in non strict mode&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is however, a flaw to this approach&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use strict&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;propObject&lt;/span&gt;&lt;span class="p"&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="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;freeze&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;propObject&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;name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Burhan&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="cm"&gt;/**
{
  prop: 42,
  propObject: {
    name: "Burhan"
  }
}
*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works perfectly fine since we are not modifying any properties of the frozen object directly.&lt;/p&gt;

&lt;p&gt;You could use the &lt;a href="https://github.com/substack/deep-freeze"&gt;deep-freeze&lt;/a&gt; package that recursively freezes all your objects&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;var&lt;/span&gt; &lt;span class="nx"&gt;deepFreeze&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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;deep-freeze&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;deepFreeze&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&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="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;z&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&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="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;z&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="cm"&gt;/**
true
true
*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will help you prevent issues with mutations&lt;/p&gt;

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

&lt;p&gt;The &lt;code&gt;const&lt;/code&gt; keyword creates a read-only reference to a value. It does not mean that the value itself is immutable. It's just that the variable identifier cannot be reassigned&lt;/p&gt;

&lt;p&gt;If you plan on using immutable objects with React or Redux, check out &lt;a href="https://github.com/immerjs/immer"&gt;ImmerJS&lt;/a&gt;. It enables you to create new objects without writing extra code for deep clones. It also has some great utility hooks to use with React&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
    </item>
  </channel>
</rss>
