<?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: Mahmoud Atwa</title>
    <description>The latest articles on DEV Community by Mahmoud Atwa (@3atwaa).</description>
    <link>https://dev.to/3atwaa</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%2F56633%2F6359ba0b-e092-41b2-bb46-bd6c23452e65.png</url>
      <title>DEV Community: Mahmoud Atwa</title>
      <link>https://dev.to/3atwaa</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/3atwaa"/>
    <language>en</language>
    <item>
      <title>Ionic SSR with React: An adventure</title>
      <dc:creator>Mahmoud Atwa</dc:creator>
      <pubDate>Mon, 28 Mar 2022 17:19:50 +0000</pubDate>
      <link>https://dev.to/3atwaa/ionic-ssr-with-react-an-adventure-1b3f</link>
      <guid>https://dev.to/3atwaa/ionic-ssr-with-react-an-adventure-1b3f</guid>
      <description>&lt;h2&gt;
  
  
  Why
&lt;/h2&gt;

&lt;p&gt;React is a great library for UI and makes it easier to build UIs and greatly reduces the development time. Ionic is also a great library for developing cross-platform hybrid apps. Ionic can be easily integrated with React. As a matter of fact React actually is officially supported by the Ionic team.&lt;/p&gt;

&lt;h3&gt;
  
  
  It’s not all flowers and roses.
&lt;/h3&gt;

&lt;p&gt;But there’s a catch; React is a JS library, where you write your UI in JS. Which means that HTML is generated on the browser. This leads to a less than ideal experience for crawlers that index your website.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Adventures
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Approach 1: using ReactDOMServer in a nodejs environment
&lt;/h3&gt;

&lt;p&gt;A standard way to enable SSR for a React.js app is to just use &lt;code&gt;ReactDOMServer&lt;/code&gt; on the server and replace the render() method with &lt;code&gt;hydrate()&lt;/code&gt; in the client so that the application will not re-render (the already rendered components) when it is served to the browser.&lt;/p&gt;

&lt;p&gt;But there’s a problem, Ionic components use stencil.js which uses web components which is not supported by &lt;code&gt;ReactDOMServer&lt;/code&gt;. So we need another solution.&lt;/p&gt;

&lt;p&gt;Example Snippet:&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;express&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ReactDOMServer&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-dom/server&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./App&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;static&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;STATIC_ASSETS_DIR&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;*&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="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;appHtml&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ReactDOMServer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;renderToString&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;App&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// Assume that we have an html template&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;htmlTemplate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^_^__APP_SHOULD_BE_HERE__^_^&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;appHtml&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;send&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Approach 2: using Next.js
&lt;/h3&gt;

&lt;p&gt;In most cases, this approach will work. It works like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Instead of using &lt;code&gt;@ionic/react&lt;/code&gt;, use &lt;code&gt;@ionic/core&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Instead of using React components (e.g. &lt;code&gt;&amp;lt;IonHeader /&amp;gt;&lt;/code&gt;) use web components (e.g. &lt;code&gt;&amp;lt;ion-header /&amp;gt;&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Initialize web components by calling &lt;code&gt;defineCustomeElements&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;And that’s it (assuming you’ve configured your project to use Next.js). For a starter repo, check this repo &lt;a href="https://github.com/adaept/moonbase-vercel-ionic"&gt;moonbase-vercel-ionic&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However our codebase at the time had some components that are not supported in &lt;code&gt;@ionic/core&lt;/code&gt;. So we couldn't use this approach.&lt;/p&gt;

&lt;h3&gt;
  
  
  Approach 3: Bringing a gun to a knife fight
&lt;/h3&gt;

&lt;p&gt;The last approach which will work with anything is to use a browser. A browser supports web components, is not limited to a certain library (e.g. react, angular, or vue). So, I used puppeteer which is a library that provides a Node.js API to control chromium &amp;amp; firefox.&lt;/p&gt;

&lt;p&gt;So our final workflow is as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The client sends a GET request to the server&lt;/li&gt;
&lt;li&gt;The server checks if the needed resource is a page or just a static asset.&lt;/li&gt;
&lt;li&gt;If it’s a static asset serve it with express and let Nginx add cache headers along with compressing the file.
Otherwise, check if the page is already rendered and in the cache.&lt;/li&gt;
&lt;li&gt;If it’s in the cache serve it as a normal static asset.&lt;/li&gt;
&lt;li&gt;Otherwise, run Puppeteer load the page URI.&lt;/li&gt;
&lt;li&gt;Wait for the page to be loaded.&lt;/li&gt;
&lt;li&gt;Grab the page’s HTML from Puppeteer and save it in the cache.&lt;/li&gt;
&lt;li&gt;Send the HTML.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This can be written in Node.js as the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Static files handler&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;*.*&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="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sendFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="c1"&gt;// Dynamic Page handler&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&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;}&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;puppeteer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;newPage&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;goto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`http://localhost:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;CLIENT_PORT&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;waitUntil&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;networkidle0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&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;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;send&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="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&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="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SERVER_PORT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// React Server&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;static&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;STATIC_ASSETS_DIR&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;*&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="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sendFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;index.html&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;CLIENT_PORT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that we’ve used two servers in this example, one where the client (i.e. the user's browser) sends requests to and handles cache as well as serving static assets while the other is for Puppeteer to connect to, to load the application.&lt;/p&gt;

&lt;p&gt;This is not the best solution since it'll requires heavy infrastructure for high traffic websites.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This article was originally posted on my own blog so if you find that it has been copied, don't worry I copied it from my self.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>ionic</category>
      <category>ssr</category>
      <category>puppeteer</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>MPADiff, make your MPA an SPA with a single LOC.</title>
      <dc:creator>Mahmoud Atwa</dc:creator>
      <pubDate>Thu, 29 Jul 2021 04:47:46 +0000</pubDate>
      <link>https://dev.to/3atwaa/mpadiff-make-your-mpa-an-spa-with-a-single-loc-1n9i</link>
      <guid>https://dev.to/3atwaa/mpadiff-make-your-mpa-an-spa-with-a-single-loc-1n9i</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Even though I write React based apps on a daily basis. One thing that I always think about is why does everyone use SPAs today. I get it, it's easier to develop, reduces development time (business people like this) &amp;amp; it has a better UX (in my opinion) when it's done right. &lt;/p&gt;

&lt;p&gt;But let's face it, it's far easier to write a Node.JS backend with handlebars for templates than it is to write a react application.&lt;/p&gt;

&lt;p&gt;Below are the pros &amp;amp; cons of using an SPA approach vs using an MPA approach.&lt;/p&gt;

&lt;h2&gt;
  
  
  MPA vs SPA
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;SPA&lt;/th&gt;
&lt;th&gt;MPA&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;SEO&lt;/td&gt;
&lt;td&gt;Nope&lt;/td&gt;
&lt;td&gt;Already Set up&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Page Load&lt;/td&gt;
&lt;td&gt;Good for simple apps, But not for complicated apps without SSR&lt;/td&gt;
&lt;td&gt;Good if you have good infra&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rendering Perf.&lt;/td&gt;
&lt;td&gt;Big No!&lt;/td&gt;
&lt;td&gt;Good&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Development Time&lt;/td&gt;
&lt;td&gt;Better for complicated UI (Assuming back-end is already made)&lt;/td&gt;
&lt;td&gt;Good for simple UIs (aka 90% of the cases)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UX&lt;/td&gt;
&lt;td&gt;Website doesn't reload on navigation&lt;/td&gt;
&lt;td&gt;Reloads on navigation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The previous comparison is not full but gives us an insight to why SPAs are becoming more and more popular.&lt;/p&gt;

&lt;p&gt;Now, the question is this. Can we make a multi-page application behave as an SPA, while still having the benefits of an MPA without much time? The answer is Yes!&lt;/p&gt;

&lt;h2&gt;
  
  
  MPADiff
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;MPADiff&lt;/code&gt; is JavaScript library written in TypeScript that makes an MPA look &amp;amp; feel like an SPA while still being an MPA it self.&lt;/p&gt;

&lt;p&gt;It works by changing the default behavior of &lt;code&gt;a&lt;/code&gt; tags. Once a link is clicked, the HTML of such link is fetched using a &lt;code&gt;GET&lt;/code&gt; request, The &lt;code&gt;body&lt;/code&gt; element is swapped &amp;amp; the &lt;code&gt;head&lt;/code&gt; element is updated (not replaced).&lt;/p&gt;

&lt;p&gt;This approach prevents reloading CSS that was already loaded.&lt;/p&gt;

&lt;p&gt;By default, the library eagerly loads link elements (i.e. before the user clicks on them). This makes navigation between different pages instantaneous, but puts an extra load on your infrastructure.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Yarn
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;yarn add mpadiff&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  npm
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;npm i mpadiff -S&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Self host
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;script src="build/index.js"&amp;gt;&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;code&gt;&amp;lt;script src="https://unpkg.com/mpadiff"&amp;gt;&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;MPADiff&lt;/code&gt; can be used &amp;amp; enabled with a single line of code, just like this:&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;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://unpkg.com/mpadiff"&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;script&amp;gt;&lt;/span&gt;
&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MPADiff&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;loaderDelay&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;loaderElement&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;eagerLoading&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="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Options
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Option&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Explanation&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;loaderDelay&lt;/td&gt;
&lt;td&gt;number (ms)&lt;/td&gt;
&lt;td&gt;number of milliseconds to wait before hiding the loader (in case of lazy loading)&lt;/td&gt;
&lt;td&gt;500&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;eagerLoading&lt;/td&gt;
&lt;td&gt;boolean&lt;/td&gt;
&lt;td&gt;Whether the links should be loaded once they appear or load them only when the user clicks on them.&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;loaderElement&lt;/td&gt;
&lt;td&gt;HTMLElement/Node/undefined&lt;/td&gt;
&lt;td&gt;The element that will be used when the contents of a link is still loading and the user has clicked on it&lt;/td&gt;
&lt;td&gt;undefined&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  Notes
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;MPADiff&lt;/code&gt; is still in its early stages, use it carefully.&lt;/li&gt;
&lt;li&gt;For bugs, issues &amp;amp; Feature requests, report to the github &lt;a href="https://github.com/atwamahmoud/MPADiff/issues" rel="noopener noreferrer"&gt;issues&lt;/a&gt; page.&lt;/li&gt;
&lt;li&gt;Full API reference: &lt;a href="https://github.com/atwamahmoud/MPADiff" rel="noopener noreferrer"&gt;https://github.com/atwamahmoud/MPADiff&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Having any thoughts? Add a comment below.&lt;/li&gt;
&lt;/ol&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/atwamahmoud" rel="noopener noreferrer"&gt;
        atwamahmoud
      &lt;/a&gt; / &lt;a href="https://github.com/atwamahmoud/MPADiff" rel="noopener noreferrer"&gt;
        MPADiff
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Get the benefits of an SPA with a single line of code. 
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt; &lt;div&gt;
  &lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;MPADiff&lt;/h2&gt;
&lt;/div&gt;


&lt;blockquote&gt;Minimal Library to mimic Single page apps. behaviour in Multi page apps.&lt;/blockquote&gt;
&lt;br&gt;
 &lt;/div&gt;

&lt;p&gt;&lt;a href="https://github.com/atwamahmoud/MPADiff/actions/workflows/main.yml" rel="noopener noreferrer"&gt;&lt;img src="https://github.com/atwamahmoud/MPADiff/actions/workflows/main.yml/badge.svg" alt="Build"&gt;&lt;/a&gt;
&lt;a href="https://github.com/atwamahmoud/MPADiff/actions/workflows/publish.yml" rel="noopener noreferrer"&gt;&lt;img src="https://github.com/atwamahmoud/MPADiff/actions/workflows/publish.yml/badge.svg" alt="Publish"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🚀 What, Why &amp;amp; How&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;MPADiff&lt;/code&gt; is a minimal JavaScript library written in TypeScript that prevents your website to reload when the user navigates to another page. This is the default behaviour for SPAs written React, Angulat, Vue &amp;amp; other SPA frameworks/libraries.&lt;/p&gt;
&lt;p&gt;The main difference here is that &lt;code&gt;MPADiff&lt;/code&gt; provides this functionality to multi page applications written in PHP, Node.js, ASP, or any other language/framework.&lt;/p&gt;
&lt;p&gt;It works by sending a &lt;code&gt;GET&lt;/code&gt; request to URIs of links to fetch HTML. Once the user clicks on such link, the &lt;code&gt;head&lt;/code&gt; element is updated (without reloading any CSS) &amp;amp; the &lt;code&gt;body&lt;/code&gt; element is swaped. Both eager &amp;amp; lazy loading of HTML documents are supported and can be configured accoeding to your needs.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Before&lt;/h3&gt;
&lt;/div&gt;

  
    
    

    &lt;span class="m-1"&gt;Before.mov&lt;/span&gt;
    
  

  

  


&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;After&lt;/h3&gt;

&lt;/div&gt;

  
    
    

    &lt;span class="m-1"&gt;after.mov&lt;/span&gt;
    
  

  

  


&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;⭐️ Features&lt;/h2&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Custom loaders&lt;/li&gt;
&lt;li&gt;Eager &amp;amp; Lazy Loading&lt;/li&gt;
&lt;li&gt;Custom delays&lt;/li&gt;
&lt;li&gt;Doesn't reload CSS.&lt;/li&gt;
&lt;li&gt;3kb…&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/atwamahmoud/MPADiff" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>mpa</category>
      <category>spa</category>
    </item>
  </channel>
</rss>
