<?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: Lyubomir Angelov</title>
    <description>The latest articles on DEV Community by Lyubomir Angelov (@lyubomir).</description>
    <link>https://dev.to/lyubomir</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%2F152092%2F6970e4c7-4da1-4260-b43f-d841db0a222c.jpg</url>
      <title>DEV Community: Lyubomir Angelov</title>
      <link>https://dev.to/lyubomir</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lyubomir"/>
    <language>en</language>
    <item>
      <title>Vbox7.com - quick performance audit</title>
      <dc:creator>Lyubomir Angelov</dc:creator>
      <pubDate>Tue, 18 Feb 2020 21:57:21 +0000</pubDate>
      <link>https://dev.to/lyubomir/vbox7-com-quick-performance-audit-382h</link>
      <guid>https://dev.to/lyubomir/vbox7-com-quick-performance-audit-382h</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;I was curious what is the speed performance of Vbox7.com website, a vastly visited website in Bulgaria. Vbox7.com is video platform just like Youtube.com but only with Bulgarian content. In December 2019 the total (desktop, mobile &amp;amp; APPs) visits are 3 200 000, quite a lot, more info you can find on their page &lt;a href="https://www.netinfocompany.bg/vbox"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Based on that I decided to not spend too much time and do quick performance analysis on the website.&lt;/p&gt;

&lt;h2&gt;
  
  
  Images
&lt;/h2&gt;

&lt;p&gt;With this number of visits and the huge amount of images and videos played, they should have lots of servers and lots of bandwidth that goes through them.&lt;/p&gt;

&lt;p&gt;That's why I went through a few pages using &lt;a href="https://webpagetest.org/"&gt;Webpagetest&lt;/a&gt; and Cloudinary Image Analysis results.&lt;/p&gt;

&lt;h3&gt;
  
  
  Logo
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://i49.vbox7.com/design/mobile3/vbox7-logo-white.svg"&gt;logo&lt;/a&gt; is an SVG file, which is very good, but what they can do is to inline it, compress it (remove unnecessary tags, comments, attributes) and make it smaller.&lt;/p&gt;

&lt;h3&gt;
  
  
  Compression and Format
&lt;/h3&gt;

&lt;p&gt;They can implement a few things for dynamically generated images eg. video posters:&lt;br&gt;
    - better compression like mozJPEG for JPEGs&lt;br&gt;
    - provide right type and format using &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; tag - &lt;a href="https://developers.google.com/speed/webp"&gt;Webp&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This should decrease the average total image size per page approximately 2.5 MB!&lt;/p&gt;

&lt;h3&gt;
  
  
  Lazy load images
&lt;/h3&gt;

&lt;p&gt;Open &lt;a href="https://webpagetest.org/result/200110_TT_87b54c0a5545a2349e76474acbea4491/1/details/"&gt;this&lt;/a&gt; Webpagetest result and you will see that this page have &lt;strong&gt;~306&lt;/strong&gt; requests, of which &lt;a href="https://webpagetest.org/result/200110_TT_87b54c0a5545a2349e76474acbea4491/1/breakdown/"&gt;&lt;strong&gt;113&lt;/strong&gt;&lt;/a&gt; are images.&lt;/p&gt;

&lt;p&gt;If they implement &lt;a href="https://developers.google.com/web/fundamentals/performance/lazy-loading-guidance/images-and-video"&gt;lazy load&lt;/a&gt; on images, the total amount of images per page can drop to &lt;strong&gt;~30&lt;/strong&gt;!&lt;/p&gt;

&lt;h3&gt;
  
  
  The CDN
&lt;/h3&gt;

&lt;p&gt;As &lt;a href="https://twitter.com/patmeenan"&gt;Patrick Meenan&lt;/a&gt; says, most of out there CDNs do not do proper HTTP2 prioritization, thus make slower load times of images and other requests. On this website, the prioritization is terrible.&lt;br&gt;
By simple look how to &lt;a href="https://github.com/pmeenan/http2priorities/tree/master/stand-alone"&gt;test http2 prioritization&lt;/a&gt; I managed to test their CDN &lt;em&gt;i49.vbox7.com&lt;/em&gt; and the results are quote &lt;strong&gt;"EPIC FAIL"&lt;/strong&gt;, you can check in the test &lt;a href="https://webpagetest.org/result/200115_VB_225f3ef511df610dd2534688759ab215/1/details/#waterfall_view_step1"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I will stop here, they have lots of room for performance improvements if you only do a quick look at the pages. :)&lt;/p&gt;

&lt;h2&gt;
  
  
  Can I ask Why
&lt;/h2&gt;

&lt;p&gt;Why they don't do it, why they are not spending several hours to implement few basic optimisations on the pages and deliver better &lt;strong&gt;user experience&lt;/strong&gt;, less user traffic spent and fewer costs for servers?&lt;/p&gt;

</description>
      <category>performance</category>
      <category>lazyload</category>
      <category>http2prioritization</category>
    </item>
    <item>
      <title>Case Study: React partial SSR with SFCC</title>
      <dc:creator>Lyubomir Angelov</dc:creator>
      <pubDate>Wed, 15 Jan 2020 18:06:15 +0000</pubDate>
      <link>https://dev.to/lyubomir/case-study-react-partial-ssr-with-sfcc-1198</link>
      <guid>https://dev.to/lyubomir/case-study-react-partial-ssr-with-sfcc-1198</guid>
      <description>&lt;h1&gt;
  
  
  Case Study: React partial SSR with SFCC
&lt;/h1&gt;

&lt;h2&gt;
  
  
  React partial SSR in restricted cloud CMSs
&lt;/h2&gt;

&lt;p&gt;This case study will show a way to implement partial &lt;strong&gt;Server-Side Rendering (SSR)&lt;/strong&gt; and achieve performance gains without big investments for middleware in cloud-based platforms.&lt;/p&gt;

&lt;p&gt;All cloud CMSs like Salesforce Commerce Cloud (SFCC) and Magento have their pros and cons. In those CMSs, we have lots of restrictions, but the major one for the purposes of this article is that we do not have access to the server, so we can't use Server-Side Rendering.&lt;/p&gt;

&lt;p&gt;SFCC (ex Demandware) is cloud-based unified e-commerce platform for B2C retailers. Its core is written in Java but clients can extend it with JavaScript which they transpile to Java.&lt;/p&gt;

&lt;p&gt;Our application is built with React and consumes JSON API returned from our headless SFCC.&lt;/p&gt;

&lt;p&gt;If we want the performance gains of the SSR we have two options:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create middleware between the React app and the backend SFCC&lt;/li&gt;
&lt;li&gt;Create Partial SSR with what you have from the system&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In our project, we can't go with option 1 because of budget, resources and time. That's why we chose option 2. This post describes what we did, but first, let's start with some background information.&lt;/p&gt;

&lt;h2&gt;
  
  
  React, SSR, Hydration, Progressive Hydration
&lt;/h2&gt;

&lt;p&gt;If our goal is to make our React website fast, one of the best things we can do is to use &lt;strong&gt;Server-Side Rendering (SSR)&lt;/strong&gt; for the whole application. For this to work, we need control over the server where the application is hosted and render the React app using, for example, &lt;a href="https://levelup.gitconnected.com/how-to-build-a-server-side-rendered-react-app-with-next-js-b405c2634b5b" rel="noopener noreferrer"&gt;Next.js&lt;/a&gt; or &lt;a href="https://itnext.io/server-side-rendering-with-react-redux-and-react-router-fa5b67d4965e" rel="noopener noreferrer"&gt;NodeJS&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;SSR generates complete HTML for the page and returns it to the browser.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    Some meta, CSS, scripts, third-parties etc.
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"app"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"app-root"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;header&amp;gt;&lt;/span&gt;
          Logo, username etc.
          &lt;span class="nt"&gt;&amp;lt;nav&amp;gt;&lt;/span&gt;The navigation items&lt;span class="nt"&gt;&amp;lt;/nav&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/header&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"app-container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
          All the content between header and footer
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;footer&amp;gt;&lt;/span&gt;
          Copyright and links stuff
        &lt;span class="nt"&gt;&amp;lt;/footer&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's ok, now we just need to use &lt;strong&gt;hydration&lt;/strong&gt; to let React attach all events handlers that it needs.&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;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hydrate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="p"&gt;[,&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that, we get approximately 20% faster in most of the metrics - LCP, Speed Index and TTI - but we will get a little bit slower Time to first byte (TTFB) because the backend needs additional time to SSR the application.&lt;/p&gt;

&lt;p&gt;But we can improve the app even further: we can apply React Progressive Hydration (which I won't discuss in detail, there are lots of articles about it:&lt;br&gt;
&lt;a href="https://twitter.com/dan_abramov/status/1200111677833973760" rel="noopener noreferrer"&gt;Dan Abramov Progressive Hydration demo&lt;/a&gt;, &lt;br&gt;
&lt;a href="https://houssein.me/progressive-react" rel="noopener noreferrer"&gt;Progressive React&lt;/a&gt;, &lt;br&gt;
&lt;a href="https://dev.to/marvelouswololo/how-to-server-side-render-react-hydrate-it-on-the-client-and-combine-client-and-server-routes-1a3p"&gt;SSR React and Hydration&lt;/a&gt;).&lt;/p&gt;
&lt;h3&gt;
  
  
  What is Progressive Hydration?
&lt;/h3&gt;

&lt;p&gt;With Progressive Hydration React can attach only the events for elements that are visible in the initial viewport, so we can further reduce JavaScript's execution time.&lt;/p&gt;
&lt;h2&gt;
  
  
  Problems
&lt;/h2&gt;

&lt;p&gt;Since we're using SFCC we are not able to do the SSR described above, that's why we had to think about what we can do in order to achieve similar results as if we had SSR.&lt;/p&gt;

&lt;p&gt;Our Homepage and Category Landing Pages are pure HTML, CSS and a little bit of JavaScript that is created in the CMS from WYSIWYG editor, again the limitation of the platform. This content is created by the third party which is responsible for the whole dynamic content on the platform. Then this content (HTML, CSS, JS) is provided with JSON API that the React app gets and fills the &lt;strong&gt;app-container&lt;/strong&gt; div.&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;let&lt;/span&gt; &lt;span class="nx"&gt;content&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="s2"&gt;result&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;html&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;ENCODED HTML/CSS/JS from the WYSIWYG editor&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;render&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;dangerouslySetInnerHTML&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;__html&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because of that approach, the end result that the customers are seeing is this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fpff1mm856egkzpzs2i44.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fpff1mm856egkzpzs2i44.jpg" alt="React no partial SSR"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem one
&lt;/h3&gt;

&lt;p&gt;What we can return directly from the backend is the HTML below, which is not enough for the React app to hydrate.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    Some meta, CSS, scripts, third-parties etc.
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"app-shell"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Static Header&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"app-container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      Content between header and footer
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"app"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Problem two
&lt;/h3&gt;

&lt;p&gt;In order to use React and the hydration mode, we must provide the whole DOM structure of the React-generated HTML.&lt;br&gt;
It is React app, almost every HTML is generated by the React and the JSON API that he consumes. With that, we don't have for example the HTML of the &lt;code&gt;&amp;lt;header&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;footer&amp;gt;&lt;/code&gt;. This is the maximum of what we can do as server-side generated HTML:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    Some meta, CSS, scripts, third-parties etc.
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"app"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"app-root"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;header&amp;gt;&amp;lt;/header&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"app-container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
          Content between header and footer
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;footer&amp;gt;&amp;lt;/footer&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we return this HTML without the content of the &lt;code&gt;&amp;lt;header&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;footer&amp;gt;&lt;/code&gt;, tags, React will throw an error, because it needs the whole DOM structure in order to attach the events and cannot fill the missing elements.&lt;/p&gt;

&lt;h2&gt;
  
  
  So what we did?
&lt;/h2&gt;

&lt;p&gt;First of all, initially, we thought that we can just create the above HTML structure and React will fill the missing elements only but few hours and errors later we figured out that React needs whole React-generated HTML in order to hydrate.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step One
&lt;/h3&gt;

&lt;p&gt;Return what we have as HTML from the backend and the initial structure looks like that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    Some meta, CSS, scripts, third-parties etc.
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"app-shell"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Static Header&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"app-container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      Content between header and footer
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"app"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"OUR_INITIAL_REACT_BUNDLES"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step Two
&lt;/h3&gt;

&lt;p&gt;Our initial App architecture is like this:&lt;/p&gt;

&lt;p&gt;App.js&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&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="s1"&gt;app-root&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;RouteList&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;RouteList.js&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RouteList&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;render&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="o"&gt;&amp;lt;&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;Fragment&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Header&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&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="s2"&gt;app-container&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="o"&gt;&amp;lt;&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;Suspense&lt;/span&gt; &lt;span class="nx"&gt;fallback&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;lt;&lt;/span&gt;&lt;span class="nx"&gt;span&lt;/span&gt; &lt;span class="o"&gt;/&amp;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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="nx"&gt;exact&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&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="nx"&gt;render&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Category&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="sr"&gt;/&amp;gt;} /&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nx"&gt;etc&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;/React.Suspense&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/React.Fragment&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When React is ready and in RouteList we delete the &lt;code&gt;app-container&lt;/code&gt; and &lt;code&gt;app-shell&lt;/code&gt; divs from Step one and let our &lt;code&gt;&amp;lt;Category /&amp;gt;&lt;/code&gt; component get again the HTML by making a request to the JSON API and render it.&lt;/p&gt;

&lt;p&gt;Something 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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RouteList&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;componentDidMount&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;elem&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="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-shell&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;elem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parentNode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;elem&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;elem&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="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-container&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;elem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parentNode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;elem&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;render&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="o"&gt;&amp;lt;&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;Fragment&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Header&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&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="s2"&gt;app-container&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="o"&gt;&amp;lt;&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;Suspense&lt;/span&gt; &lt;span class="nx"&gt;fallback&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;lt;&lt;/span&gt;&lt;span class="nx"&gt;span&lt;/span&gt; &lt;span class="o"&gt;/&amp;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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="nx"&gt;exact&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&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="nx"&gt;render&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Category&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="sr"&gt;/&amp;gt;} /&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nx"&gt;etc&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;/React.Suspense&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/React.Fragment&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we have our first Partial SSR!&lt;/p&gt;

&lt;h3&gt;
  
  
  Step Three
&lt;/h3&gt;

&lt;p&gt;The second step makes an additional request to get the same content that it's deleting, so we have changed the HTML returned from the first request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    Some meta, CSS, scripts, third-parties etc.
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"app-shell"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Static Header&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"app-loader"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;appContainer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;html&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;div id="app-container"&amp;gt;Content between header and footer&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;appLoaderElement&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="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-loader&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;appLoaderElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;decodeURIComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;appContainer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"app"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"OUR_INITIAL_REACT_BUNDLES"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then again in RouteList component, we delete the &lt;strong&gt;app-loader&lt;/strong&gt; div but the &lt;code&gt;&amp;lt;Category /&amp;gt;&lt;/code&gt; component will check if &lt;strong&gt;appContainer&lt;/strong&gt; is not empty and get the HTML from it and won't make an additional request. (Yup, we know, it is ugly.)&lt;/p&gt;

&lt;p&gt;The result is this timeline:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fey5jtp5tke4hbmmujcgg.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fey5jtp5tke4hbmmujcgg.jpg" alt="react partial SSR white gap"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  (Final) Step Four
&lt;/h3&gt;

&lt;p&gt;That white gap that you see above is ruining all our previous efforts, the SpeedIndex and LCP won't improve because of this gap and, more importantly, it's really awful for the user.&lt;/p&gt;

&lt;p&gt;This is happening because we use &lt;code&gt;React.lazy()&lt;/code&gt; and &lt;code&gt;&amp;lt;Suspense&amp;gt;&lt;/code&gt; on routing level for components that are not &lt;code&gt;&amp;lt;Header&amp;gt;&lt;/code&gt; and we are passing an empty &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt; to the &lt;code&gt;fallback&lt;/code&gt; attribute, so while React is waiting, the &lt;code&gt;&amp;lt;Category /&amp;gt;&lt;/code&gt; to load, it shows empty &lt;code&gt;span&lt;/code&gt; below the &lt;code&gt;Header&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&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;Fragment&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Header&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&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="s2"&gt;app-container&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&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;Suspense&lt;/span&gt; &lt;span class="nx"&gt;fallback&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;lt;&lt;/span&gt;&lt;span class="nx"&gt;span&lt;/span&gt; &lt;span class="o"&gt;/&amp;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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="nx"&gt;exact&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&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="nx"&gt;render&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Category&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="sr"&gt;/&amp;gt;} /&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;etc&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;/React.Suspense&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/React.Fragment&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To fix the gap we pass the JS global variable containing the HTML as the &lt;code&gt;fallback&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&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;Fragment&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Header&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&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="s2"&gt;app-container&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&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;Suspense&lt;/span&gt; &lt;span class="nx"&gt;fallback&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;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;dangerouslySetInnerHTML&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;__html&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;decodeURIComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;appContainer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;html&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="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="nx"&gt;exact&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&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="nx"&gt;render&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Category&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="sr"&gt;/&amp;gt;} /&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;etc&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;/React.Suspense&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/React.Fragment&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml" rel="noopener noreferrer"&gt;dangerouslySetInnerHTML&lt;/a&gt; is not a good practice at all, it can expose you to cross-site-scripting attack but we don't have any other choice except to live with it for now :)&lt;/p&gt;

&lt;p&gt;And the result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Felwq78xoiqm9lg5cgsgd.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Felwq78xoiqm9lg5cgsgd.jpg" alt="react partial SSR without white gap"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance improvements
&lt;/h2&gt;

&lt;p&gt;While the above code is not the prettiest one, our performance improvements are significant for Homepage and Category Landing Pages:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fzq690us3lfpmupe7u5ow.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fzq690us3lfpmupe7u5ow.png" alt="FMP and FCP results"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F2mhvy6luwbs70v92k0bz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F2mhvy6luwbs70v92k0bz.png" alt="Lighthouse results"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you for reading this long article, I will be happy if you have any comments or suggestions :)&lt;/p&gt;

</description>
      <category>ssr</category>
      <category>sfcc</category>
      <category>react</category>
      <category>javascript</category>
    </item>
    <item>
      <title>The dimensions of an img tag</title>
      <dc:creator>Lyubomir Angelov</dc:creator>
      <pubDate>Sat, 03 Aug 2019 20:40:10 +0000</pubDate>
      <link>https://dev.to/lyubomir/the-dimensions-of-an-img-tag-2fk8</link>
      <guid>https://dev.to/lyubomir/the-dimensions-of-an-img-tag-2fk8</guid>
      <description>&lt;p&gt;The other day in the team we were playing with one simple bug.&lt;br&gt;
The bug was why the Intersection Observer is loading almost all images on the page which are not in the viewport?&lt;/p&gt;

&lt;p&gt;It was simple, the &lt;strong&gt;src&lt;/strong&gt; attribute was empty:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;    &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="na"&gt;data-src=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"lazy-load"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Some title"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This was making all images on the page to render close one to another with the size of the defined line-height. So almost all images were initially in the viewport when the Intersection Observer was triggered.&lt;/p&gt;

&lt;p&gt;Ok, we got the issue, so let's define some dimensions to the img tags:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;    &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="na"&gt;data-src=&lt;/span&gt;&lt;span class="s"&gt;"https://URL_TO_IMAGE"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"lazy-load"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"200"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"200"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Some title"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Ahh, still the images are only with the size of the line-height and still almost all are visible...&lt;/p&gt;

&lt;p&gt;Then after adding some CSS to try to set the size "min-height" and etc. we were not able to set the proper dimensions.&lt;/p&gt;

&lt;p&gt;Suddenly someone remembers it if you don't have some URL to image in the &lt;strong&gt;src&lt;/strong&gt; attribute, the &lt;strong&gt;Width and Height&lt;/strong&gt; won't be used and the tag won't be that size.&lt;/p&gt;

&lt;p&gt;The simple solution was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;    &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://URL_TO_1x1_PIXEL_IMAGE"&lt;/span&gt; &lt;span class="na"&gt;data-src=&lt;/span&gt;&lt;span class="s"&gt;"https://URL_TO_REAL_IMAGE"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"lazy-load"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"200"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"200"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Some title"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Yes, if you set 1x1 image in the src, the height and width will be applied and the Intersection Observer will do his job properly.&lt;/p&gt;

&lt;p&gt;Most of the articles for Image lazy loading are not mentioning that you need src attribute filled, it is better for UI and for the lazy load.&lt;/p&gt;

</description>
      <category>html</category>
      <category>images</category>
      <category>htmlparsing</category>
    </item>
    <item>
      <title>When to use browser push notifications</title>
      <dc:creator>Lyubomir Angelov</dc:creator>
      <pubDate>Thu, 09 May 2019 17:57:16 +0000</pubDate>
      <link>https://dev.to/lyubomir/when-to-use-browser-push-notifications-32al</link>
      <guid>https://dev.to/lyubomir/when-to-use-browser-push-notifications-32al</guid>
      <description>&lt;p&gt;Push notifications are a really nice feature, you can trigger a notification to the user device with any text that you want with title, image, body and it even can make the mobile device to vibrate (depends on the browser) when receiving it.&lt;/p&gt;

&lt;p&gt;This is a really cool way to get the user attention when you have promotions, forgotten baskets full of products or you have published something new.&lt;/p&gt;

&lt;p&gt;In order to use &lt;strong&gt;push notifications&lt;/strong&gt; you have first to ask the users for permission, this is the small pop-up next to URL bar with buttons "allow" and "block":&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OA4XdR72--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/n8o7o56u00q5wf5uqicz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OA4XdR72--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/n8o7o56u00q5wf5uqicz.png" alt="push notification request"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How the majority of the websites are using this feature?&lt;/p&gt;

&lt;p&gt;They make this pop-up appear immediately when you visit their site, you have no Idea what is this, for what you have to subscribe and for god sake I didn't do anything, what is this pop-up for? Ok, block it!&lt;/p&gt;

&lt;p&gt;Most of the users are clicking &lt;strong&gt;block&lt;/strong&gt; because you don't ask for permissions on the right time and you are just throwing away the chance to convert this user.&lt;/p&gt;

&lt;p&gt;Instead of triggering it on initial loading, please do it on user action, for example after he read the article put a button to ask if the user wants to subscribe for more news. Or on saving an item to his wish list, you can ask him if he wants to subscribe to notifications in order to receive information when this item will be available.&lt;/p&gt;

&lt;p&gt;Here you can find more information about what is possible and how to install it in &lt;a href="https://developers.google.com/web/ilt/pwa/introduction-to-push-notifications"&gt;Google Dev website&lt;/a&gt;&lt;/p&gt;

</description>
      <category>notifications</category>
      <category>javascript</category>
      <category>browsers</category>
    </item>
    <item>
      <title>Why you should care when you are sending the notifications?</title>
      <dc:creator>Lyubomir Angelov</dc:creator>
      <pubDate>Wed, 17 Apr 2019 20:42:22 +0000</pubDate>
      <link>https://dev.to/lyubomir/why-you-should-care-when-you-are-sending-the-notifications-3leh</link>
      <guid>https://dev.to/lyubomir/why-you-should-care-when-you-are-sending-the-notifications-3leh</guid>
      <description>&lt;p&gt;What I observe on vast of the majority of the news websites and not only them, is that they are sending all kind of notifications (Apps, Twitter, Emails etc.) when possible, 10 AM, 2 PM, 11 PM, 1 AM.&lt;br&gt;
That's not right, know your audience, look at your analytics, check most valuable hours, think when &lt;strong&gt;you&lt;/strong&gt; want those notifications, ask friends etc.&lt;/p&gt;

&lt;p&gt;If you are not thinking about that, not knowing your audience, it is time to start doing that.&lt;/p&gt;

&lt;p&gt;Why? Because you can disappoint your users, for example when you publish something to Twitter or you send an email at 1 AM.&lt;br&gt;
Believe me, users will stop their subscription to your Twitter tweets or will unsubscribe from your newsletter and they will not read. You are not leaving a good impression like that.&lt;/p&gt;

&lt;p&gt;In general try to think as a real customer, ask friends and make A/B tests.&lt;br&gt;
Send one email, ok at 1 AM to &lt;strong&gt;half&lt;/strong&gt; of your users, then check how many of them opened it, read it and clicked on the links in, then do the same with the other HALF but in a different time, for example, 9 PM.&lt;/p&gt;

&lt;p&gt;All big websites are doing that, why you are not doing it?&lt;/p&gt;

</description>
      <category>notifications</category>
      <category>twitter</category>
      <category>newsletters</category>
    </item>
    <item>
      <title>How to send emails that are not marked as SPAM?</title>
      <dc:creator>Lyubomir Angelov</dc:creator>
      <pubDate>Sun, 14 Apr 2019 16:05:13 +0000</pubDate>
      <link>https://dev.to/lyubomir/how-to-send-emails-that-are-not-marked-as-spam-5egj</link>
      <guid>https://dev.to/lyubomir/how-to-send-emails-that-are-not-marked-as-spam-5egj</guid>
      <description>&lt;p&gt;Recently I helped one company to prevent common emails for registrations and etc. to be marked as SPAM automatically from users mailboxes.&lt;/p&gt;

&lt;p&gt;When you are using third-party service like MailChimp and with your own domain to send your emails you have to do several steps to prove all mailboxes that you are you and that you are not some spammer.&lt;/p&gt;

&lt;p&gt;To do that all services will have instructions on how to set DKIM and SPF records to your domain name that you will be using for sending the email. Usually, I create a subdomain like &lt;code&gt;mail.example.com&lt;/code&gt;, then we have to add those DKIM and SPF records provided by the service.&lt;/p&gt;

&lt;p&gt;They represent texts which tell to mailboxes that you are using different service for sending emails then your own server&lt;/p&gt;

&lt;p&gt;MailChimp examples are:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;    • DKIM:
    Create a CNAME record &lt;span class="k"&gt;for &lt;/span&gt;k1._domainkey.yoursite.com with this value: dkim.mcsv.net.

    • SPF:
    Create a TXT record &lt;span class="k"&gt;for &lt;/span&gt;yoursite.com with this value: &lt;span class="nv"&gt;v&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;spf1 include:servers.mcsv.net ?all
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you follow all the instructions of the service you will have a subdomain with DKIM and SPF records and then you should be ready to send all your newsletters and common emails with no problems.&lt;/p&gt;

&lt;p&gt;Despite the above configurations, mailboxes like Gmail might mark your emails as SPAM. Why? Because there is one last step that you have to configure when sending emails.&lt;br&gt;
Your &lt;strong&gt;From&lt;/strong&gt; record have to match the sender, otherwise, it is not trusted.&lt;/p&gt;

&lt;p&gt;Let's give an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;    Received: by mail.example.com
    From: info@example.com
    To: someuseremail@gmail.com
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In that example, the domain that the service is using for sending the email is different from the domain that is used in the &lt;em&gt;From&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;But if you change that to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;    Received: by mail.example.com
    From: yourfriends@mail.example.com
    To: someuseremail@gmail.com
    Reply-to: info@example.com
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Emails won't be marked as spam because sender domain and email &lt;em&gt;From&lt;/em&gt; domain are the same.&lt;br&gt;
With &lt;strong&gt;Reply-to&lt;/strong&gt; when the user wants to reply to our email, he will write not to &lt;em&gt;&lt;a href="mailto:yourfriends@mail.example.com"&gt;yourfriends@mail.example.com&lt;/a&gt;&lt;/em&gt; but to what we defined in &lt;em&gt;Reply-to&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Hope that will help someone with his emails. :)&lt;/p&gt;

</description>
      <category>email</category>
      <category>mailchimp</category>
      <category>mailgun</category>
    </item>
    <item>
      <title>Apache - Rewrite all URIs to a single file</title>
      <dc:creator>Lyubomir Angelov</dc:creator>
      <pubDate>Thu, 11 Apr 2019 17:01:07 +0000</pubDate>
      <link>https://dev.to/lyubomir/apache-rewrite-all-uris-to-a-single-file-1mcb</link>
      <guid>https://dev.to/lyubomir/apache-rewrite-all-uris-to-a-single-file-1mcb</guid>
      <description>&lt;p&gt;This week I had to help a friend with his new small ReacJS website running on Apache.&lt;/p&gt;

&lt;p&gt;His problem was that URIs which does not exist the Apache was returning as 404 pages, he needed a common rule used by a lot of PHP frameworks, Rewrite all URIs which are not Files or Directories to &lt;strong&gt;/index.html&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Example URL &lt;code&gt;www.example.com/myprofile&lt;/code&gt; to actually load &lt;code&gt;www.example.com/index.html&lt;/code&gt; and let the ReactJS route do his work and show what it needs.&lt;/p&gt;

&lt;p&gt;In that case, you might write something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;
    RewriteEngine on

    RewriteCond %&lt;span class="o"&gt;{&lt;/span&gt;REQUEST_FILENAME&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nt"&gt;-f&lt;/span&gt;
    RewriteCond %&lt;span class="o"&gt;{&lt;/span&gt;REQUEST_FILENAME&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nt"&gt;-d&lt;/span&gt;
    RewriteRule ^ index.html &lt;span class="o"&gt;[&lt;/span&gt;L]

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;What is this doing, it will check the URI either exists as a file or is a directory if it is NOT, it will call &lt;strong&gt;index.html&lt;/strong&gt;. The [L] means that this will be the LAST match and will stop there, will not continue if we have other rules below that.&lt;/p&gt;

&lt;p&gt;This is code is ok, not so simple and you can mess up the conditions, for example, I have seen a lot of [OR] next to &lt;code&gt;RewriteCond %{REQUEST_FILENAME} !-f [OR]&lt;/code&gt; which will not work in our case above.&lt;/p&gt;

&lt;p&gt;If you need this simple Rewrite rule, you might use Apache command available after &lt;strong&gt;2.2.16 version&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;
    FallbackResource /index.html

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This will do the same as the above 4 lines if the URI is not found on the server, ie. not a File or a Dir, it will load to &lt;strong&gt;/index.html&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This command is not part of &lt;strong&gt;mod_rewrite&lt;/strong&gt;, but of &lt;strong&gt;mod_dir&lt;/strong&gt;, if you don't have it enabled, run &lt;code&gt;sudo a2enmod dir&lt;/code&gt; and restart the Apache.&lt;/p&gt;

</description>
      <category>apache</category>
      <category>htaccess</category>
    </item>
    <item>
      <title>JavaScript interview question that you have to know</title>
      <dc:creator>Lyubomir Angelov</dc:creator>
      <pubDate>Tue, 02 Apr 2019 21:46:11 +0000</pubDate>
      <link>https://dev.to/lyubomir/javascript-interview-question-that-you-have-to-know-17f3</link>
      <guid>https://dev.to/lyubomir/javascript-interview-question-that-you-have-to-know-17f3</guid>
      <description>&lt;p&gt;What is the difference between &lt;em&gt;var&lt;/em&gt;, &lt;em&gt;let&lt;/em&gt; and &lt;em&gt;const&lt;/em&gt; in JavaScript?&lt;/p&gt;

&lt;p&gt;It happened to me with few junior JavaScript and few PHP mid/senior developers that they didn't know the answer and the bad side is that all of them had a decent experience in projects with JavaScript.&lt;/p&gt;

&lt;p&gt;The difference is huge, Scope, Declaration and Re-declaration.&lt;br&gt;
I was going to explain in details but found a very good article here that have all the details &lt;a href="https://dev.to/sarah_chima/var-let-and-const--whats-the-difference-69e"&gt;Var, let and const- what's the difference?&lt;/a&gt;&lt;/p&gt;

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