<?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>Forem: Jorge</title>
    <description>The latest articles on Forem by Jorge (@jorgeagoiz).</description>
    <link>https://forem.com/jorgeagoiz</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%2F803632%2F246e4551-bc5a-45d8-b9a7-487820717cf9.jpeg</url>
      <title>Forem: Jorge</title>
      <link>https://forem.com/jorgeagoiz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/jorgeagoiz"/>
    <language>en</language>
    <item>
      <title>NextJs, Docker and IP Geolocation</title>
      <dc:creator>Jorge</dc:creator>
      <pubDate>Sat, 09 Nov 2024 20:20:33 +0000</pubDate>
      <link>https://forem.com/jorgeagoiz/nextjs-docker-and-ip-geolocation-1al1</link>
      <guid>https://forem.com/jorgeagoiz/nextjs-docker-and-ip-geolocation-1al1</guid>
      <description>&lt;p&gt;These days, I've been working on a solution that would allow us to geolocate users through their IP address, with our &lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;NextJs&lt;/a&gt; project hosted on AWS ECS in a Docker container.&lt;/p&gt;

&lt;p&gt;With the primary focus on geolocating users through their IP address, other challenges emerged, which I will enumerate.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. AVOIDING THIRD-PARTY CALLS
&lt;/h3&gt;

&lt;p&gt;This point was important because, although there is a wide catalog of services (many free of charge) that offer IP geolocation, I didn't want to depend on a third-party call if possible.&lt;/p&gt;

&lt;p&gt;During my research, I found several services that allow you to download a binary file with the &lt;a href="https://maxmind.github.io/MaxMind-DB/" rel="noopener noreferrer"&gt;".mmdb"&lt;/a&gt; extension, which is the actual database we can use to geolocate IPs.&lt;/p&gt;

&lt;p&gt;After completing the investigation I opted for &lt;a href="https://www.maxmind.com/en/geoip-databases" rel="noopener noreferrer"&gt;Maxmind&lt;/a&gt;. They have many options through which you can download the binary database but I decided to use the geoipupdate automation they offer in their documentation. This allows you to automate the process of downloading and updating the &lt;code&gt;.mmdb&lt;/code&gt; file.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. PROTECTING LOGIC FROM CLIENT-SIDE
&lt;/h3&gt;

&lt;p&gt;Another key aspect was to leverage Next.js's server-side capabilities to avoid exposing logic on the client side. In current versions, this can be done by either generating a "route handler" or using a "server action". For versions prior to 13, we would need to create our own "API route".&lt;/p&gt;

&lt;p&gt;To obtain our users' IP on the server side, we only need the &lt;a href="https://nextjs.org/docs/app/api-reference/functions/headers" rel="noopener noreferrer"&gt;req.headers['x-forwarded-for']&lt;/a&gt; header provided by Next.js. Once we capture their IP, we'll search for its origin in our file using the &lt;a href="https://www.npmjs.com/package/mmdb-lib" rel="noopener noreferrer"&gt;mmdb-lib node package&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. PERIODIC AUTOMATIC DATABASE SYNCHRONIZATION
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://github.com/maxmind/geoipupdate" rel="noopener noreferrer"&gt;Maxmind geoipupdate integration&lt;/a&gt; was extremely helpful for this purpose. This integration automatically manages the download and update of the file with minimal configuration, requiring only your credentials to be provided.&lt;/p&gt;

&lt;p&gt;The main problem I encountered was that within a node:alpine Docker container, I couldn't execute cron jobs with a user other than root. I resolved this by using &lt;a href="https://github.com/aptible/supercronic" rel="noopener noreferrer"&gt;supercronic&lt;/a&gt;, a tool optimized for running your cron jobs inside Docker images. Additionally, it's worth nothing that this tool facilitates the visualization of logs about how the process targeted by the crontab has progressed.&lt;/p&gt;

&lt;p&gt;Once this was resolved, I managed to keep a cron job running in the background within the Docker container where my Next.js project is deployed. This cron job periodically checks and updates my binary database file stored within the container's own file system.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;&lt;strong&gt;FINAL NOTES&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;

&lt;p&gt;In order to have a guide where part of this process can be visualized, I have generated a pre-configured template. In it, we can verify the functionality and observe the minimum necessary configuration:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/jorgeAgoiz/nextjs-docker-maxmind" rel="noopener noreferrer"&gt;Visit my template on Github&lt;/a&gt;&lt;/p&gt;

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

</description>
      <category>nextjs</category>
      <category>docker</category>
      <category>maxmind</category>
      <category>geolocation</category>
    </item>
    <item>
      <title>Big O Notation and Algorithms in JavaScript</title>
      <dc:creator>Jorge</dc:creator>
      <pubDate>Sun, 22 Sep 2024 18:28:47 +0000</pubDate>
      <link>https://forem.com/jorgeagoiz/big-o-notation-and-algorithms-in-javascript-4djf</link>
      <guid>https://forem.com/jorgeagoiz/big-o-notation-and-algorithms-in-javascript-4djf</guid>
      <description>&lt;h3&gt;
  
  
  Introduction to Big O Notation
&lt;/h3&gt;

&lt;p&gt;Big O notation shows the number of operations an algorithm will perform, its complexity, and how quickly it will grow. It will never show the execution time of the algorithm.&lt;/p&gt;

&lt;p&gt;These are the six main types of complexity we find in Big O notation:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Constant O(1):&lt;/strong&gt; The number of executions will always be the same regardless of the input size "n". It is the best complexity since the size of the input data does not affect it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Logarithmic O(log n):&lt;/strong&gt; The number of executions increases logarithmically in proportion to the input size "n". Typically, the executions involve dividing the input data into smaller parts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Linear O(n):&lt;/strong&gt; The number of executions increases linearly with the input size "n". The executions will be equal to the input size, so the larger the input, the more executions will be required.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exponential O(2^n):&lt;/strong&gt; In this case, the number of executions doubles in relation to the input size "n". If with an input X we get 20 executions, with double that input we will get 400 executions. While not the worst, it is recommended to avoid this complexity, especially for large datasets.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quadratic O(n^2):&lt;/strong&gt; In this case, the number of executions increases quadratically with the input size "n". This occurs when there are nested loops. It is one of the worst complexities, along with factorial complexity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Factorial O(n!):&lt;/strong&gt; In this case, the number of executions increases factorially with the input size "n". Along with quadratic complexity, it is one of the worst and becomes nearly impossible to handle with large amounts of data.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

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



&lt;p&gt;Let's look at a couple of examples of search algorithms in JavaScript where we can measure two of the listed complexities:&lt;/p&gt;

&lt;p&gt;&lt;u&gt;1. Linear Search&lt;/u&gt;&lt;/p&gt;

&lt;p&gt;Linear search goes through the array element by element until it finds the desired value or reaches the end of the array.&lt;/p&gt;

&lt;p&gt;The complexity of this algorithm is O(n), or linear. It increases in proportion to the size of the array, meaning the larger the array, the more executions will be required.&lt;/p&gt;

&lt;p&gt;In this code example, we return the index of the element when it matches the value we are searching for, and -1 when the value is not found.&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;function&lt;/span&gt; &lt;span class="nf"&gt;linearSearch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;value&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;i&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;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some JavaScript array methods that use linear search:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;indexOf&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;lastIndexOf&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;includes&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;find&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;findIndex&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;some&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;every&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;u&gt;2. Binary Search&lt;/u&gt;&lt;/p&gt;

&lt;p&gt;First, it's important to note that this search algorithm can only be performed on sorted arrays.&lt;/p&gt;

&lt;p&gt;What happens here is that the array is divided into two halves, then the value we're searching for is compared to determine which half it belongs to. The algorithm iterates with the same operation over the relevant half until it finds the value.&lt;/p&gt;

&lt;p&gt;The complexity of this algorithm is O(log n), or logarithmic. In the following code example, at each step, the algorithm halves the search space until it finds the desired value or determines that it is not present. We return the index where the value is found, or -1 if the value is not in the array.&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;function&lt;/span&gt; &lt;span class="nf"&gt;binarySearch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&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;let&lt;/span&gt; &lt;span class="nx"&gt;end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;middle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;middle&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;middle&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="nx"&gt;end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;middle&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;middle&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nx"&gt;middle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&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;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;middle&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;middle&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  In Conclusion
&lt;/h3&gt;

&lt;p&gt;Big O notation is a standardized way of measuring the efficiency of different algorithms, focusing on predicting their behavior as the input size grows.&lt;/p&gt;

&lt;p&gt;It's important to emphasize the need to dive deeper into these concepts, especially if we aim for excellence when handling large amounts of data.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;Resources:&lt;/u&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Image of the chart taken from &lt;a href="https://www.freecodecamp.org/news/big-o-cheat-sheet-time-complexity-chart" rel="noopener noreferrer"&gt;FreeCodeCamp.org&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>algorithms</category>
      <category>performance</category>
    </item>
    <item>
      <title>Web Components Introduction</title>
      <dc:creator>Jorge</dc:creator>
      <pubDate>Sun, 05 Nov 2023 20:55:21 +0000</pubDate>
      <link>https://forem.com/jorgeagoiz/web-components-basics-5335</link>
      <guid>https://forem.com/jorgeagoiz/web-components-basics-5335</guid>
      <description>&lt;h2&gt;
  
  
  What is a web component?
&lt;/h2&gt;

&lt;p&gt;When we talk about a &lt;em&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_components" rel="noopener noreferrer"&gt;WebComponents&lt;/a&gt;&lt;/em&gt;, we are talking about a set of Web APIS, which together with different technologies (&lt;em&gt;HTML, CSS and JavaScript&lt;/em&gt;) and always natively under web standards, allow you to create elements with a specific purpose in a fully customizable way, reusable and extendable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Important features of Web Components
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements" rel="noopener noreferrer"&gt;&lt;strong&gt;1. Custom Elements&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_templates_and_slots" rel="noopener noreferrer"&gt;&lt;strong&gt;2. HTML Templates&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM" rel="noopener noreferrer"&gt;&lt;strong&gt;3. Shadow DOM&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules" rel="noopener noreferrer"&gt;&lt;strong&gt;4. ES Modules&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM#encapsulation_from_css" rel="noopener noreferrer"&gt;&lt;strong&gt;5. CSS Scopes &amp;amp; Parts&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;u&gt;Custom Elements &lt;/u&gt;
&lt;/h3&gt;

&lt;p&gt;They are a set of Web APIS that allow you to define custom HTML elements. Just as the HTML5 standard defines that official HTML tags must consist of a single word, custom elements must consist of at least two words separated by a hyphen.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;u&gt;HTML Templates&lt;/u&gt;
&lt;/h3&gt;

&lt;p&gt;They allow you to create code fragments isolated from the document, its content will be inert and will not be processed or rendered until we clone its content&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;u&gt;Shadow DOM&lt;/u&gt;
&lt;/h3&gt;

&lt;p&gt;It allows you to attach hidden DOMs within the &lt;em&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Introduction" rel="noopener noreferrer"&gt;regular DOM&lt;/a&gt;&lt;/em&gt;, making it possible to encapsulate and isolate elements from the rest of the page.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;u&gt;ES Modules&lt;/u&gt;
&lt;/h3&gt;

&lt;p&gt;It´s a native feature that allows the import and export of data fragments between different JavaScript files.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;u&gt;CSS Scopes &amp;amp; Parts&lt;/u&gt;
&lt;/h3&gt;

&lt;p&gt;Although CSS works globally by default, we have specific pseudoclasses and pseudoelements in addition to the &lt;em&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/::part" rel="noopener noreferrer"&gt;“CSS Parts”&lt;/a&gt;&lt;/em&gt; to expose parts of our component to the outside and style them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Advantages of web components
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;They follow web standards so they work in any current browser.&lt;/li&gt;
&lt;li&gt;Its implementation is native so we do not depend on third-party frameworks or libraries.&lt;/li&gt;
&lt;li&gt;They are reusable, extensible and allow us to create fully encapsulated elements.&lt;/li&gt;
&lt;li&gt;Currently you can implement them in almost all the most popular Frameworks. &lt;strong&gt;&lt;a href="https://custom-elements-everywhere.com/" rel="noopener noreferrer"&gt;Check it&lt;/a&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;p&gt;These are some of the documentation in Spanish and English that I consider to be a reference.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://lenguajejs.com/webcomponents/" rel="noopener noreferrer"&gt;https://lenguajejs.com/webcomponents/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.webcomponents.org/" rel="noopener noreferrer"&gt;https://www.webcomponents.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/es/docs/Web/API/Web_components" rel="noopener noreferrer"&gt;https://developer.mozilla.org/es/docs/Web/API/Web_components&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://htmlwithsuperpowers.netlify.app/" rel="noopener noreferrer"&gt;https://htmlwithsuperpowers.netlify.app/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>webcomponents</category>
    </item>
    <item>
      <title>Two React apps in the same S3 Bucket.</title>
      <dc:creator>Jorge</dc:creator>
      <pubDate>Fri, 10 Mar 2023 11:29:43 +0000</pubDate>
      <link>https://forem.com/jorgeagoiz/two-react-apps-in-a-same-s3-bucket-4ado</link>
      <guid>https://forem.com/jorgeagoiz/two-react-apps-in-a-same-s3-bucket-4ado</guid>
      <description>&lt;p&gt;These days ago, I had to search for information and investigate whether two React applications could coexist in the same S3 bucket, without using any other AWS service except the S3 bucket.&lt;/p&gt;

&lt;p&gt;I will say that this is not a good practice and only in certain cases like the one that has been presented to me would it be a solution.&lt;/p&gt;

&lt;p&gt;The idea is to be able to jump between the two applications once both have been deployed to the bucket. To do this, the first step would be to create a folder structure that facilitates understanding as much as possible.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./react-apps
    /original-app #### Original react app
    /nested-app #### Nested react app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For both projects ( &lt;em&gt;&lt;strong&gt;original-app&lt;/strong&gt;&lt;/em&gt; and &lt;em&gt;&lt;strong&gt;nested-app&lt;/strong&gt;&lt;/em&gt;) we will use &lt;a href="https://vitejs.dev/guide/"&gt;Vite + React&lt;/a&gt;. So inside the &lt;strong&gt;&lt;em&gt;"/react-apps"&lt;/em&gt;&lt;/strong&gt; folder :&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm create vite@latest original-app -- --template react&lt;/code&gt;&lt;br&gt;
&lt;code&gt;npm create vite@latest nested-app -- --template react&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Within each project we will find the file &lt;em&gt;&lt;strong&gt;"vite.config.js"&lt;/strong&gt;&lt;/em&gt; which we have to adjust in both cases. First we'll go with the configuration file of the &lt;em&gt;&lt;strong&gt;"original-app"&lt;/strong&gt;&lt;/em&gt; project:&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="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;@vitejs/plugin-react-swc&lt;/span&gt;&lt;span class="dl"&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;defineConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vite&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// https://vitejs.dev/config/&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;react&lt;/span&gt;&lt;span class="p"&gt;()],&lt;/span&gt;
  &lt;span class="na"&gt;base&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;outDir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../dist&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;emptyOutDir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Basically we are indicating where to build the project and not to show any warning when doing it outside the root directory. We will build both projects in our root directory &lt;em&gt;&lt;strong&gt;"/react-apps"&lt;/strong&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In &lt;em&gt;&lt;strong&gt;"nested-app"&lt;/strong&gt;&lt;/em&gt; our configuration file should 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="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;@vitejs/plugin-react-swc&lt;/span&gt;&lt;span class="dl"&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;defineConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vite&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// https://vitejs.dev/config/&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;react&lt;/span&gt;&lt;span class="p"&gt;()],&lt;/span&gt;
  &lt;span class="na"&gt;base&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/nested-app/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;outDir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../dist/nested-app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;emptyOutDir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here are two differences:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The first is that we are indicating that &lt;em&gt;&lt;strong&gt;"/nested-app/"&lt;/strong&gt;&lt;/em&gt; will be the public route where the application will serve us both in development and in production.&lt;/li&gt;
&lt;li&gt;The second is that we are telling it to build the project in a subdirectory of the &lt;em&gt;&lt;strong&gt;"original-app"&lt;/strong&gt;&lt;/em&gt; build.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once we have the configuration files as we have seen, the next step would be to &lt;a href="https://reactrouter.com/en/main/start/tutorial#setup"&gt;install React Router&lt;/a&gt; in both projects.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install react-router-dom localforage match-sorter sort-by
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will need to use the &lt;a href="https://reactrouter.com/en/main/router-components/hash-router"&gt;"HashRouter"&lt;/a&gt; component so that the two applications can coexist and we can go from one to the other once they are in our bucket or we are serving the static ones through &lt;em&gt;&lt;strong&gt;"npm serve"&lt;/strong&gt;&lt;/em&gt; . You can read the official documentation to understand how works this component.&lt;/p&gt;

&lt;p&gt;To understand the behavior at a basic level, let's take a look at the &lt;em&gt;&lt;strong&gt;"App.jsx"&lt;/strong&gt;&lt;/em&gt; components of both the &lt;em&gt;&lt;strong&gt;"original-app"&lt;/strong&gt;&lt;/em&gt; and &lt;em&gt;&lt;strong&gt;"nested-app"&lt;/strong&gt;&lt;/em&gt; applications.&lt;/p&gt;

&lt;p&gt;In both applications we have configured two routes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Home page&lt;/em&gt;&lt;/strong&gt; =&amp;gt; &lt;em&gt;&lt;strong&gt;"/"&lt;/strong&gt;&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Page about&lt;/em&gt;&lt;/strong&gt; =&amp;gt; &lt;em&gt;&lt;strong&gt;"/about"&lt;/strong&gt;&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This would be the component of our &lt;em&gt;&lt;strong&gt;"original-app"&lt;/strong&gt;&lt;/em&gt; project:&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="c1"&gt;// Path: react-apps/original-app/App.jsx&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;HashRouter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Routes&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-router-dom&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;App&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="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;HashRouter&lt;/span&gt; &lt;span class="na"&gt;basename&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&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;Routes&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;Route&lt;/span&gt;
            &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;
            &lt;span class="na"&gt;element&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&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="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/nested-app/#/about"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;About Nested App&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&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;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/#/about"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;About Original App&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&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="si"&gt;}&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;Route&lt;/span&gt; 
            &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/about/"&lt;/span&gt; 
            &lt;span class="na"&gt;element&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&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="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/nested-app/#/"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Home Nested App&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&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;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/#/"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Home Original App&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&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="si"&gt;}&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;Routes&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;HashRouter&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;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And this would be the component of our &lt;em&gt;&lt;strong&gt;"nested-app"&lt;/strong&gt;&lt;/em&gt; project:&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="c1"&gt;// Path: react-apps/nested-app/App.jsx&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;HashRouter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Routes&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-router-dom&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;App&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="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;HashRouter&lt;/span&gt; &lt;span class="na"&gt;basename&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&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;Routes&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;Route&lt;/span&gt; 
            &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt; 
            &lt;span class="na"&gt;element&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&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="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/nested-app/#/about"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;About Nested App&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&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;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/#/about"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;About Original App&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&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="si"&gt;}&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;Route&lt;/span&gt;
            &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/about/"&lt;/span&gt;
            &lt;span class="na"&gt;element&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&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="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/#/"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Home Original App&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&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;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/nested-app/#/"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Home Nested App&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&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="si"&gt;}&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;Routes&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;HashRouter&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;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Right now we could move between the two routes of both applications. Jumping from one application to another with the only peculiarity that the &lt;strong&gt;&lt;em&gt;"HashRouter"&lt;/em&gt;&lt;/strong&gt; component works by adding &lt;em&gt;&lt;strong&gt;"Hash"&lt;/strong&gt;&lt;/em&gt; to the routes. You could share information between the two applications either through the URL or through the &lt;em&gt;&lt;strong&gt;"SessionStorage"&lt;/strong&gt;&lt;/em&gt; or &lt;em&gt;&lt;strong&gt;"LocalStorage"&lt;/strong&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Once we have all this structure we can execute the build of &lt;em&gt;&lt;strong&gt;"original-app"&lt;/strong&gt;&lt;/em&gt; and then the build of &lt;em&gt;&lt;strong&gt;"nested-app"&lt;/strong&gt;&lt;/em&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="c"&gt;# Path: react-apps/original-app&lt;/span&gt;
npm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Path: react-apps/nested-app&lt;/span&gt;
npm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;em&gt;&lt;strong&gt;"/dist"&lt;/strong&gt;&lt;/em&gt; folder will be generated in our root directory and we should see something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./react-apps
   /original-app #### Original react app
   /nested-app #### Nested react app
   /dist #### Folder with both builds
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside of &lt;em&gt;&lt;strong&gt;"/dist"&lt;/strong&gt;&lt;/em&gt; folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.dist/
   index.html #### Index of original-app
   /assets #### Assets of original-app
   /nested-app #### Folder with nested-app
     index.html #### Index of nested-app
     /assets #### Assets of nested-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we could upload the contents of the &lt;em&gt;&lt;strong&gt;"/dist"&lt;/strong&gt;&lt;/em&gt; folder and have the two applications coexist within the same S3 bucket. We could also serve our statics by running the &lt;em&gt;&lt;strong&gt;"serve"&lt;/strong&gt;&lt;/em&gt; command from the &lt;em&gt;&lt;strong&gt;"/original-app"&lt;/strong&gt;&lt;/em&gt; folder which would be our root application.&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="c"&gt;# Path: ./react-apps/original-app&lt;/span&gt;
npm run serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, just remember that this is not a good practice and that the React Router documentation itself currently advises against the use of the &lt;em&gt;&lt;strong&gt;&lt;a href="https://dev.tor"&gt;"HashRouter"&lt;/a&gt;&lt;/strong&gt;&lt;/em&gt; component. But for certain cases, it could be a temporary solution to a problem since with this it would not be necessary to use &lt;em&gt;&lt;strong&gt;&lt;a href="https://docs.aws.amazon.com/es_es/AmazonCloudFront/latest/DeveloperGuide/Introduction.html"&gt;AWS "CloudFront"&lt;/a&gt;&lt;/strong&gt;&lt;/em&gt;, just the S3 bucket.&lt;/p&gt;

&lt;p&gt;Thanks to my co-worker Víctor 🙌 and the &lt;a href="https://www.webreactiva.com/"&gt;community of Daniel Primo&lt;/a&gt; 💜 who helped me with this experiment.&lt;/p&gt;

&lt;p&gt;Greetings 👋&lt;/p&gt;

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