<?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: asaf g</title>
    <description>The latest articles on DEV Community by asaf g (@asaf_g6).</description>
    <link>https://dev.to/asaf_g6</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%2F456495%2Fffebca09-435d-4ef6-bc0b-13f40bc86878.jpg</url>
      <title>DEV Community: asaf g</title>
      <link>https://dev.to/asaf_g6</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/asaf_g6"/>
    <language>en</language>
    <item>
      <title>Long pollng with nodejs</title>
      <dc:creator>asaf g</dc:creator>
      <pubDate>Sun, 01 Aug 2021 14:51:59 +0000</pubDate>
      <link>https://dev.to/asaf_g6/long-pollng-with-nodejs-jb8</link>
      <guid>https://dev.to/asaf_g6/long-pollng-with-nodejs-jb8</guid>
      <description>&lt;p&gt;Long polling is just like short polling, but with a bigger pole! No, not really!&lt;br&gt;&lt;br&gt;
Sometimes, we need to get updates from a server, but we don't know if the resource that we're after is there at the moment.&lt;br&gt;&lt;br&gt;
Examples for that can be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Checking if a file exists on a server&lt;/li&gt;
&lt;li&gt;Waiting for some field to be updated&lt;/li&gt;
&lt;li&gt;Checking for new messages on a chat app
I bet you can find more similar scenarios.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, what are your options today in our http driven world?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Short polling &lt;/li&gt;
&lt;li&gt;Using something like Server Sent Events (SSE)&lt;/li&gt;
&lt;li&gt;Websockets (which is actually tcp)&lt;/li&gt;
&lt;li&gt;Long polling&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Of course if you don't limit yourself to http, you can use GRPC, a PUB/SUB server or roll your own with tcp.&lt;/p&gt;
&lt;h2&gt;
  
  
  So what is long polling anyway?
&lt;/h2&gt;

&lt;p&gt;Long polling is a technique to achieve a continuous connection between a server and a client.&lt;/p&gt;
&lt;h3&gt;
  
  
  The server:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Receives a request&lt;/li&gt;
&lt;li&gt;Checks if it has data to return to the client&lt;/li&gt;
&lt;li&gt;If it has data, it returns it in the response&lt;/li&gt;
&lt;li&gt;If it doesn't have data, it waits and checks if the data is available repeatedly (polling)&lt;/li&gt;
&lt;li&gt;After a certain time has passed the server "gives up" and returns an empty response&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  The client:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Send the requests&lt;/li&gt;
&lt;li&gt;Waits&lt;/li&gt;
&lt;li&gt;Receives the response&lt;/li&gt;
&lt;li&gt;Checks for data (and if there is, does something with it)&lt;/li&gt;
&lt;li&gt;Repeats&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  How is long polling better than just polling?
&lt;/h2&gt;

&lt;p&gt;"Just polling" or short polling can only get results at the interval it polls. &lt;br&gt;
So, in short polling this is how it goes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The client sends a request&lt;/li&gt;
&lt;li&gt;The server immediately return a response&lt;/li&gt;
&lt;li&gt;The client checks for data (and do something if it's available)&lt;/li&gt;
&lt;li&gt;The client sleeps an "interval" and repeats&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The connection here is not continuous. If our interval is 5 seconds, it means we actually get results &lt;strong&gt;only&lt;/strong&gt; every 5 seconds.&lt;br&gt;
Our result in this case can be 4.99 seconds old. &lt;br&gt;
With long polling on the other hand, we get the result almost immediately. I say almost, because there's the time between getting the response and sending another request. &lt;br&gt;
Let's assume that, that time is 100 milliseconds plus 200 for latency. In the worst case your result can be 300 milliseconds old. This is for sure a lot more "real time"-ish.&lt;/p&gt;

&lt;p&gt;Alright! I assume that you are now convinced. Let's move on to the implementation.&lt;/p&gt;
&lt;h2&gt;
  
  
  The client
&lt;/h2&gt;

&lt;p&gt;This is the easiest part, just loop and make the requests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;client.js&lt;/strong&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;'&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="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&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="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="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;hadErr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;requesting...&lt;/span&gt;&lt;span class="dl"&gt;"&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;axios&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="s1"&gt;http://127.0.0.1:8080&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="na"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10000&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// This will sometime be empty&lt;/span&gt;
            &lt;span class="p"&gt;})&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;People we have an error!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="nx"&gt;hadErr&lt;/span&gt; &lt;span class="o"&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="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hadErr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// break out of the loop in case of error&lt;/span&gt;
            &lt;span class="c1"&gt;// maybe in a real live situation we could do something here*&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;


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

&lt;/div&gt;



&lt;p&gt;This code is pretty simple, loop forever and print whatever you got.&lt;br&gt;&lt;br&gt;
Note that, the timeout is 10 seconds which should be more time than the time the server will wait (server returns after 5 seconds if there's no data).&lt;/p&gt;
&lt;h2&gt;
  
  
  The server
&lt;/h2&gt;

&lt;p&gt;Now, this is where the magic happens.&lt;br&gt;&lt;br&gt;
Let's start with our "resource". I have implemented a very generic "one time" event emitter. &lt;br&gt;
The calling code can register to the "event", and when the event happens it is automatically unregistered.&lt;br&gt;
You'll see how I'm using it in a sec.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;event.js&lt;/strong&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="c1"&gt;// A very generic event emitter&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;EventEmitter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nx"&gt;listeners&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

    &lt;span class="nx"&gt;fire&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&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;var&lt;/span&gt; &lt;span class="nx"&gt;k&lt;/span&gt; &lt;span class="k"&gt;in&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;listeners&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;listener&lt;/span&gt; &lt;span class="o"&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;listeners&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;k&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;unregister&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// unregister this listener&lt;/span&gt;
            &lt;span class="nx"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&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="nx"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listeners&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Register&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;unregister&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&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="k"&gt;delete&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;listeners&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;id&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="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;EventEmitter&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


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

&lt;/div&gt;



&lt;p&gt;This is pretty standard. You can check out another implementation of it &lt;a href="https://www.dofactory.com/javascript/design-patterns/observer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I'm using express.js for the server, it's easy enough and take cares of most of the stuff. Let's start with a simplified version of our server and continue working on from there.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;index.js&lt;/strong&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&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;EventEmitter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./event.js&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="c1"&gt;// create an instance of our event emitter&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;eventEmitter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;EventEmitter&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="s1"&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;function&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="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;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&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;end&lt;/span&gt;&lt;span class="p"&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;server&lt;/span&gt; &lt;span class="o"&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="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&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;host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Example app listening at http://%s:%s&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;port&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;Ok, so this is pretty standard also. Taken from some express.js example or something. What it does is basically return a 200 OK header and closes the request.&lt;/p&gt;

&lt;p&gt;Let's add code for our event emitter to actually emit events.&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;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ms&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="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;   


&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&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="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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;waitTimeMS&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="nx"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10000&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;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;waitTimeMS&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;eventEmitter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fire&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;waitTimeMS&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;The &lt;code&gt;main&lt;/code&gt; function is looping forever, sleeping a random amount of milliseconds (0 - 10000) and calling &lt;code&gt;fire&lt;/code&gt; with an object.&lt;br&gt;
Great, every few seconds an event will be fired. Let's see how we use that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="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="s1"&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;function&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="p"&gt;{&lt;/span&gt;
   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// milliseconds of now will be fine for our case&lt;/span&gt;
   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;event&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&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;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;201&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;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
   &lt;span class="p"&gt;};&lt;/span&gt;
   &lt;span class="nx"&gt;eventEmitter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handler&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, we register to the event with the &lt;code&gt;handler&lt;/code&gt; function. When the loop in the main function will call the &lt;code&gt;fire&lt;/code&gt; function, this function will run and output the event to the client along with 201 status code.&lt;br&gt;
But, what if there isn't an event? Let's add the part that handles the returning of empty data to the client.&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="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="s1"&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;function&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="p"&gt;{&lt;/span&gt;
   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// milliseconds of now will be fine for our case&lt;/span&gt;
   &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;timer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&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;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;clearTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;timer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;event&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&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;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;201&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;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
   &lt;span class="p"&gt;};&lt;/span&gt;

   &lt;span class="nx"&gt;eventEmitter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="nx"&gt;timer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt; 
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;timeout&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;wasUnregistered&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;eventEmitter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;unregister&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;wasUnregistered&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;wasUnregistered&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;wasUnregistered&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;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&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;end&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="mi"&gt;5000&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;We added a timer in the start of the function and we are also clearing it in case the event fires. &lt;br&gt;
In case the event didn't fire, we unregister the handler function from the event. &lt;br&gt;
The unregister function returns a boolean, if it returns false the function was already unregistered! So, we write the empty data response only if the event didn't fire. &lt;br&gt;
This is to avoid a race condition between the handler function and the timeout function.  &lt;/p&gt;

&lt;h2&gt;
  
  
  What situation remains unhandled?
&lt;/h2&gt;

&lt;p&gt;You might have noticed, that the event can fire exactly in the time that the client is getting the response and before it makes another request. &lt;br&gt;
The code doesn't handle that and there's a few possible solutions that we can implement. &lt;br&gt;
I can think of a few examples, can you?&lt;br&gt;
One example would be to run two sets of requests and another would be to hold off and "retry" the event if there's no listeners. &lt;/p&gt;

&lt;p&gt;I'm not going to implement any of those, although they sound pretty cool.&lt;/p&gt;

&lt;p&gt;I would just love it, if you make a pull request on the &lt;a href="https://github.com/asafg6/node-js-long-polling"&gt;github repo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hope you enjoyed reading this post.&lt;br&gt;&lt;br&gt;
And of course if you did, please share and tell your friends!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>http</category>
    </item>
    <item>
      <title>Common Pitfalls Developing a Chatbot With Rasa and How to Overcome Them</title>
      <dc:creator>asaf g</dc:creator>
      <pubDate>Fri, 30 Oct 2020 15:15:26 +0000</pubDate>
      <link>https://dev.to/asaf_g6/common-pitfalls-developing-a-chatbot-with-rasa-and-how-to-overcome-them-fk9</link>
      <guid>https://dev.to/asaf_g6/common-pitfalls-developing-a-chatbot-with-rasa-and-how-to-overcome-them-fk9</guid>
      <description>&lt;p&gt;Written by Rashit Bedi for &lt;a href="https://www.turtle-techies.com"&gt;https://www.turtle-techies.com&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Rasa is Open source conversational AI apparatus.  &lt;/p&gt;

&lt;p&gt;NLU in Rasa represents Natural Language Understanding. &lt;br&gt;
Befuddled among NLP and NLU? &lt;br&gt;
Well NLP represents Natural Language Processing while NLU is short form Natural Language Understanding. &lt;br&gt;
Both offer a shared objective of understanding the collaboration between spoken language (e.g English) and the language of the computer. &lt;br&gt;
Rasa NLU is Natural Language Processing framework for aim characterization, named retrieving responses, element extraction and some more. &lt;br&gt;
It is exceptionally used for - distinguish sentiments, conversational chatbots, Named-Entity Recognition and recognizing the reason for a sentence (intent).&lt;/p&gt;
&lt;h2&gt;
  
  
  Objective
&lt;/h2&gt;

&lt;p&gt;In this article, we are going to talk about common issues while developing a bot with RASA framework. &lt;br&gt;
We will also discuss ways to overcome these by functionalities provided by RASA and few other tricks applicable across all bot development frameworks.&lt;/p&gt;
&lt;h2&gt;
  
  
  Common Issues
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Generating NLU Data
&lt;/h3&gt;

&lt;p&gt;NLU (Natural Language Understanding) comes bundled with the Rasa framework that performs intent identification, entity extraction, and response retrieval.&lt;/p&gt;

&lt;p&gt;NLU will take in a user query such as "Please transfer 500 $ to Mike" and return structured data like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"intent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fund_transfer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"entities"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"500"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"beneficiary"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Mike"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The major pain factor for any problem that we choose to solve with ML/AI is data and NLU problems are no different.&lt;br&gt;
Building NLU models &lt;strong&gt;is tough&lt;/strong&gt;, and building ones that are production-grade is even tougher. &lt;br&gt;
Below are some useful tips for designing your RASA NLU training data to get the most out of your chatbot.&lt;/p&gt;
&lt;h4&gt;
  
  
  Conversation-Driven Development for NLU
&lt;/h4&gt;

&lt;p&gt;Conversation-Driven Development (CDD) means letting real world user conversations guide your bot building process. &lt;br&gt;
This process will help your bot understand conversations like common slangs, synonyms or abbreviations that are hard for a bot developer to remember and incorporate in training data. &lt;/p&gt;
&lt;h4&gt;
  
  
  Capture Real Data
&lt;/h4&gt;

&lt;p&gt;With regards to working out RASA NLU training data since it requires a lot of data to get trained efficiently, bot builders frequently depend on text generation tools and programs to rapidly build the number of right training examples for preparing models. &lt;br&gt;
These tools are great for building bulk training data. &lt;br&gt;
While this methodology can be efficient, it makes NLU models inclined to overfit information that isn't illustrative of things a genuine client would state. &lt;br&gt;
The variance in any data set is key for a well-trained NLU model.  &lt;/p&gt;

&lt;p&gt;To dodge such an issue, it is a smart thought to gather consistently however much genuine client interactions or conversations as could be expected to use as training data. &lt;br&gt;
Despite the fact that your bot will commit errors at first, the way toward preparing and assessing on client interactions will empower your model to sum up substantially more successfully in real world situations. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Did you know?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Chatette is a Python program that generates training datasets for Rasa NLU given template files. If you want to make &lt;br&gt;
large datasets of example data for Natural Language Understanding tasks without too much of a headache, Chatette is a project for you.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Z0uQCvvB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rmt8iyb932rh8qci8rm5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Z0uQCvvB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rmt8iyb932rh8qci8rm5.png" alt="Image description" width="880" height="162"&gt;&lt;/a&gt;&lt;br&gt;
Specifically, Chatette implements a Domain Specific Language (DSL) that allows you to define templates to generate a large number of sentences, which are then saved in the input format(s) of Rasa NLU.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;
  
  
  Share with close group users Early
&lt;/h4&gt;

&lt;p&gt;So as to accumulate genuine training data, you will require genuine client messages. &lt;br&gt;
A bot designer can just concoct a restricted range of examples, and users will consistently astonish you with what they state. &lt;br&gt;
This implies you should impart your bot to test users outside the advancement group as ahead of schedule as could be expected under the circumstances. &lt;br&gt;
See the full CDD guidelines for additional subtleties.&lt;/p&gt;
&lt;h3&gt;
  
  
  Avoiding Intent Mismatch
&lt;/h3&gt;

&lt;p&gt;Intents are characterized utilizing character and word-level features generated from your training examples, contingent upon what featurizers you've added to your NLU pipeline. &lt;br&gt;
At the point when various intents contain similar words requested along these lines, this can make disarray for the intent classifier.&lt;/p&gt;
&lt;h4&gt;
  
  
  Making smart use of Entities
&lt;/h4&gt;

&lt;p&gt;Intent mismatch or confusion often occurs when you want your assistant's response to be conditioned on information provided by the user, the user query will match to more than one intents with high confidence. &lt;br&gt;
For example, "How do I block my debit card?" versus "I want to block my credit card."&lt;/p&gt;

&lt;p&gt;Since each of these user messages will lead to a different response from the bot, your initial approach might be to create separate RASA intents for each card type.&lt;/p&gt;

&lt;p&gt;e.g. &lt;code&gt;credit_card_block&lt;/code&gt; and &lt;code&gt;debit_card_block&lt;/code&gt;. &lt;br&gt;
However, these intents are trying to achieve the same goal (blocking the card) and will likely be phrased similarly, which may cause the model to confuse these intents.&lt;/p&gt;

&lt;p&gt;To avoid intent mismatch, group these training examples into a single card block intent and make the response depend on the value of a categorical &lt;code&gt;card_type&lt;/code&gt; slot that comes from an entity. &lt;br&gt;
This also makes it easy to handle the case when no entity is provided, e.g. "How do I block my card?" For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="na"&gt;stories&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;story&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;block my debit card&lt;/span&gt;
  &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;intent&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;block_card&lt;/span&gt;
      &lt;span class="na"&gt;entities&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;card_type&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;slot_was_set&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;card_type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;debit&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;utter_debit_card_block&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;story&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;block my credit card&lt;/span&gt;
  &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;intent&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;block_card&lt;/span&gt;
      &lt;span class="na"&gt;entities&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;card_type&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;slot_was_set&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;card_type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;credit&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;utter_credit_card_block&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;story&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;block my card&lt;/span&gt;
  &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;intent&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;block_card&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;utter_ask_card_type&lt;/span&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Extracting entities
&lt;/h3&gt;

&lt;p&gt;Common entities such as names, addresses, and cities require a large amount of training data for an NLU model to generalize effectively.&lt;br&gt;&lt;br&gt;
RASA provides many options for entity extractions, it gets quite difficult to understand which method to use when. &lt;br&gt;
Let’s drill down on a few of them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZKobhFhe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ynw3a9gqm8denxjq1o2u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZKobhFhe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ynw3a9gqm8denxjq1o2u.png" alt="Image description" width="880" height="442"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;RASA framework provides two great options for pre-trained extraction models: first is the &lt;code&gt;DucklingEntityExtractor&lt;/code&gt; and &lt;code&gt;SpacyEntityExtractor&lt;/code&gt;. &lt;br&gt;
Because these extraction models have been pre-trained on a very large corpus of data, you can use them to extract the entities they support without the need of annotating them in your training data. &lt;br&gt;
Apart from these pre-trained extractions, RASA provides tools for extraction of entities.&lt;/p&gt;
&lt;h4&gt;
  
  
  First up, Regexes!
&lt;/h4&gt;

&lt;p&gt;A &lt;code&gt;RegEx&lt;/code&gt;, or Regular Expression, is a sequence of characters that forms a search pattern (but I assume you already know that). &lt;br&gt;
RASA provides provision to set regexes against any entity. &lt;br&gt;
Regexes are useful for performing entity extraction on structured patterns such as 11-digit bank account numbers. &lt;br&gt;
Regex patterns can be used to generate features for the NLU model to learn, or as a method of direct entity matching. &lt;/p&gt;

&lt;p&gt;To set this up follow the below example:&lt;/p&gt;

&lt;p&gt;Data look like this in your &lt;strong&gt;nlu.md&lt;/strong&gt; file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;
&lt;span class="gu"&gt;## intent:inform&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;AB-123&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;customer_id&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="nv"&gt;BB-321&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;customer_id&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="nv"&gt;12345&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;transaction_id&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="nv"&gt;23232&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;transaction_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="gu"&gt;## regex:customer_id&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="se"&gt;\b&lt;/span&gt;[A-Z]{2}-&lt;span class="se"&gt;\d&lt;/span&gt;{3}&lt;span class="se"&gt;\b&lt;/span&gt;
&lt;span class="gu"&gt;## regex:account_number&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="se"&gt;\b\d&lt;/span&gt;{11}&lt;span class="se"&gt;\b&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;And the config file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;
&lt;span class="na"&gt;language&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;en"&lt;/span&gt;
&lt;span class="na"&gt;pipeline&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SpacyNLP"&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SpacyTokenizer"&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SpacyFeaturizer"&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RegexFeaturizer"&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CRFEntityExtractor"&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EntitySynonymMapper"&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SklearnIntent&lt;/span&gt;

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  Second, Lookup Tables!
&lt;/h4&gt;

&lt;p&gt;You can think of look up tables as databases of information, which you can set against any entity for matching. &lt;br&gt;
Lookup tables are processed as a regex pattern that checks if any of the lookup table entries exist in the training example. &lt;br&gt;
Similar to regexes, lookup tables can be used to provide features to the model to improve entity recognition, or used to perform match-based entity recognition. &lt;br&gt;
Examples of where you can use lookup tables are types of Apple IPhone models, a la carte menu options or ice cream flavours.&lt;/p&gt;

&lt;h4&gt;
  
  
  Lastly, Synonyms!
&lt;/h4&gt;

&lt;p&gt;Adding synonyms or similar words to your RASA NLU training data is helpful for mapping certain user query words to a solitary standardized entity. &lt;br&gt;
Synonyms, however, are not meant for improving your model's entity recognition and have no effect on NLU performance.&lt;/p&gt;

&lt;p&gt;A good use case for synonyms is when normalizing entities belonging to distinct groups. &lt;br&gt;
For example, a virtual assistant that asks users what type of loan they're interested in, they might respond with "house loan," "I need home loan," or "housing." It would be a good idea to map house, home, and housing to the normalized value house so that the processing logic will only need to account for a narrow set of possibilities.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Take care of Misspellings!!&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Running over incorrect spellings is inescapable, so your bot needs a successful method to deal with this.&lt;br&gt;&lt;br&gt;
Remember that the objective isn't to address incorrect spellings, however, to accurately distinguish intents and entities.&lt;br&gt;&lt;br&gt;
Consequently, while a spellchecker may appear to be an apt arrangement, changing your featurizers and training data regularly are adequate to represent incorrect spellings.&lt;br&gt;&lt;br&gt;
Adding a character-level featurizer gives a viable protection against spelling mistakes by representing portions of words, rather than just entire words.&lt;br&gt;&lt;br&gt;
You can add character level featurization to your pipeline by utilizing the &lt;code&gt;char_wb&lt;/code&gt; analyzer for the &lt;code&gt;CountVectorsFeaturizer&lt;/code&gt;&lt;br&gt;&lt;br&gt;
Notwithstanding character-level featurization, you can add basic incorrect spellings to your training data.  &lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;Apart from the above points, generally speaking if there’s any downside to RASA’s feature rich framework, it might be the steep learning curve with respect to how these features work in tandem. &lt;br&gt;
As some other chatbot developers have noted, Rasa isn’t necessarily for beginners. &lt;br&gt;
Unless you’ve built chatbots before using other chabot development frameworks, Rasa’s framework might strike you as a bit intimidating at first.  &lt;/p&gt;

&lt;p&gt;Having said that, there are some great tutorials and material available for the beginners to start working on this fabulous framework.&lt;br&gt;&lt;br&gt;
Most importantly it has amazing community support.&lt;br&gt;&lt;br&gt;
A diverse group of makers and conversational AI enthusiasts. Where people of different backgrounds and locations help each other to understand the framework and create better AI assistants.  &lt;/p&gt;

</description>
      <category>rasa</category>
      <category>nlu</category>
      <category>python</category>
    </item>
    <item>
      <title>Certificate Pathways to Cyber Security</title>
      <dc:creator>asaf g</dc:creator>
      <pubDate>Fri, 09 Oct 2020 07:17:45 +0000</pubDate>
      <link>https://dev.to/asaf_g6/certificate-pathways-to-cyber-security-2j67</link>
      <guid>https://dev.to/asaf_g6/certificate-pathways-to-cyber-security-2j67</guid>
      <description>&lt;p&gt;Written by Nipuna Dilhara&lt;/p&gt;

&lt;p&gt;If you are reading this article it means you are already interested in cybersecurity. &lt;br&gt;
That’s the first symptom of becoming obsessed with this fascinating IT discipline. &lt;br&gt;
You might have heard about all these cyber attacks, data breaches, system vulnerabilities at least a few times a week. &lt;br&gt;
If you are an IT professional already, you might be aware of how fast the cybersecurity industry is booming and governments and companies are struggling to find the right talent and keep up with the growing demand. &lt;br&gt;
It doesn’t matter if you are either already into IT or a total beginner. &lt;br&gt;
If you want to uplift your life for the better, then you have come to the right place.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is Cyber Security Really in Demand?
&lt;/h2&gt;

&lt;p&gt;If you are having any doubts, first check the below image provided by &lt;a href="https://www.cyberseek.org/heatmap.html"&gt;cybserseek&lt;/a&gt;, which shows cybersecurity job openings in the USA.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GA2DpLGO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xbf4d5mzc69bm7hznumj.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GA2DpLGO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xbf4d5mzc69bm7hznumj.jpg" alt="Image description" width="721" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I couldn't recall another career path that gathered the attention of this degree in recent years as cybersecurity.&lt;br&gt;
According to the &lt;a href="https://www.bls.gov/ooh/computer-and-information-technology/information-security-analysts.htm#tab-1"&gt;US Bureau of Labor Statistics&lt;/a&gt;, the expected job growth for information security professionals is around 31% between 2019 to 2029 which is much faster than other IT-related occupations. &lt;br&gt;
Most of the recent researches say that the demand for skilled cybersecurity professionals won’t go down in the foreseeable future. &lt;/p&gt;

&lt;p&gt;When thinking about the current IT industry, those statistics don’t surprise me.&lt;br&gt;&lt;br&gt;
There aren’t enough people with the required analytical and innovative skills to tackle the growing threats in the digital world.&lt;/p&gt;

&lt;p&gt;So from where all these opportunities are coming from? What cybersecurity jobs have more demand and changes than others?&lt;/p&gt;

&lt;p&gt;Let’s have a look at the most in-demand cybersecurity career pathways in brief.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;reference: &lt;a href="https://www.cyberdegrees.org/jobs/"&gt;https://www.cyberdegrees.org/jobs/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Full Disclosure: this post might have some affiliate links.&lt;/p&gt;

&lt;h2&gt;
  
  
  Career Pathways in Cyber Security
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Information Security Analyst
&lt;/h3&gt;

&lt;p&gt;If we put it in simple words, the main responsibility of a Security Analyst is to protect an organization's data from malicious attacks.&lt;br&gt;&lt;br&gt;
An Information Security Analyst monitors the system for potential security breaches. &lt;br&gt;
Apart from that, the main job duties might include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Developing organization security policies&lt;/li&gt;
&lt;li&gt;Informing and training employees regarding security measurements, new applications, and hardware&lt;/li&gt;
&lt;li&gt;Conducting penetration testings&lt;/li&gt;
&lt;li&gt;Installing software tools to secure the environment, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It doesn’t sound like an easy job. So it’s no wonder why Security Analysts are in such high demand.  &lt;/p&gt;

&lt;h3&gt;
  
  
  Ethical Hacker
&lt;/h3&gt;

&lt;p&gt;Becoming an Ethical Hacker or White Hat Hacker might be one of the best things that can happen to your life. &lt;br&gt;
It’s such an interesting job but not meant for everyone. &lt;br&gt;
Ethical hackers are certified security professionals who are authorized by the employer or a hiring organization to penetrate their system and find existing and potential system vulnerabilities. &lt;br&gt;
They use the same techniques as Black Hat Hackers do, but for a better purpose. &lt;br&gt;
Responsibilities of an Ethical Hacker don’t end from finding vulnerabilities. &lt;br&gt;
In most cases, they have to find a way to patch the exposed vulnerability and prevent malicious attackers from using them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Penetration Tester
&lt;/h3&gt;

&lt;p&gt;Penetration testing is a subset of the broad responsibilities of an Ethical Hacker. &lt;br&gt;
However, I’m listing it separately since it’s one of the most demanded jobs currently in the world. &lt;br&gt;
Organizations are eager to find Penetration Testers with correct skills. &lt;br&gt;
The responsibility of Penetration Testers is mainly to identify system vulnerabilities. &lt;br&gt;
But Penetration Testers are focused on a specific area defined for testing whereas Ethical Hackers work on a wider range. &lt;br&gt;
Penetration is one of the functions of Ethical Hackers that have to be carried out while searching for vulnerabilities.&lt;br&gt;
And yet Penetration Testers are still in high demand and being &lt;a href="https://www.hudsoncourses.com/ethical-hacker-vs-penetration-tester/"&gt;recruited separately from Ethical Hackers&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Secure Software Developer
&lt;/h3&gt;

&lt;p&gt;The Secure Software Development is for those who are passionate about programming as well as the security aspects of it. &lt;br&gt;
Secure Software Developers have to focus on developing secure applications by integrating security best practices and protocols. &lt;br&gt;
Becoming a Secure Software Developer, you have to understand every aspect of software development based on the Software Development Life Cycle (SDLC).&lt;br&gt;
They should have specialized knowledge of software design, software security, computer systems and networks, and programming. &lt;br&gt;
The knowledge on software-based security strategies categorizes Secure Software Developers apart from traditional programmers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Digital Forensic Analyst
&lt;/h3&gt;

&lt;p&gt;Digital Forensic Analysts specially trained to retrieve digital evidence from various digital assets used in cybercrimes.&lt;br&gt;
In some cases, you will see they work with law enforcement agencies to expand investigations into the digital world.&lt;br&gt;
Their role is to provide consultant and technical support whenever necessary. &lt;br&gt;
Within an organization, Digital Forensics is involved with securing sensitive data, educating employees about cybersecurity issues, identifying data breaches and weaknesses, and many more.&lt;/p&gt;

&lt;p&gt;Digital Forensic Analysts are often hired by government agencies, corporations, law firms, etc. &lt;br&gt;
If you are interested in stuff like investigating crimes, following digital fingerprints then this might be for you. &lt;br&gt;
You will never know unless you give a try.&lt;/p&gt;

&lt;h3&gt;
  
  
  Security Architect
&lt;/h3&gt;

&lt;p&gt;Security Architects design, plan and supervise systems and networks that will prevent security threats. &lt;br&gt;
They identify the strengths and weaknesses of their organization’s systems and networks and take necessary measurements accordingly. &lt;br&gt;
It’s an exciting job role which often needs to be researching new technologies to make things more secure and better in performance. &lt;br&gt;
Security Architects possess an in-depth knowledge of software and hardware design, computer networks, computer programming, and risk management. &lt;br&gt;
A well experienced Security Architect often has strong analytical and problem-solving skills which highlight them apart from other cybersecurity professionals.  &lt;/p&gt;

&lt;h2&gt;
  
  
  How to get in?
&lt;/h2&gt;

&lt;p&gt;Well, it wasn’t easy to isolate and list down the career and responsibilities of this field with vast variety. &lt;br&gt;
But we did our research and identified positions which might help you most. &lt;br&gt;
Apart from what we have mentioned here, there are several other positions in the industry which are coming with a handsome salary. &lt;br&gt;
Also, you might see in other places that the aforementioned job roles and responsibilities have been mentioned under different job titles.&lt;br&gt;&lt;br&gt;
Cybersecurity is a vast field with a variety of specializations. &lt;br&gt;
Many governments are trying to gather these specializations under one umbrella called Cybersecurity. &lt;br&gt;
So there can be some mismatches between how each job role is titled by two people. &lt;br&gt;
But we suppose that you already have the picture to get a basic idea.&lt;/p&gt;

&lt;p&gt;So how can we get into this booming industry?&lt;br&gt;&lt;br&gt;
Indeed, having an undergraduate or postgraduate degree in Cybersecurity or a relevant area will put you one step ahead. &lt;br&gt;
What about others? Everyone deserves to be a part of this if he or she has the interest and keen to learn. &lt;br&gt;
We are living in a generation where our life is not getting decided by just a university degree. &lt;br&gt;
Companies like to hire higher candidates with the correct technical skills, mindset, and the potential to achieve greater things.&lt;/p&gt;

&lt;p&gt;But how do we prove them we are the people they were looking for? &lt;br&gt;
How do we prove we have the knowledge and qualifications to deliver value to their organization?  &lt;/p&gt;

&lt;p&gt;That’s when cybersecurity professional certificates are coming into the play.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cybersecurity Professional Certificates
&lt;/h2&gt;

&lt;p&gt;Unlike other IT disciplines, Cybersecurity has a well known set of professional certificates for anyone with the hunger to learn more and achieve more. &lt;br&gt;
You may not have a 4 years university degree, but you have been given the opportunity to develop your career via these certificates. &lt;/p&gt;

&lt;p&gt;It’s up to you how far you wish to go and in which direction. &lt;br&gt;
But if you have the characteristics that I was mentioning, then following certificates will give you a fair chance to land on a job in cybersecurity.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CompTIA Linux+&lt;/li&gt;
&lt;li&gt;CompTIA Network+&lt;/li&gt;
&lt;li&gt;CompTIA Security+&lt;/li&gt;
&lt;li&gt;Certified Ethical Hacker (ECH)&lt;/li&gt;
&lt;li&gt;System Security Certified Practitioner (SSCP)&lt;/li&gt;
&lt;li&gt;Offensive Security Certified Professional (OSCP)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s have a deeper look at each and every one of the above.&lt;/p&gt;

&lt;h3&gt;
  
  
  CompTIA Linux+
&lt;/h3&gt;

&lt;p&gt;If you are at the beginner level, completing the Linux+ will come in handy for sure. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2vUypL4m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mailnm9yuc4peyryjkwy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2vUypL4m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mailnm9yuc4peyryjkwy.png" alt="Image description" width="225" height="225"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Kali Linux is known to be the most loved Linux distro among Cybersecurity professionals. &lt;br&gt;
We suppose that it will remain the same in the foreseeable future as well.&lt;/p&gt;

&lt;p&gt;The Linux+ has been designed to provide you with the fundamental but essential skills to work in the Linux environment. &lt;br&gt;
The certification will test your abilities on Linux commands, maintenance tasks, installing and configuring workstations, and networking.&lt;/p&gt;

&lt;p&gt;It’s guaranteed that this certificate will provide you with a confidence boost and more importantly a kick start to the career in Cybersecurity.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://click.linksynergy.com/deeplink?id=lebg7qNf2d8&amp;amp;mid=39197&amp;amp;murl=https%3A%2F%2Fwww.udemy.com%2Fcourse%2Fcomptia-linux-2009-part-1-of-part-2%2F"&gt;Linux+ Udemy course&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.comptia.org/certifications/linux"&gt;https://www.comptia.org/certifications/linux&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  CompTIA Network+
&lt;/h3&gt;

&lt;p&gt;CompTIA Network+ is a well known entry-level certificate provided by CompTIA. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CgbRkLfR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/08iv44xeavy36v79l09u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CgbRkLfR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/08iv44xeavy36v79l09u.png" alt="Image description" width="255" height="197"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It will provide you with an in-depth understanding of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Networking technologies and devices&lt;/li&gt;
&lt;li&gt;Network security practices&lt;/li&gt;
&lt;li&gt;Network security policies&lt;/li&gt;
&lt;li&gt;Network security threats&lt;/li&gt;
&lt;li&gt;Defense mechanisms&lt;/li&gt;
&lt;li&gt;Damage recovery&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;and other relevant knowledge areas regarding both wired and wireless networks.&lt;br&gt;
Networking is an essential aspect to gain the required skills which play a vital role in information security and policies.&lt;br&gt;
No company would like to make headlines for a critical data breach. &lt;br&gt;
It will tear apart their reputation to a state that cannot be rebuilt. &lt;br&gt;
So companies tend to invest more and more in ensuring their data and information security in each passing day. &lt;br&gt;
Due to these reasons Network+ has become one of the major certificates that any employer considers during an interview.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://click.linksynergy.com/deeplink?id=lebg7qNf2d8&amp;amp;mid=39197&amp;amp;murl=https%3A%2F%2Fwww.udemy.com%2Fcourse%2Fcomptia-network-cert-n10-007-the-total-course%2F"&gt;TOTAL: CompTIA Network+ Certification&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.comptia.org/certifications/network"&gt;https://www.comptia.org/certifications/network&lt;/a&gt;  &lt;/p&gt;

&lt;h3&gt;
  
  
  CompTIA Security+
&lt;/h3&gt;

&lt;p&gt;The CompTIA Security+ is another great entry-level certificate and according to most professionals, it’s the best certificate to be followed at this level. &lt;br&gt;
The Security+ is a vendor-neutral qualification that has been approved by the US Department of Defence and employees around the globe.&lt;/p&gt;

&lt;p&gt;This certificate has been designed to cover a wide range of security-related skills, use case simulations, and technical knowledge. &lt;br&gt;
You have to gain knowledge on a variety of security threats, vulnerabilities, security tools, risk management, secure application development, and many relevant areas.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--J-hBlmsS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yixkq7y62pa3rj3q2r24.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--J-hBlmsS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yixkq7y62pa3rj3q2r24.png" alt="Image description" width="255" height="197"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you have the Security+ under your belt, it will open the doorway to more advanced careers such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Network Security Engineer&lt;/li&gt;
&lt;li&gt;Network Security Administrator&lt;/li&gt;
&lt;li&gt;Security Analyst&lt;/li&gt;
&lt;li&gt;Senior Technical Support Engineer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s totally up to you how to unitize the broad knowledge gathered for this certificate program. &lt;br&gt;
You will be able to build your future career upon it.&lt;/p&gt;

&lt;p&gt;It’s true that the CompTIA Security+ sounds complex and will need a lot more training to gain the required knowledge and experience in these areas. But the effort you put to complete the certificate will be worth it for sure.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.comptia.org/certifications/security"&gt;https://www.comptia.org/certifications/security&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://click.linksynergy.com/deeplink?id=lebg7qNf2d8&amp;amp;mid=39197&amp;amp;murl=https%3A%2F%2Fwww.udemy.com%2Fcourse%2Fcomptia-security-certification-sy0-501-the-total-course%2F"&gt;Comptia Security+ on Udemy&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  CEH: Certified Ethical Hacker
&lt;/h3&gt;

&lt;p&gt;Here comes some interesting stuff. Hacking!&lt;/p&gt;

&lt;p&gt;The CEH certificate is mainly designed for those who are interested in hacking. &lt;br&gt;
It’s the most well-known certificate that will clear the path of becoming an ethical hacker. &lt;br&gt;
Even though doing ethical or unethical stuff is totally up to you, this certificate will provide you with the foundation knowledge of the world of hacking.  &lt;/p&gt;

&lt;p&gt;Hacking is a double-edged sword. &lt;br&gt;
It can be used for both good and bad purposes. &lt;br&gt;
The CEH certificate covers the knowledge required to become a White Hat hacker. &lt;br&gt;
A White Hat hacker uses the same tools and techniques as a malicious attacker to identify vulnerabilities and enhance the organization's security.&lt;/p&gt;

&lt;p&gt;You might already have found this certificate interesting. &lt;br&gt;
But we don’t recommend you to jump straight into this. &lt;br&gt;
The CEH is not considered as an entry-level certificate. &lt;br&gt;
It’s more likely an intermediate certificate that allows security professionals to get into a more specific job category of ethical hackers or penetration testers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5mfkgjpQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1aze62x99djnl5yq9i81.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5mfkgjpQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1aze62x99djnl5yq9i81.png" alt="Image description" width="880" height="685"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The CEH is not an easy certificate to collect. &lt;br&gt;
It covers a wide range of skills and knowledge on different attacking methodologies and prevention techniques relevant to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Network scanning&lt;/li&gt;
&lt;li&gt;Social engineering&lt;/li&gt;
&lt;li&gt;DoS attacks&lt;/li&gt;
&lt;li&gt;SQL injections&lt;/li&gt;
&lt;li&gt;Session hijacking&lt;/li&gt;
&lt;li&gt;Viruses and Trojans&lt;/li&gt;
&lt;li&gt;Cryptography&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And much more.&lt;/p&gt;

&lt;p&gt;Once you become a certified ethical hacker, you will be able to work on the aforementioned cyber attacks, identifying vulnerabilities, plan and implement defense strategies for your organization.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://click.linksynergy.com/deeplink?id=lebg7qNf2d8&amp;amp;mid=39197&amp;amp;murl=https%3A%2F%2Fwww.udemy.com%2Fcourse%2Fcertified-ethical-hacker-ceh-a-to-z-course%2F"&gt;Certified Ethical Hacker (CEH 10) A to Z Course&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.eccouncil.org/programs/certified-ethical-hacker-ceh/"&gt;https://www.eccouncil.org/programs/certified-ethical-hacker-ceh/&lt;/a&gt;  &lt;/p&gt;

&lt;h3&gt;
  
  
  System Security Certified Practitioner (SSCP)
&lt;/h3&gt;

&lt;p&gt;The SSCP is another globally recognized certificate that is offered by (ISC)2. &lt;br&gt;
As the name indicates, SSCP mainly focuses on technical aspects of system security. &lt;br&gt;
In order to earn the SSCP, you might have to have practical knowledge of security over the theoretical part.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LIZASGht--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b4aka1fa4w5bq9mr455i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LIZASGht--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b4aka1fa4w5bq9mr455i.png" alt="Image description" width="507" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A few of the widely covered areas of this certificate are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Access and management control&lt;/li&gt;
&lt;li&gt;Risk analysis and identification&lt;/li&gt;
&lt;li&gt;Incident response and recovery&lt;/li&gt;
&lt;li&gt;Network and system security&lt;/li&gt;
&lt;li&gt;Security operations and administration&lt;/li&gt;
&lt;li&gt;Cryptography&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are still at the beginner level, unfortunately, this might not be the certificate for you. &lt;br&gt;
The SSCP is more of an intermediate certificate for those who are having the experience of a couple of years in the cyber securing or networking fields.&lt;/p&gt;

&lt;p&gt;However, if you are already having a few years of experience and planning to move into positions such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Network security engineer&lt;/li&gt;
&lt;li&gt;Network administrator&lt;/li&gt;
&lt;li&gt;Security analyst&lt;/li&gt;
&lt;li&gt;System engineer &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;and other similar roles then SSCP would be the ideal certificate to earn. &lt;br&gt;
It will give you the required qualifications to follow your passion in one of the aforementioned areas.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://click.linksynergy.com/deeplink?id=lebg7qNf2d8&amp;amp;mid=39197&amp;amp;murl=https%3A%2F%2Fwww.udemy.com%2Fcourse%2Fsscp-certification-systems-security-certified-practitioner%2F"&gt;SSCP Certification&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.isc2.org/Certifications/SSCP"&gt;https://www.isc2.org/Certifications/SSCP&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Offensive Security Certified Professional (OSCP)
&lt;/h3&gt;

&lt;p&gt;The OSCP is solely designed for those who are wishing to become penetration testers. &lt;br&gt;
Becoming a penetration tester is a wonderful career choice which most cybersecurity professionals dream of having. &lt;br&gt;
It’s the dream job of many cybersecurity professionals due to its fascinating job role.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ryi1_xrX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wpktzomndzxlegmolv2j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ryi1_xrX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wpktzomndzxlegmolv2j.png" alt="Image description" width="600" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The OSCP is provided by the Offensive Security organization who is the founder of beloved OS, Kali Linux. &lt;br&gt;
So you know OSCP is worth considering. &lt;br&gt;
Many employers consider the OSCP is the foundation certification for a pen testing job role. &lt;br&gt;
It will cover topics such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Active and passive information gathering&lt;/li&gt;
&lt;li&gt;Vulnerability scanning&lt;/li&gt;
&lt;li&gt;Web application attacks&lt;/li&gt;
&lt;li&gt;Client-side attacks&lt;/li&gt;
&lt;li&gt;Buffer overflows&lt;/li&gt;
&lt;li&gt;Privilege escalations
And more.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The OSCP is not an easy certificate to achieve. &lt;br&gt;
It includes heavy pen-testing practicals which need much more time and effort to &lt;a href="https://click.linksynergy.com/deeplink?id=lebg7qNf2d8&amp;amp;mid=39197&amp;amp;murl=https%3A%2F%2Fwww.udemy.com%2Fcourse%2Foscp-prep-practical-hands-on-offensivept-penetration-testing%2F"&gt;practice&lt;/a&gt; than for other certificates. &lt;br&gt;
Even though the certificate content is comparatively difficult, the end result will be highly rewarding. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.offensive-security.com/pwk-oscp/"&gt;https://www.offensive-security.com/pwk-oscp/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Is that All?
&lt;/h2&gt;

&lt;p&gt;These are only a few of the important certificates which will guide you from the beginner level to the more advanced level. &lt;br&gt;
The CompTIA has published its own pathway into cyber security which suits people at different levels of their careers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RGGW9Mo2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i0gf49zldvg50dwmiotj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RGGW9Mo2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i0gf49zldvg50dwmiotj.png" alt="Image description" width="565" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The EC-Council, who issued the Certified Ethical Hacker (CEH) certificate has its own certification path to become ethical hackers, security analysts and penetration testers.&lt;/p&gt;

&lt;p&gt;If you are really passionate about cyber security and looking for a way to get into it, this is the correct time than ever before. &lt;br&gt;
You won’t need university degrees any more. &lt;br&gt;
You have more than enough resources available at your doorstep. &lt;br&gt;
There are plenty of opportunities currently available for those who are with the right mind set. &lt;/p&gt;

&lt;p&gt;However, it won’t be not an easy path. &lt;br&gt;
You have to work hard and spend most of your time achieving your passion. &lt;br&gt;
After all, cyber security is for hardworking and passionate people. &lt;br&gt;
You should be always ready to run the extra mile.&lt;/p&gt;

&lt;p&gt;If you feel like cyber security is for you, don’t be afraid to follow these certificates and build your career step by step. &lt;br&gt;
It will be hard for you at first. &lt;br&gt;
You will feel like quitting. &lt;br&gt;
However, if you love the process and keep pushing yourself, you will be able to land on your dream job in cyber security most certainly.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to Write XML Changesets in Liquibase</title>
      <dc:creator>asaf g</dc:creator>
      <pubDate>Mon, 21 Sep 2020 15:31:33 +0000</pubDate>
      <link>https://dev.to/asaf_g6/how-to-write-xml-changesets-in-liquibase-1j77</link>
      <guid>https://dev.to/asaf_g6/how-to-write-xml-changesets-in-liquibase-1j77</guid>
      <description>&lt;p&gt;Written by Suresh Regmi&lt;br&gt;
If you want to have a basic understanding of Liquibase, I would suggest you look into our previous article on database version control with liquibase &lt;a href="https://www.turtle-techies.com/database-version-controler-with-liquibase/"&gt;https://www.turtle-techies.com/database-version-controler-with-liquibase/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We are assuming that you have already installed liquibase in your system. &lt;br&gt;
If you haven’t, please refer to this official documentation from liquibase &lt;a href="https://www.liquibase.org/get-started/first-steps"&gt;https://www.liquibase.org/get-started/first-steps&lt;/a&gt;.  &lt;/p&gt;

&lt;p&gt;In this article, we will be discussing &lt;strong&gt;changelogs&lt;/strong&gt;, &lt;strong&gt;changesets&lt;/strong&gt; and some examples of how to write changesets in XML format. &lt;br&gt;
The database I am referring to while writing changesets is Oracle. &lt;br&gt;
You might need to change some of the values from code I provided according to the database you are using for example the driver detail, the connection parameter, data types etc.&lt;/p&gt;
&lt;h2&gt;
  
  
  Some background information
&lt;/h2&gt;
&lt;h3&gt;
  
  
  What is a changelog
&lt;/h3&gt;

&lt;p&gt;A changelog is a collection of the changesets. Changelogs can be written in SQL, XML, JSON and YAML format.&lt;br&gt;&lt;br&gt;
Changelogs can include nested elements like preConditions, property, changeSet, include, context etc.&lt;/p&gt;
&lt;h3&gt;
  
  
  What is a changeset
&lt;/h3&gt;

&lt;p&gt;Changeset in liquibase represents a single change to your database. &lt;br&gt;
Each changeset is executed in a transaction and will be either committed or rolled back depending on whether there is an error or not.&lt;br&gt;&lt;br&gt;
Each changeset is uniquely identified by “ID”, “AUTHOR” and the directory and filename of the changelog file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--a7YhCzir--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/42ed3s2ma0ktjsal4qvu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--a7YhCzir--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/42ed3s2ma0ktjsal4qvu.png" alt="Image description" width="880" height="307"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Let’s start with organizing your changelog files
&lt;/h2&gt;

&lt;p&gt;Changelog files can be managed in two ways - either to create a single changelog file and add all of your changesets to that file, or create multiple files and split the changesets across them.  &lt;/p&gt;

&lt;p&gt;In my experience, the latter is more manageable and has a lot of advantages.&lt;br&gt;&lt;br&gt;
Segregating changesets based on database objects and release versions help to manage the changes in a more organized way.  &lt;/p&gt;

&lt;p&gt;If you already have a base database and you want to implement liquibase to that project, you can add changesets for initial tables, data and procedures in different folders and manage database updates based on release versions. &lt;br&gt;
Managing changelog files based on release will help you to understand the changes that were part of the release and will be easier for other developers. &lt;/p&gt;

&lt;p&gt;Working in an agile environment, here is an example of organizing changelogs that I use most and suggest others to follow.&lt;br&gt;
 I also prefer organizing changesets in multiple files and using the include tag in the database changelog of master changelog file to define the files and order of execution.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--l8Jmhq9z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b1wpwztfebgaqgiqrmvp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--l8Jmhq9z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b1wpwztfebgaqgiqrmvp.png" alt="Image description" width="704" height="568"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can also define a master changelog file containing nested include elements to define the execution order of the files. An example of a master changelog file including other changeset files to run in order is given below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;

&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;databaseChangeLog&lt;/span&gt;
        &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://www.liquibase.org/xml/ns/dbchangelog"&lt;/span&gt;
        &lt;span class="na"&gt;xmlns:xsi=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2001/XMLSchema-instance"&lt;/span&gt;
        &lt;span class="na"&gt;xsi:schemaLocation=&lt;/span&gt;&lt;span class="s"&gt;"http://www.liquibase.org/xml/ns/dbchangelog
         http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;include&lt;/span&gt; &lt;span class="na"&gt;file=&lt;/span&gt;&lt;span class="s"&gt;"Initial-Changesets/Initial-Tables/Initial-Tables.xml"&lt;/span&gt; &lt;span class="na"&gt;relativeToChangelogFile=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;include&lt;/span&gt; &lt;span class="na"&gt;file=&lt;/span&gt;&lt;span class="s"&gt;"Initial-Changesets/Initial-Procedures/Initial-Procedures.xml"&lt;/span&gt; &lt;span class="na"&gt;relativeToChangelogFile=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;include&lt;/span&gt; &lt;span class="na"&gt;file=&lt;/span&gt;&lt;span class="s"&gt;"Initial-Changesets/Initial-Data/Initial-Data.xml"&lt;/span&gt; &lt;span class="na"&gt;relativeToChangelogFile=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;include&lt;/span&gt; &lt;span class="na"&gt;file=&lt;/span&gt;&lt;span class="s"&gt;"Updates/Release-1.1-Updates.xml"&lt;/span&gt; &lt;span class="na"&gt;relativeToChangelogFile=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;include&lt;/span&gt; &lt;span class="na"&gt;file=&lt;/span&gt;&lt;span class="s"&gt;"Updates/Release-1.2-Updates.xml"&lt;/span&gt; &lt;span class="na"&gt;relativeToChangelogFile=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/databaseChangeLog&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;



&lt;p&gt;Here, I will explain to you different methods of writing changesets in liquibase with an example of two tables EMPLOYEE and DEPARTMENT.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. How to create tables with liquibase XML
&lt;/h2&gt;

&lt;p&gt;We can create one or more than one table in a single changeset. &lt;br&gt;
We can define &lt;code&gt;NOT NULL&lt;/code&gt; constraint, Primary Key and Foreign Key etc inside the createTable tag. &lt;br&gt;
Constraints can also be defined outside the create table tag. &lt;br&gt;
Here is an example of creating tables DEPARTMENT and EMPLOYEES  in a single changeset.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;changeSet&lt;/span&gt; &lt;span class="na"&gt;author=&lt;/span&gt;&lt;span class="s"&gt;"Author1"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;createTable&lt;/span&gt; &lt;span class="na"&gt;tableName=&lt;/span&gt;&lt;span class="s"&gt;"DEPARTMENT"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;column&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"ID"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"NUMBER"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;constraints&lt;/span&gt; &lt;span class="na"&gt;nullable=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt; &lt;span class="na"&gt;primaryKey=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;/column&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;column&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"DEPT_NAME"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"VARCHAR2(100 BYTE)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;constraints&lt;/span&gt; &lt;span class="na"&gt;nullable=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;/column&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;column&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"DEPT_DESCRIPTION"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"VARCHAR2(1000 BYTE)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;/column&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;/createTable&amp;gt;&lt;/span&gt;

 &lt;span class="nt"&gt;&amp;lt;createTable&lt;/span&gt; &lt;span class="na"&gt;tableName=&lt;/span&gt;&lt;span class="s"&gt;"EMPLOYEES"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;column&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"ID"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"NUMBER"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;constraints&lt;/span&gt; &lt;span class="na"&gt;nullable=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt; &lt;span class="na"&gt;primaryKey=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;/column&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;column&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"NAME"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"VARCHAR2(100 BYTE)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;/column&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;column&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"DEPARTMENT_ID"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"NUMBER"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;constraints&lt;/span&gt; &lt;span class="na"&gt;nullable=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt; &lt;span class="na"&gt;foreignKeyName=&lt;/span&gt;&lt;span class="s"&gt;"DEPARTMENT_ID_FK"&lt;/span&gt; &lt;span class="na"&gt;references=&lt;/span&gt;&lt;span class="s"&gt;"DEPARTMENT(ID)"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;/column&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;column&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"DESIGNATION"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"VARCHAR2(250 BYTE)"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;column&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"SALARY"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"NUMBER"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;/createTable&amp;gt;&lt;/span&gt;

 &lt;span class="nt"&gt;&amp;lt;addNotNullConstraint&lt;/span&gt; &lt;span class="na"&gt;columnName=&lt;/span&gt;&lt;span class="s"&gt;"NAME"&lt;/span&gt; &lt;span class="na"&gt;tableName=&lt;/span&gt;&lt;span class="s"&gt;"EMPLOYEES"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/changeSet&amp;gt;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;While creating changesets, I would suggest using a single database change in changeset so that if there is an error in one database change in a changeset, we don’t need to roll back the whole changesets. &lt;br&gt;
For example, in the changeset given, if there is an error in EMPLOYEES table, Liquibase will fail after creating the DEPARTMENT table, so in the next execution after resolving the error it will throw an exception saying table DEPARTMENT has already been created. So, we need to manually rollback the changes that come before the one with the error. &lt;/p&gt;
&lt;h2&gt;
  
  
  2. Let’s insert some data using SQL file
&lt;/h2&gt;

&lt;p&gt;Liquibase allows us to run the SQL stored in an external file. &lt;br&gt;
This is valuable in the event that when the changesets are not supported by Liquibase, if there should be an occurrence of bulk insertions and furthermore for the situation where users incline toward utilizing SQL contents over the other Liquibase changelog alternatives, as XML, JSON, and YAML. &lt;br&gt;
Here is how you can insert records in the table EMPLOYEES using an external SQL file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;
&lt;span class="nt"&gt;&amp;lt;changeSet&lt;/span&gt; &lt;span class="na"&gt;author=&lt;/span&gt;&lt;span class="s"&gt;"Author1"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;sqlFile&lt;/span&gt; &lt;span class="na"&gt;dbms=&lt;/span&gt;&lt;span class="s"&gt;"oracle"&lt;/span&gt;
          &lt;span class="na"&gt;encoding=&lt;/span&gt;&lt;span class="s"&gt;"utf8"&lt;/span&gt;
          &lt;span class="na"&gt;endDelimiter=&lt;/span&gt;&lt;span class="s"&gt;";"&lt;/span&gt;
          &lt;span class="na"&gt;path=&lt;/span&gt;&lt;span class="s"&gt;"Release1_SQL/insert_into_employees_file.sql"&lt;/span&gt;
          &lt;span class="na"&gt;relativeToChangelogFile=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
          &lt;span class="na"&gt;splitStatements=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
          &lt;span class="na"&gt;stripComments=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/changeSet&amp;gt;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;SQL File&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;---- DEPARTMENT&lt;/span&gt;
&lt;span class="k"&gt;Insert&lt;/span&gt; &lt;span class="k"&gt;into&lt;/span&gt; &lt;span class="n"&gt;DEPARTMENT&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;DEPT_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;DEPT_DESCRIPTION&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;values&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'D1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'D1 Department'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;---- EMPLOYEES&lt;/span&gt;
&lt;span class="k"&gt;Insert&lt;/span&gt; &lt;span class="k"&gt;into&lt;/span&gt; &lt;span class="n"&gt;EMPLOYEES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;DEPARTMENT_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;DESIGNATION&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;SALARY&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;values&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'John Doe'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'Developer'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;50000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. How to write SQL statements using SQL tag
&lt;/h2&gt;

&lt;p&gt;Liquibase also allows us to write SQL inside XML changeset to run whatever SQL you want. &lt;br&gt;
It can be useful in the cases when complex changesets aren’t supported by liquibase automated changesets. &lt;br&gt;
Below is an example of writing complex changes using the SQL tag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;
&lt;span class="nt"&gt;&amp;lt;changeSet&lt;/span&gt; &lt;span class="na"&gt;author=&lt;/span&gt;&lt;span class="s"&gt;"Author1"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;sql&lt;/span&gt; &lt;span class="na"&gt;dbms=&lt;/span&gt;&lt;span class="s"&gt;"oracle"&lt;/span&gt;
      &lt;span class="na"&gt;endDelimiter=&lt;/span&gt;&lt;span class="s"&gt;";"&lt;/span&gt;
      &lt;span class="na"&gt;splitStatements=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
      &lt;span class="na"&gt;stripComments=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   MERGE INTO EMPLOYEES  dest
   USING  (SELECT 2   AS id, 'John Doe2'  AS Name,  1 AS DEPARTMENT_ID, 'Clerk'  AS DESIGNATION, 40000 AS SALARY  FROM   dual) src
   ON (dest.id = src.id )
   WHEN NOT matched THEN
   INSERT (dest.ID,dest.NAME,dest.DEPARTMENT_ID,dest.DESIGNATION,dest.SALARY) VALUES  (src.ID,src.NAME,src.DEPARTMENT_ID,src.DESIGNATION,src.SALARY) ;
 &lt;span class="nt"&gt;&amp;lt;/sql&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/changeSet&amp;gt;&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. How to create Procedures and Triggers
&lt;/h2&gt;

&lt;p&gt;Procedures and triggers can be created/run using the &lt;code&gt;createProcedure&lt;/code&gt; tag in Liquibase or using custom SQL changesets. &lt;br&gt;
If you want to use the &lt;code&gt;CREATE OR REPLACE&lt;/code&gt; feature in Liquibase, runOnChange='true' can be set which will either create or update stored procedures while running.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;
&lt;span class="nt"&gt;&amp;lt;changeSet&lt;/span&gt; &lt;span class="na"&gt;author=&lt;/span&gt;&lt;span class="s"&gt;"Author1"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"4"&lt;/span&gt; &lt;span class="na"&gt;runOnChange=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;createProcedure&lt;/span&gt;
           &lt;span class="na"&gt;encoding=&lt;/span&gt;&lt;span class="s"&gt;"utf8"&lt;/span&gt;
           &lt;span class="na"&gt;procedureName=&lt;/span&gt;&lt;span class="s"&gt;"LIST_EMPLOYEES_BY_DEPT"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;![CDATA[CREATE OR REPLACE PROCEDURE "LIST_EMPLOYEES_BY_DEPT" (
 P_PARAM1    IN EMPLOYEES.DEPARTMENT_ID%TYPE,
 RETURNCURSOR    OUT SYS_REFCURSOR) AS
BEGIN
 OPEN RETURNCURSOR FOR
 SELECT * 
 FROM EMPLOYEES
 WHERE DEPARTMENT_ID=P_PARAM1;
END LIST_EMPLOYEES_BY_DEPT;
]]&amp;gt;&lt;/span&gt;    
   &lt;span class="nt"&gt;&amp;lt;/createProcedure&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/changeSet&amp;gt;&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. How to work with changelog parameters
&lt;/h2&gt;

&lt;p&gt;Liquibase allows us to define global changelog parameters which will allow dynamic substitution of the parameter in the changelogs described using the &lt;code&gt;${parameter-name}&lt;/code&gt; syntax. &lt;br&gt;
There are many ways to configure parameter values including command line parameter, properties file, parameter block of the database changelog file etc. &lt;/p&gt;

&lt;p&gt;Here is an example of using the changelog parameter in the &lt;strong&gt;liquibase.properties&lt;/strong&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;
&lt;span class="na"&gt;changeLogFile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;target/classes/changelog/master.xml&lt;/span&gt;
&lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;oracle.jdbc.OracleDriver&lt;/span&gt;

&lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${schema.connection.url}&lt;/span&gt;
&lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${schema.user}&lt;/span&gt;
&lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${schema.password}&lt;/span&gt;

&lt;span class="c1"&gt;# ChangeLog Parameters&lt;/span&gt;
&lt;span class="na"&gt;client.name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${dept.name}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Using changelog parameter in &lt;code&gt;changeSet&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;
&lt;span class="nt"&gt;&amp;lt;changeSet&lt;/span&gt; &lt;span class="na"&gt;author=&lt;/span&gt;&lt;span class="s"&gt;"Author1"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"5"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;sql&lt;/span&gt; &lt;span class="na"&gt;dbms=&lt;/span&gt;&lt;span class="s"&gt;"oracle"&lt;/span&gt;
      &lt;span class="na"&gt;endDelimiter=&lt;/span&gt;&lt;span class="s"&gt;";"&lt;/span&gt;
      &lt;span class="na"&gt;splitStatements=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
      &lt;span class="na"&gt;stripComments=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  UPDATE DEPARTMENT SET DEPT_DESCRIPTION='D1 Department New' WHERE DEPT_NAME= '${dept.name}' ;
 &lt;span class="nt"&gt;&amp;lt;/sql&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/changeSet&amp;gt;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Changelog parameter  in changelog file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;
&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;databaseChangeLog&lt;/span&gt;
        &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://www.liquibase.org/xml/ns/dbchangelog"&lt;/span&gt;
        &lt;span class="na"&gt;xmlns:xsi=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2001/XMLSchema-instance"&lt;/span&gt;
        &lt;span class="na"&gt;xsi:schemaLocation=&lt;/span&gt;&lt;span class="s"&gt;"http://www.liquibase.org/xml/ns/dbchangelog
         http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt;  &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"table.name"&lt;/span&gt;  &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"TEST_TABLE"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;  

    &lt;span class="nt"&gt;&amp;lt;changeSet&lt;/span&gt;  &lt;span class="na"&gt;author=&lt;/span&gt;&lt;span class="s"&gt;"Author1"&lt;/span&gt;  &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"6"&lt;/span&gt; &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;  
         &lt;span class="nt"&gt;&amp;lt;createTable&lt;/span&gt;  &lt;span class="na"&gt;tableName=&lt;/span&gt;&lt;span class="s"&gt;"${table.name}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;  
             &lt;span class="nt"&gt;&amp;lt;column&lt;/span&gt;  &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"id"&lt;/span&gt;  &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"int"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;  
             &lt;span class="nt"&gt;&amp;lt;column&lt;/span&gt;  &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"column1"&lt;/span&gt;  &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"varchar2(10)"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;  
             &lt;span class="nt"&gt;&amp;lt;column&lt;/span&gt;  &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"column2"&lt;/span&gt;  &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"int"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;  
         &lt;span class="nt"&gt;&amp;lt;/createTable&amp;gt;&lt;/span&gt;  
    &lt;span class="nt"&gt;&amp;lt;/changeSet&amp;gt;&lt;/span&gt;  
&lt;span class="nt"&gt;&amp;lt;/databaseChangeLog&amp;gt;&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  That's all folks!
&lt;/h2&gt;

&lt;p&gt;As the application development process goes on, increasingly more database changes are done by the development team which should be kept up and overseen.&lt;br&gt;&lt;br&gt;
With these examples, you will be able to complete the majority of migration tasks for your database including object creation, data insertion and migration, composing DDL and DML utilizing SQL tag, defining the changelog parameters and so on.&lt;/p&gt;

</description>
      <category>liquibase</category>
    </item>
    <item>
      <title>How to Package Your Multi-platform Electron App</title>
      <dc:creator>asaf g</dc:creator>
      <pubDate>Sun, 06 Sep 2020 11:47:58 +0000</pubDate>
      <link>https://dev.to/asaf_g6/how-to-package-your-multi-platform-electron-app-5528</link>
      <guid>https://dev.to/asaf_g6/how-to-package-your-multi-platform-electron-app-5528</guid>
      <description>&lt;p&gt;&lt;em&gt;Written by &lt;a href="https://www.turtle-techies.com/author/andres-acevedo/"&gt;Andres Acevedo&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In part &lt;a href="https://www.turtle-techies.com/multi-platform-desktop-app-with-electron"&gt;one&lt;/a&gt; and &lt;a href="https://www.turtle-techies.com/securing-your-electron-app"&gt;two&lt;/a&gt; of these Electron app development series, we created a basic text loader, and then addressed some security issues. &lt;br&gt;
But at the end of the day, we have not yet experienced the best feature of Electron apps:  &lt;/p&gt;

&lt;p&gt;Their ability to run on multiple platforms.  &lt;/p&gt;

&lt;p&gt;In this tutorial, we will use the codebase that we ended up with in the last part. &lt;a href="https://github.com/mran3/Secure-Text-File-Loader"&gt;you can get it here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; I usually provide a link to a repository with the completed project at the end of the tutorial, but for this one I think is important that you have the &lt;code&gt;package.json&lt;/code&gt; at hand to compare it with yours and find any possible differences in case you run into problems.&lt;/p&gt;

&lt;p&gt;You can find the app configured to build on macOS, Windows, and Linux here:&lt;br&gt;&lt;br&gt;
&lt;a href="https://github.com/mran3/Text-File-Loader-Build"&gt;https://github.com/mran3/Text-File-Loader-Build&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  macOS windows management
&lt;/h2&gt;

&lt;p&gt;Before delving into packaging our app, let's do a small adjustment to our code to respect the conventions of the macOS platform, where usually applications remain open even if they don't have any active windows. &lt;br&gt;
We can implement that behavior easily with electron by adding the following code to &lt;strong&gt;app.js&lt;/strong&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="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;window-all-closed&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;platform&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;darwin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&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;quit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// "darwin" targets macOS only.&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;


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

&lt;/div&gt;



&lt;p&gt;Other possible values for &lt;code&gt;process.platform&lt;/code&gt; are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;freebsd&lt;/li&gt;
&lt;li&gt;linux&lt;/li&gt;
&lt;li&gt;openbsd&lt;/li&gt;
&lt;li&gt;win32 (applies to any Windows).&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;If you are on a mac, relaunch our app and check that when you close the window, the app remains on the dock. &lt;br&gt;
Don’t worry about the electron icon, we will solve that next.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Icons
&lt;/h2&gt;

&lt;p&gt;Also, if we are talking about distributing our app and provide a good user experience, we can not do it with the Electron logo as the icon. Create or find an icon of your liking for your app, I am going to use this one:  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CbwnL2zN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/78pegdq4j2zguisqe13r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CbwnL2zN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/78pegdq4j2zguisqe13r.png" alt="The icon used for this tutorial" width="128" height="128"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;macOS uses a &lt;code&gt;.icns&lt;/code&gt; format, Windows requires &lt;code&gt;.ico&lt;/code&gt; and Linux prefer &lt;code&gt;.png&lt;/code&gt;, fortunately, you can create icon files from a &lt;code&gt;.png&lt;/code&gt; using online tools like  &lt;a href="https://cloudconvert.com/png-to-icns"&gt;https://cloudconvert.com/png-to-icns&lt;/a&gt; .&lt;/p&gt;

&lt;p&gt;Once you have them in both formats, create a new folder in the root of the project (I called it &lt;strong&gt;assets&lt;/strong&gt;) and put both icon files there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Packaging and distribution toolset
&lt;/h2&gt;

&lt;p&gt;To distribute your app with Electron, you need to package it for each operating system you want to target. &lt;br&gt;
The goal is to generate a &lt;code&gt;.exe&lt;/code&gt; file for Windows, a &lt;code&gt;.app&lt;/code&gt; for macOS, a &lt;code&gt;.deb&lt;/code&gt; for Debian-based Linux distributions, and so on.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/electron/electron-packager"&gt;Electron Packager&lt;/a&gt; is the official Electron tool to help us convert our source code to a bundle specific for macOS, Linux, or Windows. &lt;/p&gt;

&lt;p&gt;For Windows, Electron Packager will create a functional &lt;code&gt;.exe&lt;/code&gt; along with a bunch of &lt;code&gt;.dll&lt;/code&gt; and config files. &lt;br&gt;
Although you can put this together on a &lt;code&gt;.zip&lt;/code&gt; file and send it to your users, that does not provide a great user experience. &lt;br&gt;
So we can go a step ahead and consider not only how to package our app but also how to distribute it. &lt;/p&gt;

&lt;p&gt;That's when &lt;a href="https://www.electronforge.io/"&gt;Electron Forge&lt;/a&gt; comes into play, allowing us to create nice step by step installation wizards for our application. &lt;br&gt;
Internally Electron Forge uses Electron Packager, so it is not necessary to install them separately, let's run the following command to install them both:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; @electron-forge/cli &lt;span class="nt"&gt;-D&lt;/span&gt;

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

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Be careful not to install electron-forge (without the @), as this will install electron-forge v5 which has problems creating apps for the latest versions of macOS.&lt;br&gt;&lt;br&gt;
Besides that, the official documentation relates to v6.  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then, let's import our app into the Electron Forge workflow by running on a terminal located at the root of our project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
npx @electron-forge/cli import

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

&lt;/div&gt;



&lt;p&gt;Have in mind that if you want to start a new Electron app with Forge included, you don't have to import your project, instead, you can start a new project with the &lt;code&gt;create-electron-app&lt;/code&gt; command (more info on the official Electron Forge documentation: &lt;a href="https://www.electronforge.io/"&gt;https://www.electronforge.io/&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Although in theory, you could generate all your packages from one platform, that requires installing and configuring a lot of tools (i.e. wine and mono on mac to be able to build for Windows), so I recommend generating each executable in its own platform.&lt;/p&gt;

&lt;h3&gt;
  
  
  macOS
&lt;/h3&gt;

&lt;p&gt;We are all set for making our executables.&lt;br&gt;&lt;br&gt;
I will start with macOS, but you can skip ahead if you are interested in the process for Windows or Ubuntu Linux.&lt;/p&gt;

&lt;p&gt;Open your &lt;code&gt;package.json&lt;/code&gt; and in the scripts section, add one new entry:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;make-mac&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;npx @electron-forge/cli make --platform darwin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Also, modify the name field so it &lt;strong&gt;does not contain spaces or uppercase letters&lt;/strong&gt;. &lt;br&gt;
I am sure you don't want to present your app to your users with that hyphens on it, to avoid that, create a new field below &lt;code&gt;name&lt;/code&gt; named &lt;code&gt;productName&lt;/code&gt; and put whatever name you like.&lt;br&gt;&lt;br&gt;
The beginning of your &lt;code&gt;package.json&lt;/code&gt; file should look similar to 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="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&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;electro-text-reader&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;productName&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;ElectroReader&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;version&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;1.2.0&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;description&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;Multi platform Text Loader&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;main&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;main.js&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;scripts&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;test&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;echo &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Error: no test specified&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; &amp;amp;&amp;amp; exit 1&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;make-mac&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;electron-forge make --platform darwin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Now we need to add some configuration for Electron Forge, inside your &lt;code&gt;package.json&lt;/code&gt; there should be a &lt;code&gt;config&lt;/code&gt; field:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;config&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;forge&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;packagerConfig&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;icon&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;./assets/icon&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;As you can see, the icon extension is not specified, but Electron Packager (under the hood) will add the correct extension (.ico or .icons) depending on the platform.  &lt;/p&gt;

&lt;p&gt;Now run the script we created by running the following command on your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
npm run make-mac

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

&lt;/div&gt;



&lt;p&gt;At the end of the process, you should end up with a new folder named out.&lt;br&gt;&lt;br&gt;
Inside of it there should be two folders one with a long name containing the &lt;code&gt;.app&lt;/code&gt; file generated by Electron Packager and the other named &lt;strong&gt;make&lt;/strong&gt; contains a &lt;code&gt;.zip&lt;/code&gt; file that you can distribute to your users. &lt;br&gt;
Uncompress, run and enjoy: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lQD-onX_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6fqbdc26drkd0qp4dxje.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lQD-onX_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6fqbdc26drkd0qp4dxje.png" alt="Our installed macOS app" width="475" height="524"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Doesn't it look nice?&lt;/em&gt;  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
For each platform, you can have different makers that produce different types of distributable files, maker-zip is the default maker for macOS, but others allow for example exporting to DMG files&lt;br&gt;&lt;br&gt;
(you can read more about it here: &lt;a href="https://www.electronforge.io/config/makers/dmg"&gt;https://www.electronforge.io/config/makers/dmg&lt;/a&gt; ).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Ubuntu (Debian) Linux {#linux}
&lt;/h3&gt;

&lt;p&gt;To create a &lt;code&gt;.deb&lt;/code&gt; package, we will need to make sure that our system has two utilities installed: &lt;code&gt;fakeroot&lt;/code&gt; and &lt;code&gt;dpkg&lt;/code&gt;, these are not &lt;code&gt;npm&lt;/code&gt; packages, but actual applications of the operating system.&lt;br&gt;&lt;br&gt;
To install them, run the following commands on your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;dpkg
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;fakeroot

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

&lt;/div&gt;



&lt;p&gt;Add a new entry inside your scripts section with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;make-linux&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;npx @electron-forge/cli make --platform linux --targets deb&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

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

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;You could just execute &lt;code&gt;npx @electron-forge/cli make&lt;/code&gt; without the platform or targets arguments and electron forge will try to identify in what platform it is running and try to create the corresponding packages. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Getting the icon to work on linux required some additional steps.&lt;br&gt;&lt;br&gt;
Make sure the configuration of maker for debian (in your &lt;code&gt;package.json&lt;/code&gt;) specifies what icon to use:&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="p"&gt;{&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&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;@electron-forge/maker-deb&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;config&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;icon&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;./build/icon.png&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;p&gt;This will set the icon of the app, but for it to appear in the dock, we will need to jump off from our &lt;code&gt;package.json&lt;/code&gt; for a moment and modify our &lt;code&gt;main.js&lt;/code&gt; adding the icon to the call of new &lt;code&gt;BrowserWindow&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;win&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;BrowserWindow&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;800&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;join&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;getAppPath&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;build/icon.png&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;webPreferences&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;worldSafeExecuteJavaScript&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="na"&gt;contextIsolation&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="na"&gt;preload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;join&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;getAppPath&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;preload.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Now on a terminal let's run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
npm run make-linux

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

&lt;/div&gt;



&lt;p&gt;If everything went well you should have again an out folder with two sub-folders.&lt;br&gt;&lt;br&gt;
One with a bunch of files (the output of electron-packager), and make where you will find a nice &lt;code&gt;.deb&lt;/code&gt; file ready to be double-clicked and install our beautiful app:  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nkproPBO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m50tcc7qfq984shd0i2x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nkproPBO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m50tcc7qfq984shd0i2x.png" alt="Our installed Linux app" width="880" height="704"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The app installed on Ubuntu&lt;/em&gt;  &lt;/p&gt;

&lt;p&gt;One configuration that builds your app without problem in one platform, might need to install additional packages on another. &lt;br&gt;
For example, macOS does not have a problem if the description field on &lt;code&gt;package.json&lt;/code&gt; is not present, but it &lt;strong&gt;is required&lt;/strong&gt; for Debian.&lt;/p&gt;
&lt;h3&gt;
  
  
  Windows  {#windows}
&lt;/h3&gt;

&lt;p&gt;As you might guess, we need to add a new entry to &lt;code&gt;npm&lt;/code&gt; scripts. &lt;br&gt;
Why not test the platform inferring capabilities of Electron Forge and call it without parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;make&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;npx @electron-forge/cli make&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Squirrel is the default maker for Windows. &lt;br&gt;
It is intended to be lightweight and provide a hassle-free experience to the user, not requiring admin permissions or long installation wizards.&lt;br&gt;&lt;br&gt;
As a side note, this makes Squirrel great for creating apps that can run on a pen drive.&lt;/p&gt;

&lt;p&gt;Right now Squirrel will work, but it won't generate a nice Desktop icon, but for that, we just need to add a simple line to our &lt;code&gt;main.js&lt;/code&gt; file:&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;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;electron-squirrel-startup&lt;/span&gt;&lt;span class="dl"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run &lt;code&gt;npm make&lt;/code&gt; from the terminal, install your application, test it, and if everything goes right, edit your CV and add "Developer of multi-platform desktop applications". 😉  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DVYRu-nR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/omoy3uyobphh61r9967w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DVYRu-nR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/omoy3uyobphh61r9967w.png" alt="Our installed Windows app" width="298" height="308"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Electron app installed on Windows&lt;/em&gt;  &lt;/p&gt;

&lt;p&gt;If you run into any problems, remember that you can find the completed project on:&lt;br&gt;&lt;br&gt;
&lt;a href="https://github.com/mran3/Text-File-Loader-Build"&gt;https://github.com/mran3/Text-File-Loader-Build&lt;/a&gt; &lt;/p&gt;

</description>
      <category>electron</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Database Version Control With Liquibase</title>
      <dc:creator>asaf g</dc:creator>
      <pubDate>Sun, 06 Sep 2020 08:51:30 +0000</pubDate>
      <link>https://dev.to/asaf_g6/database-version-control-with-liquibase-5gpm</link>
      <guid>https://dev.to/asaf_g6/database-version-control-with-liquibase-5gpm</guid>
      <description>&lt;h2&gt;
  
  
  Motivation
&lt;/h2&gt;

&lt;p&gt;Let me give you a scenario,&lt;br&gt;&lt;br&gt;
You have a project with multiple database instances in different environments (Dev, QA, Production) and you need to manage the database schema changes that are done against those environments. &lt;br&gt;
Let’s assume that you are managing those changes by creating a git project or a shared file on a drive and adding a new SQL file for each database changes you are doing. &lt;br&gt;
To implement your changes in that database, for each SQL file, you need to run the changes in each environment manually and add a flag or note to indicate which change is run on which environment.&lt;br&gt;&lt;br&gt;
Would it be able to complete your task? &lt;br&gt;
Yes, Yet, is it a decent method to manage schema changes?&lt;br&gt;&lt;br&gt;
Of Course Not.&lt;/p&gt;

&lt;h2&gt;
  
  
  Here are some of the many problems you might face while doing so
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Hard to synchronize database and application code changes in different environments&lt;/li&gt;
&lt;li&gt;The tedious process to run each change manually in different environments&lt;/li&gt;
&lt;li&gt;Collaboration across the development team on what change is deployed and what is not&lt;/li&gt;
&lt;li&gt;Hard to roll-back to the previous version of the database&lt;/li&gt;
&lt;li&gt;Possibility of data loss&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Here comes Liquibase
&lt;/h2&gt;

&lt;p&gt;Liquibase is an open-source library for tracking and managing database schema changes that can be used for any database with a JDBC driver.&lt;br&gt;&lt;br&gt;
It is a platform-independent database migration tool that allows the database changes referred to as ‘changesets’ to be written in various formats including XML, JSON, YAML, and SQL. &lt;/p&gt;

&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Supports almost all databases that have a JDBC driver.&lt;/li&gt;
&lt;li&gt;Changesets can be written in different formats like XML, JSON, YAML, and SQL. &lt;/li&gt;
&lt;li&gt;Can be used to automatically generate changesets for an existing database&lt;/li&gt;
&lt;li&gt;Easy to integrate with build tools like Jenkins, Maven etc&lt;/li&gt;
&lt;li&gt;Supports database rollbacks &lt;/li&gt;
&lt;li&gt;Supports context-dependent logic allowing us to use global context and preconditions &lt;/li&gt;
&lt;li&gt;Can be executed via command line, Apache Maven, Apache Ant, Spring Framework&lt;/li&gt;
&lt;li&gt;Has feature to generate changeset from an existing database and can also generate schema difference as changesets&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Different ways to run liquibase
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Embed liquibase with your app:&lt;/strong&gt; Embedding liquibase with your application code will automatically deploy liquibase on the app startup.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run liquibase using build tools:&lt;/strong&gt; Integrate liquibase into your build process (with build tools like Jenkins, Ant, Maven, and Gradle) and update them without being tied up with the application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generate the SQL and run it manually:&lt;/strong&gt; Using update SQL, Liquibase provides the SQL generated from the changeset along with the database changes required to keep the tracking tables up to date. DBA will then inspect the SQL and run them against the database. &lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Installation Process
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites:&lt;/strong&gt; Liquibase requires Java 8+&lt;/p&gt;

&lt;p&gt;There are two ways to install Liquibase, Manual installation and using liquibase installer.  &lt;/p&gt;

&lt;p&gt;If you set up liquibase using the liquibase installer, dependencies, directories, config and properties files will all be in place already. &lt;br&gt;
It also provides some examples which will provide you with the core concepts required to understand the changesets.&lt;/p&gt;

&lt;p&gt;In the case of manual installation, you need to download the compressed liquibase file and extract it in your workspace.&lt;br&gt;&lt;br&gt;
For windows users, you need to add a new &lt;code&gt;PATH&lt;/code&gt; variable in the &lt;code&gt;Environment Variables&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
For macOS users, the path should be added to the &lt;code&gt;bash.profile&lt;/code&gt; file.  &lt;/p&gt;

&lt;p&gt;For detailed instruction on Installation please follow this &lt;a href="https://docs.liquibase.com/concepts/installation/home.html"&gt; document &lt;/a&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Core Concepts
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;liquibase.properties:&lt;/strong&gt; The file &lt;code&gt;liquibase.properties&lt;/code&gt; is a text-based file that stores common properties like database connection parameters, driver details, classpath parameters, global changelog parameters etc. 
If you install liquibase using liquibase installer, it will provide pre-written &lt;code&gt;liquibase.properties&lt;/code&gt; file while in case of manual installation, you need to create &lt;code&gt;liquibase.properties&lt;/code&gt; file using a sample file provided. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZmtHYbD2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/s58zkqaj2c0rz9ug5i3e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZmtHYbD2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/s58zkqaj2c0rz9ug5i3e.png" alt="Sample liquibase.properties file for Oracle"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;DatabaseChangeLog:&lt;/strong&gt; Databasechangelog is a file where all changesets go. Each database changelog can include one or more changesets.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jbbi21NB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/f0r13ang59hmscneki30.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jbbi21NB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/f0r13ang59hmscneki30.png" alt="Example of an empty DatabaseChangeLog file"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Changeset:&lt;/strong&gt; In liquibase, a changeset is represented as an atomic change to the database. Each changeset should be uniquely identified using author and id fields. 
The database handles each changeset as a single transaction. 
Changesets can be written in JSON, XML, SQL and YAML formats.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MsGjg8SO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/w41uzwp6co5nkkqmwr98.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MsGjg8SO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/w41uzwp6co5nkkqmwr98.png" alt="Example of a changeset in XML format"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;DATABASECHANGELOG &amp;amp; DATABASECHANGELOGLOCK:&lt;/strong&gt; These two tables are created by liquibase to track the changes that are run against the database and to make sure that no other migrations age going on.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--U7MsHDxa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/czqwbpzi8im42by40vyb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--U7MsHDxa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/czqwbpzi8im42by40vyb.png" alt="DATABASECHANGELOG table structure"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What if I don’t like Liquibase?
&lt;/h2&gt;

&lt;p&gt;If you told me that you don’t like liquibase and are looking for alternatives, I would ask why not Liquibase first.&lt;br&gt;&lt;br&gt;
Liquibase is a sophisticated tool for database migration that has all features that you need for professional database refactoring and versioning.  &lt;/p&gt;

&lt;p&gt;But still, if you don’t want to use liquibase, here are some alternatives.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Flyway:&lt;/strong&gt; Flyway is an open-source Apache licenced tool for database migration where you can write migrations in database-specific SQL or using Java code. For more details on Flyway, you can refer to this website. &lt;a href="https://flywaydb.org/"&gt;https://flywaydb.org/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;YUNIQL:&lt;/strong&gt; YUNIQL is also an open-source schema versioning and database migration engine that uses plain SQL scripts which can be integrated with CI/CD pipelines. If you want to check out YUNIQL, you can refer to this website. &lt;a href="https://yuniql.io/"&gt;https://yuniql.io/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>database</category>
      <category>sql</category>
      <category>tools</category>
    </item>
    <item>
      <title>Checking Out Quest DB</title>
      <dc:creator>asaf g</dc:creator>
      <pubDate>Mon, 31 Aug 2020 15:52:44 +0000</pubDate>
      <link>https://dev.to/asaf_g6/checking-out-quest-db-m5p</link>
      <guid>https://dev.to/asaf_g6/checking-out-quest-db-m5p</guid>
      <description>&lt;h2&gt;
  
  
  What is Quest DB?
&lt;/h2&gt;

&lt;p&gt;QuestDB is an open-source Time Series database that uses a column-oriented storage approach and vectored execution for simple and extremely quick query execution.&lt;br&gt;&lt;br&gt;
It was developed by QuestDB Limited in 2014.&lt;br&gt;&lt;br&gt;
It is written in Java and supports Linux, macOS and Windows as the server operating system.&lt;br&gt;&lt;br&gt;
The query language utilized for QuestDB is SQL (Structured Query Language) alongside its expansion for time series-analysis.&lt;br&gt;&lt;br&gt;
QuestDB depends on the relational data model, normally found in some of the popular relational databases like PostgreSQL, MySQL, SQL Server, Oracle, and so forth which means that each time-series estimation is recorded in its row, with a time field followed by other fields.&lt;/p&gt;

&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;p&gt;Some of the best features of QuestDB are as follows.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Time series database with a relational data model.&lt;/li&gt;
&lt;li&gt;SIMD optimized analytics&lt;/li&gt;
&lt;li&gt;Uses column-oriented storage technologies with each column stored continuously in sequential blocks&lt;/li&gt;
&lt;li&gt;It allows columns to be chosen as a designated timestamp to utilize it’s high-performance time series functions&lt;/li&gt;
&lt;li&gt;Comes with a built-in SQL optimizer&lt;/li&gt;
&lt;li&gt;InfluxDB line and Postgres wire protocol support&lt;/li&gt;
&lt;li&gt;Supports time series and relational joins&lt;/li&gt;
&lt;li&gt;It supports horizontal partitioning (by timestamps)&lt;/li&gt;
&lt;li&gt;Supports ACID &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The setting up of QuestDB can be done easily by following the &lt;a href="https://questdb.io/docs/introduction/"&gt;QuestDB documentation&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
It runs on port 9000 (by default) and provides a web console to interact with the database. The web console has a schema/table browser, query tool and visualization window where the query results can be shown either in tabular form or using graphs.&lt;/p&gt;

&lt;p&gt;Here is how the web console looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="/checking-out-quest-db/image1.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cqlr2a9Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.turtle-techies.com/checking-out-quest-db/image1.png" alt="QuestDB web console" class="screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to setup QuestDB
&lt;/h2&gt;

&lt;p&gt;If like me, you want to setup QuestDB for learning or for a development environment, I would recommend using Docker.&lt;br&gt;
Here are the instructions I used: &lt;br&gt;
&lt;a href="https://questdb.io/docs/packages/docker/"&gt; &lt;/a&gt;&lt;a href="https://questdb.io/docs/packages/docker/"&gt;https://questdb.io/docs/packages/docker/&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Your other options are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Using binaries: &lt;br&gt;
For setting up QuestDB using binaries, you can refer to QuestDB's documentation &lt;a href="https://questdb.io/docs/packages/binaries/"&gt; &lt;/a&gt;&lt;a href="https://questdb.io/docs/packages/binaries/"&gt;https://questdb.io/docs/packages/binaries/&lt;/a&gt; .  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Homebrew: &lt;br&gt;
For macOS users, QuestDB is available via Homebrew &lt;a href="https://questdb.io/docs/packages/homebrew/"&gt; &lt;/a&gt;&lt;a href="https://questdb.io/docs/packages/homebrew/"&gt;https://questdb.io/docs/packages/homebrew/&lt;/a&gt; . &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why should you choose QuestDB?
&lt;/h2&gt;

&lt;p&gt;The one thing I like most about QuestDB is that despite the fact that its engineering is planned from the ground up to be close to the hardware.&lt;br&gt;
It offers advanced execution and is additionally centered around making it simpler for designers to integrate and query.&lt;/p&gt;

&lt;p&gt;Following are the reasons you should choose QuestDB&lt;/p&gt;

&lt;h3&gt;
  
  
  Easy to set up and use
&lt;/h3&gt;

&lt;p&gt;QuestDB is a lightweight open-source database and is anything but difficult to set up without any conditions. &lt;br&gt;
It will take just a couple of minutes to download and you can begin playing with it. &lt;br&gt;
Its official website provides detailed technical documentation which makes installation, configuration and running the database very simple. &lt;br&gt;
Its web console enables us to perform real-time analytics with easy visualization using different types of charts like bar, line area etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  Supports SQL
&lt;/h3&gt;

&lt;p&gt;One reason for utilizing QuestDB is its SQL-like query language. &lt;br&gt;
On the off chance that you know about SQL, utilizing QuestDB would be simpler as it depends on SQL with its very time-series alterations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Performance
&lt;/h3&gt;

&lt;p&gt;Execution is one of the fundamental rules that ought to be thought of while picking the database. &lt;br&gt;
QuestDB offers better execution while managing time-series data like data from IoT gadgets, stock value information and DevOps measurements. &lt;br&gt;
For a database that is new in the TSDB field, it gives seemingly preferable execution over other entrenched time-series databases.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why QuestDB is not a good choice?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  New to the TSDB ecosystem
&lt;/h3&gt;

&lt;p&gt;QuestDB is a less mature product than other time-series databases like TimescaleDB and InfluxDB, which implies that there are a ton of integrations and features that are yet to be worked from the developers' side. &lt;br&gt;
So if you are searching for a well established time-series database with an extraordinary help network and discussion, QuestDB isn't there yet.&lt;/p&gt;

&lt;h3&gt;
  
  
  OLTP Support
&lt;/h3&gt;

&lt;p&gt;OLTP databases require frequent inserts, updates, and deletes with user-defined constraints to be kept up. &lt;br&gt;
If you are intending to utilize a database that likewise supports Online Transaction Processing, QuestDB is not a solid match. &lt;/p&gt;

&lt;h2&gt;
  
  
  How does it compare with other databases?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  QuestDB vs SQL Databases
&lt;/h3&gt;

&lt;p&gt;QuestDB is like a SQL database (MySQL, Oracle, PostgreSQL) however unique from multiple points of view.&lt;br&gt;&lt;br&gt;
Other relational databases can also handle time-series data but they tend to offer worse performance while dealing with common time-series operations like real-time aggregations of data.  &lt;/p&gt;

&lt;p&gt;On the other hand, QuestDB is purpose-built for fast storage and processing of time series data. &lt;br&gt;
The data model followed by QuestDB is a relational data model which means that data is stored in a table and each row in a table represents a collection of related values. &lt;br&gt;
It also follows the ACID property and supports joins like relational databases but does not allow user-defined constraints and triggers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Alternatives to QuestDB
&lt;/h3&gt;

&lt;p&gt;Some of the best alternatives to QuestDB are as follows&lt;/p&gt;

&lt;h4&gt;
  
  
  InfluxDB
&lt;/h4&gt;

&lt;p&gt;InfluxDB is an open-source time-series database designed for high-availability storage and retrieval of data.&lt;br&gt;&lt;br&gt;
It is a part of the TICK (Telegraf, InfluxDB, Chronograf, Kapacitor) stack and has a non-relational, NoSQL data model. It has SQL-like query language to handle interactions with the data&lt;/p&gt;

&lt;h4&gt;
  
  
  TimescaleDB
&lt;/h4&gt;

&lt;p&gt;Built on the top of the Postgres database, TImescaleDB is optimized for fast ingest and complex queries with full SQL support like traditional relational databases. &lt;/p&gt;

&lt;h5&gt;
  
  
  KDB+
&lt;/h5&gt;

&lt;p&gt;KDB+ is also a high performance column-store relational time-series database with in-memory abilities.&lt;br&gt;&lt;br&gt;
It is commonly used to store, analyze and process high-frequency financial time series data.&lt;/p&gt;

&lt;p&gt;I hope you enjoyed, and of course as always, feel free to comment or share.&lt;br&gt;&lt;br&gt;
Thank you for reading. &lt;/p&gt;

</description>
      <category>database</category>
      <category>sql</category>
    </item>
    <item>
      <title>Securing Your Electron App</title>
      <dc:creator>asaf g</dc:creator>
      <pubDate>Tue, 18 Aug 2020 10:33:53 +0000</pubDate>
      <link>https://dev.to/asaf_g6/securing-your-electron-app-384g</link>
      <guid>https://dev.to/asaf_g6/securing-your-electron-app-384g</guid>
      <description>&lt;p&gt;&lt;em&gt;Written by &lt;a href="https://www.turtle-techies.com/author/andres-acevedo/"&gt;Andres Acevedo&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In our &lt;a href="https://www.turtle-techies.com/multi-platform-desktop-app-with-electron"&gt;previous article&lt;/a&gt;, we explored how to create a useful Electron app focusing on functionality, but leaving aside some aspects like security and platform specific features.  &lt;/p&gt;

&lt;p&gt;In this article, we will continue from where we left, to progress in the path from a Prototype to a real world Application!  &lt;/p&gt;

&lt;p&gt;I’d like to begin with an analogy: in healthcare studies, there's an important Latin maxim: Primum non nocere, it means:&lt;br&gt;&lt;br&gt;
 "first, do no harm". Another way to state it is that, "given an existing problem, it may be better not to do something, or even to do nothing, than to risk causing more harm than good." &lt;/p&gt;

&lt;p&gt;If we are introducing security problems to our clients, it could be best to go back a bit (pun intended) and solve these vulnerabilities before adding new features to our pretty piece of software. &lt;/p&gt;
&lt;h2&gt;
  
  
  Working according to the warnings
&lt;/h2&gt;

&lt;p&gt;So, is our app secure? If we run it with &lt;code&gt;npx electron&lt;/code&gt; . and open the Developer Tools (View&amp;gt;Toggle Developer Tools), we can see that the console is giving us several security warnings:  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6T0Qz_2v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3sh6uh5hhptbrz4qpeug.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6T0Qz_2v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3sh6uh5hhptbrz4qpeug.png" alt="electron showing security warnings" width="801" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One easy way to improve our app's security is to add a special meta header to our &lt;strong&gt;index.html&lt;/strong&gt; file:&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;meta&lt;/span&gt; &lt;span class="na"&gt;http-equiv=&lt;/span&gt;&lt;span class="s"&gt;"Content-Security-Policy"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"default-src 'self'; script-src 'self'"&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 instructs the Chromium rendering engine to only run local scripts.  &lt;/p&gt;

&lt;p&gt;You can also add other allowed domains in the following way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;
Content-Security-Policy: script-src 'self' https://apis.example.com

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

&lt;/div&gt;



&lt;p&gt;If you want to learn more about CSP, check:&lt;br&gt;&lt;br&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP"&gt; &lt;/a&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP"&gt;https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Once we add that line to the header section of our website and refresh our app &lt;code&gt;(View &amp;gt; Reload)&lt;/code&gt;, we are left with just one security warning:  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--n_d_Xsa0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1sf0gpp023urv5p5n61i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--n_d_Xsa0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1sf0gpp023urv5p5n61i.png" alt="electron showing only one security warning" width="795" height="573"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Getting rid of this security warning requires that we modify our &lt;code&gt;main.js&lt;/code&gt; file and add the following &lt;code&gt;webPreference&lt;/code&gt; to our &lt;code&gt;BrowserWindow&lt;/code&gt; call:&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;webPreferences&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nl"&gt;worldSafeExecuteJavaScript&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="nx"&gt;contextIsolation&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What this does is to enforce isolation between the &lt;code&gt;Renderer World&lt;/code&gt; (Chromium renderer) and Node World. This sandboxes any malicious code run from the &lt;strong&gt;renderer&lt;/strong&gt;, reducing the possible damage of an exploited vulnerability.&lt;/p&gt;

&lt;p&gt;Once we add the code, reloading the view is not enough - as we did changes in our &lt;code&gt;main.js&lt;/code&gt; file, so we have to terminate our Electron App and relaunch it with: &lt;code&gt;npx electron&lt;/code&gt; .&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nMqT7i7e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bjtg23omqghzqmpt0p5s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nMqT7i7e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bjtg23omqghzqmpt0p5s.png" alt="electron showing console errors" width="785" height="583"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Good news:&lt;/strong&gt; we got rid of the warning.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Bad news:&lt;/strong&gt; now we have an actual error and our app does not work anymore&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Fixing the code
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Require&lt;/code&gt; is a node function, and because we configured electron to separate &lt;code&gt;renderer&lt;/code&gt; and node worlds, we can not use &lt;code&gt;require()&lt;/code&gt; on our &lt;code&gt;renderer.js&lt;/code&gt; file. &lt;br&gt;
Even if we have the &lt;code&gt;nodeIntegration: true&lt;/code&gt; setting.&lt;br&gt;&lt;br&gt;
In fact, let's remove that setting, so our &lt;code&gt;BrowserWindow&lt;/code&gt; call in &lt;code&gt;main.js&lt;/code&gt; now looks 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;const&lt;/span&gt; &lt;span class="nx"&gt;win&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;BrowserWindow&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;800&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;webPreferences&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;worldSafeExecuteJavaScript&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="na"&gt;contextIsolation&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;blockquote&gt;
&lt;p&gt;Electron provides us with a way to use node functions in the renderer world: &lt;strong&gt;Preload scripts&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Add the following line to &lt;code&gt;webPreferences&lt;/code&gt; in our &lt;code&gt;BrowserWindow&lt;/code&gt; call on &lt;code&gt;main.js&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="nx"&gt;preload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;join&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;getAppPath&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;preload.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It 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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;win&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;BrowserWindow&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;800&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;webPreferences&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;worldSafeExecuteJavaScript&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="na"&gt;contextIsolation&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="na"&gt;preload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;join&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;getAppPath&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;preload.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Don't forget to include the path module at the beginning of &lt;code&gt;main.js&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's create the &lt;code&gt;preload.js&lt;/code&gt; file and write the following on it:&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;contextBridge&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ipcRenderer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;electron&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;contextBridge&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exposeInMainWorld&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;electron&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="na"&gt;ipcRenderer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ipcRenderer&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;As you can see on the first line, we can use the &lt;code&gt;require()&lt;/code&gt; function in &lt;code&gt;preload.js&lt;/code&gt; without problems in order to import the &lt;code&gt;ipcRenderer&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Now, we will remove the require line that is causing the error on the &lt;code&gt;renderer.js&lt;/code&gt; file:&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ipcRenderer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;electron&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;As we are not requiring &lt;code&gt;ipcRenderer&lt;/code&gt; anymore, we can not continue using it in the same way as before. &lt;br&gt;
But that's when the &lt;code&gt;contextBridge.exposeInMainWorld&lt;/code&gt; function we added on &lt;code&gt;preload.js&lt;/code&gt; comes in handy.&lt;br&gt;
Our &lt;code&gt;ipcRenderer&lt;/code&gt; can be accessed on the &lt;code&gt;rendered.js&lt;/code&gt; file by using &lt;code&gt;window.electron.ipcRenderer&lt;/code&gt;.  &lt;/p&gt;

&lt;p&gt;So it now 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;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;fileSelected&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&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;loadedFilePath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;files&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="nx"&gt;path&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&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;electron&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ipcRenderer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;read-file&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;loadedFilePath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;loadedText&lt;/span&gt;&lt;span class="dl"&gt;"&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;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fileLoader&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;change&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fileSelected&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Result:  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5ruMeLPN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wxhwk9yy3cxr8vqaqfsd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5ruMeLPN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wxhwk9yy3cxr8vqaqfsd.png" alt="electron showing console" width="798" height="598"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We've made it! Our app works again and without any security warnings!&lt;/p&gt;

&lt;p&gt;You can find the code of our Secure Text Loader on the following repo:&lt;br&gt;
&lt;a href="https://github.com/mran3/Secure-Text-File-Loader/"&gt; &lt;/a&gt;&lt;a href="https://github.com/mran3/Secure-Text-File-Loader/"&gt;https://github.com/mran3/Secure-Text-File-Loader/&lt;/a&gt; &lt;/p&gt;

</description>
    </item>
    <item>
      <title>Multi Platform Desktop App With Electron</title>
      <dc:creator>asaf g</dc:creator>
      <pubDate>Fri, 14 Aug 2020 10:17:15 +0000</pubDate>
      <link>https://dev.to/asaf_g6/multi-platform-desktop-app-with-electron-51ci</link>
      <guid>https://dev.to/asaf_g6/multi-platform-desktop-app-with-electron-51ci</guid>
      <description>&lt;p&gt;&lt;em&gt;Written by &lt;a href="https://www.turtle-techies.com/author/andres-acevedo/"&gt;Andres Acevedo&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Slack, Visual Studio Code, and Skype among others have shown us that writing performant eye-catching multi-platform apps with web technologies is not only possible but that they can compete with apps made using different frameworks as native libraries or Java.&lt;/p&gt;

&lt;p&gt;Today we will create a basic app that allows reading a text file into a text area.&lt;br&gt;&lt;br&gt;
This functionality is at the core of several apps like word processors, and code editors among others.&lt;/p&gt;
&lt;h2&gt;
  
  
  Pre Requisites
&lt;/h2&gt;

&lt;p&gt;A solid understanding of how HTML, CSS, and Javascript work together on a web page.&lt;br&gt;&lt;br&gt;
Ability to code on Javascript.&lt;br&gt;&lt;br&gt;
Node and Npm (or Yarn installed).&lt;br&gt;&lt;br&gt;
Know how to install node packages.  &lt;/p&gt;
&lt;h2&gt;
  
  
  Installing Electron
&lt;/h2&gt;

&lt;p&gt;Run&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;to initialize a new node application and fill the information requested in the terminal.&lt;/p&gt;

&lt;p&gt;Then run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; electron
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Hello Electron
&lt;/h2&gt;

&lt;p&gt;Now we will create a basic app that displays "Hello Electron" just to see the electron framework working.&lt;/p&gt;

&lt;p&gt;Create a new &lt;code&gt;main.js&lt;/code&gt; file and write the following on it:&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="c1"&gt;// We need to use require instead of import because this code runs on a node environment. &lt;/span&gt;
&lt;span class="kd"&gt;const&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;BrowserWindow&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;electron&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;createWindow&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Create the browser window.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;win&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;BrowserWindow&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;800&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;webPreferences&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;nodeIntegration&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="c1"&gt;// and load the index.html of the app.&lt;/span&gt;
  &lt;span class="nx"&gt;win&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loadFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&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="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;whenReady&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;createWindow&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// In this file you can include the rest of your app's specific main process&lt;/span&gt;
&lt;span class="c1"&gt;// code. You can also put them in separate files and require them here.&lt;/span&gt;


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

&lt;/div&gt;



&lt;p&gt;Now create a very simple index.html file:&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="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&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;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Hello Hello Electron!&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &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;h1&amp;gt;&lt;/span&gt;Hello Electron!&lt;span class="nt"&gt;&amp;lt;/h1&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;Now, let's run the &lt;code&gt;npx electron&lt;/code&gt; command on your shell to see our first electron app running.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Wwd9r9sk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/70nip7cb4qwwidqm78aa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Wwd9r9sk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/70nip7cb4qwwidqm78aa.png" alt="electron running hello" width="510" height="347"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is very nice, but can give us the impression that Electron is just a wrapper that we use on our websites to convert them to desktop applications.  &lt;/p&gt;

&lt;p&gt;Once we add some more functionality to our app, we will see that there are specific Electron topics that we need to take care of in order to create a useful piece of software.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Electron File Loader
&lt;/h2&gt;

&lt;p&gt;Let's change our HTML so we have an input file control and a textarea element:&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="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&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;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"styles.css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Text File Loader&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&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;main&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Text File Loader&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"file"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"fileLoader"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"fileLoader"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;textarea&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"loadedText"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"loadedText"&lt;/span&gt; &lt;span class="na"&gt;cols=&lt;/span&gt;&lt;span class="s"&gt;"30"&lt;/span&gt; &lt;span class="na"&gt;rows=&lt;/span&gt;&lt;span class="s"&gt;"20"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/textarea&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/main&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;We will also need some simple CSS style, so create a new file called styles.css and put the following content on it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;main&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;textarea&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;block&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;At this moment, when you run your app it should look something like this:  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lZAs4GPu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mtk4cfzwzxp6oh69lma2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lZAs4GPu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mtk4cfzwzxp6oh69lma2.png" alt="electron text file loader" width="607" height="477"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;We have the visual elements, now we need to make them interactive with Javascript. For this, we need to call a script inside our HTML using the script tag. Put it at the end of the file, just after closing the body tag:&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;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"module"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"./renderer.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;



&lt;p&gt;Of course, we need to create this new &lt;code&gt;renderer.js&lt;/code&gt; file. There we will add an event listener to detect that a file has been selected by the user:&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="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fileLoader&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;change&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fileSelected&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Now, the code for the event handler:&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ipcRenderer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;electron&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="kd"&gt;function&lt;/span&gt;  &lt;span class="nx"&gt;fileSelected&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&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;loadedFilePath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;files&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="nx"&gt;path&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&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;electron&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ipcRenderer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;read-file&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;loadedFilePath&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;This kind of function should be familiar if you are a web Javascript developer, except for this line:&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;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&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;electron&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ipcRenderer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;read-file&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;loadedFilePath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Usually, the code of Electron apps runs in two different isolated contexts: &lt;/p&gt;

&lt;p&gt;The rendered context is the JavaScript code that is interpreted by a &lt;code&gt;WebView&lt;/code&gt; provided by Electron and the main context is a node environment where you can make use of some native desktop functionalities (like loading files from the filesystem).  &lt;/p&gt;

&lt;p&gt;&lt;code&gt;ipcRenderer&lt;/code&gt; is an &lt;em&gt;EventEmitter&lt;/em&gt;. It provides a few methods so you can send synchronous and asynchronous messages from the render process (web page) to the main process.  &lt;/p&gt;

&lt;p&gt;We are sending the 'read-file' message, but we need another piece of code to receive this message, right?  &lt;/p&gt;

&lt;p&gt;Of course! That is what the next code is about, write it into your app.js file:&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;ipcMain&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;read-file&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;ipcEvent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;path&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;path&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Load: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;        
        &lt;span class="c1"&gt;//Here we will add the necessary code for loading the file.&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;blockquote&gt;
&lt;p&gt;Don't forget to require ipcMain from electron at the beginning of the &lt;strong&gt;main.js&lt;/strong&gt; file&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&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="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;BrowserWindow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ipcMain&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;electron&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you check in the console (your terminal as the handle is executed in the main context).&lt;br&gt;&lt;br&gt;
You will see that it prints out the name of the file that we have selected.  &lt;/p&gt;

&lt;p&gt;Loading and returning the file contents is a two-liner using &lt;strong&gt;promises&lt;/strong&gt; along with &lt;code&gt;async&lt;/code&gt; and &lt;code&gt;await&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="nx"&gt;ipcMain&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;read-file&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;ipcEvent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;path&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;path&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Load: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;path&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;loadedText&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;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf-8&lt;/span&gt;&lt;span class="dl"&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;loadedText&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;blockquote&gt;
&lt;p&gt;Don't forget to require the promise ready version of the &lt;code&gt;fs&lt;/code&gt; module at the beginning of &lt;strong&gt;main.js&lt;/strong&gt; .  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now that we have our data, let's go back to our &lt;code&gt;renderer.js&lt;/code&gt; file and show them in the text area adding the following line to our &lt;code&gt;fileSelected&lt;/code&gt; function:&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;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;fi&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/electron-1/text-file.png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_blank&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/electron-1/text-file.png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;alt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;electron text file loader&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;screenshot&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/a&amp;gt;leSelected&lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;e&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;{   &lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loadedFilePath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;files&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="nx"&gt;path&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;data&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;ipcRenderer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;read-file&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;loadedFilePath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;loadedText&lt;/span&gt;&lt;span class="dl"&gt;"&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;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Voilà! You have coded a simple but functional app with Electron.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IC0bYz3Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u056co0wfhajsxct7q4l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IC0bYz3Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u056co0wfhajsxct7q4l.png" alt="a working electron text file loader" width="807" height="490"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can check out the source code of this example on:&lt;br&gt;&lt;br&gt;
&lt;a href="https://github.com/mran3/Text-File-Loader"&gt; &lt;/a&gt;&lt;a href="https://github.com/mran3/Text-File-Loader"&gt;https://github.com/mran3/Text-File-Loader&lt;/a&gt; &lt;/p&gt;

</description>
      <category>electron</category>
    </item>
    <item>
      <title>Evolution of Serverless Technologies</title>
      <dc:creator>asaf g</dc:creator>
      <pubDate>Sat, 25 Jul 2020 17:01:18 +0000</pubDate>
      <link>https://dev.to/asaf_g6/evolution-of-serverless-technologies-1md4</link>
      <guid>https://dev.to/asaf_g6/evolution-of-serverless-technologies-1md4</guid>
      <description>&lt;p&gt;Written by &lt;a href="https://www.turtle-techies.com/author/nipuna-dilhara/"&gt;Nipuna Dilhara&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it all started - Datacenters
&lt;/h2&gt;

&lt;p&gt;When it comes to the modern era, deploying web services has become a common requirement that needs minimal effort. However, it wasn’t the case a few decades ago.&lt;br&gt;&lt;br&gt;
In the late 90s, the internet was a trending topic among people due to the emergence of web applications. It was a fascinating idea to make the data available online and available from anywhere from the world.  &lt;/p&gt;

&lt;p&gt;During this period, companies started to move their services as monolithic web applications and deployed and hosted in bulky and massive physical servers with local data centers. However, deploying monolithic applications and maintaining physical servers required a lot of work. They needed a considerable amount of hardware components. Delivering, assembling, and configuring them required a lot of time and expertise.   &lt;/p&gt;

&lt;p&gt;The hardware components were needed to be delivered, assembled, and configured which was time-consuming and needed specific domain expertise that wasn't common in those days. It was the opposite of what we are experiencing today.  &lt;/p&gt;

&lt;p&gt;As time goes, the amount of data to be processed gradually increased due to the advancements of new technologies and more importantly due to the improvements of businesses and their use cases. More complex data types such as relational data, graphical representations, and document-oriented data came into play. Hence, using traditional approaches based on local servers was not an option anymore. Due to these reasons, businesses started to move towards running several environments on single hosting services to utilize the hardware and maintenance efforts.  &lt;/p&gt;

&lt;p&gt;The concept of Network-Attached Storage (NAS) was the first such approach towards shared hosting services. It was simply a file storage server attached to a computer network that facilitates access of data to a large and diverse group of clients.  &lt;/p&gt;

&lt;p&gt;Even though the NAS was an effective solution for the problem, the deployment, and required resources were highly expensive. As a result, the small and medium-sized companies could not afford to move into NAS based solutions.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction of Cloud Computing
&lt;/h2&gt;

&lt;p&gt;With the further advancements of technologies, the concept of using Virtual Machines (VM) surfaced as a much affordable and flexible approach. As the name indicates, the VM is a computer application that acts as a separate virtual computer inside the same computer. Hence it allows users to run different operating systems with the required applications and configurations inside the same physical machine. During the 1990s, these concepts provided the fundamental of developing necessary computer infrastructure for the initiation of cloud computing concepts.  &lt;/p&gt;

&lt;p&gt;When the required technological background was being built, Amazon launched the Amazon Web Services - Elastic Computer Cloud (AWS-EC2) in the year 2006, making an evolutionary change to the direction of cloud computing. This allowed people and businesses to hire VMs to run their web services with minimal configuration cost and effort. The EC2 provided a secure and scalable computer space to run user applications through virtual servers hosted in the cloud.&lt;/p&gt;

&lt;p&gt;The EC2 consists of five key advantages over the known limitations of the traditional approach of data centers which became a common feature of later cloud computing services.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reduced labor cost&lt;/li&gt;
&lt;li&gt;Reduced risk&lt;/li&gt;
&lt;li&gt;Reduced infrastructure cost&lt;/li&gt;
&lt;li&gt;Scaling&lt;/li&gt;
&lt;li&gt;Lead time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hosting monolithic applications in local servers required extensive maintenance and management. With the arrival of cloud computing, the corresponding responsibilities were transferred to the cloud service providers which was a huge relief and advantage for businesses.  &lt;/p&gt;

&lt;p&gt;Also, cloud computing freed businesses from having the burden of any hardware failure and the expertise of handling such situations. The cloud computing services provided the required infrastructure and their repair and maintenance for less cost.  &lt;/p&gt;

&lt;p&gt;In the early days, businesses had to go through the troublesome processes of buying more servers and related infrastructures when expanding their businesses with the growth of customer base and service. With the arrival of cloud computing, it became so much easier and cost-effective to increase and decrease the number of owning instances according to the requirement.  &lt;/p&gt;

&lt;p&gt;The significantly less deployment time of applications made cloud computing a good bargain for businesses. Also, it gave the edge for businesses over those who were still using traditional data centers based hostings.  &lt;/p&gt;

&lt;h2&gt;
  
  
  IaaS, Saas, and PaaS
&lt;/h2&gt;

&lt;p&gt;There are three popular paradigms of cloud computing which changed the way of using the infrastructure.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Infrastructure as a Service (Iaas)&lt;/li&gt;
&lt;li&gt;Software as a Service (SaaS)&lt;/li&gt;
&lt;li&gt;Platform as a Service (PaaS)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  IaaS
&lt;/h3&gt;

&lt;p&gt;Iaas was the first one to be introduced. The AWS Simple Storage Service was one of such kind which was soon followed by Google, Microsoft, and other leading IT names of the industry.  &lt;/p&gt;

&lt;p&gt;The term ‘Cloud’ was originally referred to as a public cloud which was a set of computer resources delivered by a provider and stored in a service provider’s data centers. However, due to the rise of cloud infrastructures, businesses became able to have their own data centers utilizing software such as Open Stack. Such self-hosted systems that use on-premise hardware were known as private clouds.  &lt;/p&gt;

&lt;h3&gt;
  
  
  PaaS
&lt;/h3&gt;

&lt;p&gt;The PasS came into play after the IaaS. As IaaS provided all the infrastructure necessities, PaaS brought an operating system and kept on top of IaaS. This freed businesses from the burden of installing operating systems and setting up relevant configurations. The cloud service provider took the responsibility of:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Operating system installation&lt;/li&gt;
&lt;li&gt;Upgrading patches&lt;/li&gt;
&lt;li&gt;Monitoring the system&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Microsoft Azure, Google App Engine, Heroku, and Elastic Beanstalk are some examples of such PaaS providers.  &lt;/p&gt;

&lt;p&gt;If a business wants to have their own PaaS, they can either host it on-premise servers, on top of a public IaaS cloud service, or use a mix of both private and public clouds which was generally referred to as a hybrid cloud.  &lt;/p&gt;

&lt;h3&gt;
  
  
  SaaS
&lt;/h3&gt;

&lt;p&gt;The Software as a Service was a successor of PaaS. As the IaaS provided the necessary infrastructure and PaaS provided an operating system to run on, SaaS was a software distribution model where the businesses can host their software applications and make them available for customers. If a customer requested a published software, the business provided the customer with access to a copy of the software with which the customer can work. The customer received all the new features and updates promptly and customer-specific details were saved on the customer’s device, on the cloud, or both.  &lt;/p&gt;

&lt;p&gt;Parallel to these cloud computing advancements, the application architectures have also evolved massively. As the monolithic applications were needed to be scaled with the time, the amount of data processing was also increased with that. This made it’s difficult to run monolithic applications within a single server. So they were moved into a more fine-grained approach where the application was broken into small manageable parts that will run in dedicated machines. This leads the path to the arrival of containers.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Containers
&lt;/h2&gt;

&lt;p&gt;A container consists of a complete run time environment that includes an application with all its dependencies, libraries, and other configuration files that are required for the successful and smooth run of the application.  &lt;/p&gt;

&lt;p&gt;The first commercial container was introduced as a feature of the Solaris 10 Unix operating system in the name “Zones”.   There are some similarities between Containers and VMs as both of them provide secure and independent space for the software application to execute. They give the impression of an individual system with its own set of administrators and users. However, unlike with virtual machines, a stack of containers can be put together on a single hosted operating system with significantly less time compared to VMs.  &lt;/p&gt;

&lt;p&gt;In the early days of containers, the community believed that the containerizing was hard to do. The arrival of Docker in the year 2013 was able to change this upside down. Docker fastly got the attention of the industry experts due to its easiness to bundle applications with everything that it requires to run. As the containers gathered attention, cloud computing service providers had to host and manage containers on behalf of businesses which eventually got the name Container as a Service (CaaS). Kubernetes, Google container engines, AWS-ECS are some well-known examples of CaaS.  &lt;/p&gt;

&lt;p&gt;Containers offered a simplified interface for developers that can be used to directly implement the code which reduced the burden of what developers needed to worry about while deploying applications. However, it was not enough. the industry experts were looking for a more simplified and convenient approach to further reduce the complexity for developers. It was this era, that the concept of serverless emerged making it possible for developers to focus only on their code and corresponding service configurations instead of worrying about everything else. With the arrival of serverless, all the burden of deploying an application into the final hosted location was transferred to the service provider.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Serverless
&lt;/h2&gt;

&lt;p&gt;The serverless architecture facilitates the developers with both Backend as a Service (BaaS) and Function as a Service (FaaS) features.&lt;br&gt;&lt;br&gt;
The BaaS allows programmers to concentrate on the front end of the application and manage backend infrastructure without building or maintaining them. The FaaS is a serverless backend service that enables developers to create modular pieces of code on the move that can be implemented in response to certain events. This approach took off the requirement of maintaining physical infrastructure and the procedure that should be followed when deploying an application to server-side spaces. Hence it further facilitated programmers to only focus on the application logic. The programmers only had to write the programming logic and upload them to the FaaS platform which would invoke the function as an executable object once an corresponding event occurred. This made the serverless to be an event-based approach where the flow of the program was determined by different events or user inputs.  &lt;/p&gt;

&lt;p&gt;Businesses got most out of these evolutionary advancements of serverless technologies. The arrival and development of serverless technologies reduced the cost and the effort required for the deployment and maintenance of business applications. When the businesses wanted to scale their operations or even change the directions of their services, they were able to do it with considerably less burden compared to monolithic applications hosted on server-side spaces. Tasks that took years to complete became less time consuming as the evolutions of serverless concepts.  &lt;/p&gt;

&lt;p&gt;The release of AWS Lambda marked a great milestone in the serverless, reducing the speed of deployment to milliseconds with greater scalability and availability. The AWS Lambda facilitated programmers to completely focus on the logical aspect of the application.  &lt;/p&gt;

&lt;p&gt;Soon the competition for the dominance of the serverless domain grew rapidly. Even though it seems like Amazon is still in lead, other services such as Microsoft and Google came into the play threatening the dominance of Amazon. However, even to the current date of 2020, Amazon is still leading the Cloud infrastructure services launching new concepts and technologies regularly.  &lt;/p&gt;

&lt;p&gt;But the race hasn't ended yet. The evolution of new serverless concepts and technologies hasn't ended yet. It’s guaranteed that there are a lot more to come. The focus on serverless technologies in the IT industry is greater than never before. Even at the university level, serverless technologies have become a trending topic that created opportunities for new projects and researches. It’s already clear that serverless technologies will become a key factor of the future IT and business world. For the moment, let’s keep our heads high and see where these technological evolutions take us.  &lt;/p&gt;

</description>
      <category>serverless</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Analyzing SSL Handshake Logs</title>
      <dc:creator>asaf g</dc:creator>
      <pubDate>Sat, 11 Jul 2020 20:15:41 +0000</pubDate>
      <link>https://dev.to/asaf_g6/analyzing-ssl-handshake-logs-2772</link>
      <guid>https://dev.to/asaf_g6/analyzing-ssl-handshake-logs-2772</guid>
      <description>&lt;h1&gt;
  
  
  Analyzing SSL handshake logs
&lt;/h1&gt;

&lt;h2&gt;
  
  
  SSL 101
&lt;/h2&gt;

&lt;p&gt;Currently, we are in an era of online businesses and for good or bad, we are in a path of becoming an online life form. Meanwhile, cyber crimes and attacks are becoming more of a threat to businesses at each passing day.  &lt;/p&gt;

&lt;p&gt;If you are an online business owner or stakeholder, one of your main goals is to create a trusted environment for your consumers. You have to win the faith of customers that their money and sensitive details are secured with you. Consumers won’t purchase unless they feel safe with their money and have the trust of receiving the purchased product or service.  &lt;/p&gt;

&lt;p&gt;In the modern era, the SSL is one of the key elements that create the foundations of trust by establishing a secure connection.&lt;/p&gt;

&lt;p&gt;The SSL ensures that the internet connection between two systems and the sensitive data transferring between those two systems is secure which prevents cyber criminals from compromising any information transferred. If you visit an SSL secured website, you will receive a visual indication as below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hnTlFIu3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/jkllsbllqwxf1eds6fuy.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hnTlFIu3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/jkllsbllqwxf1eds6fuy.jpg" alt="Search bar with padlock"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So what is this SSL?&lt;/p&gt;

&lt;p&gt;The SSL stands for Secure Socket Layer.&lt;/p&gt;

&lt;p&gt;Let me give you some insightful details on where this SSL protocol runs.&lt;/p&gt;

&lt;p&gt;You might have heard that TCP/IP (Transmission Control Protocol/Internet Protocol) governs the transport and routing of data over the internet. The HTTP protocol runs on top of TCP/IP to support application tasks such as presenting web pages and running relevant functionalities.&lt;/p&gt;

&lt;p&gt;The SSL protocol runs above the TCP/IP and below the HTTP. The SSL uses TCP/IP on behalf of HTTP and establishes an encrypted secure connection between two communicating parties (client and server). With the SSL protocol in place, an eavesdropper can only see the connection endpoints but cannot read or modify any of the actual data. Hence it protects users' sensitive data.&lt;/p&gt;

&lt;p&gt;Let’s see how the SSL does that?&lt;/p&gt;

&lt;p&gt;That is where the SSL-Handshake comes into play.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deep Dive into SSL Handshake
&lt;/h2&gt;

&lt;p&gt;The SSL-Handshake allows an SSL-enabled server to authenticate itself to an SSL-enabled client and also allows the client to authenticate itself to the remote server. During the handshake, both parties exchange important and unique information that establishes the aforementioned secured connection.&lt;/p&gt;

&lt;p&gt;There are two types of SSL-Handshakes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One-way SSL&lt;/li&gt;
&lt;li&gt;Two-way SSL (Mutual SSL)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is a major difference between these two types of handshakes.&lt;/p&gt;

&lt;p&gt;In a one-way SSL, the client validates the identity of the server whereas, in two-way SSL, both the server and the client validate the identity of each other.&lt;/p&gt;

&lt;p&gt;Let’s discuss the steps of SSL-Handshake in more detail.&lt;/p&gt;

&lt;p&gt;The SSL-Handshake mainly consists of the following steps.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Client Hello&lt;/li&gt;
&lt;li&gt;Server Hello&lt;/li&gt;
&lt;li&gt;Certificate Chain&lt;/li&gt;
&lt;li&gt;Server Key Exchange&lt;/li&gt;
&lt;li&gt;Certificate Request (only in two-way SSL)&lt;/li&gt;
&lt;li&gt;Server Hello Done&lt;/li&gt;
&lt;li&gt;Client Key Exchange&lt;/li&gt;
&lt;li&gt;Client Change Cipher Spec&lt;/li&gt;
&lt;li&gt;Client Finished&lt;/li&gt;
&lt;li&gt;Server Change Cipher Spec&lt;/li&gt;
&lt;li&gt;Server Finished&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The following diagram illustrates more on the flow.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BT6B-omh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/vzif7yura2x20mllbtns.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BT6B-omh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/vzif7yura2x20mllbtns.jpg" alt="SSL handshake breakdown"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let me explain what each step means.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Client Hello
&lt;/h3&gt;

&lt;p&gt;The first message is called ‘ClientHello’ which is sent from the client to the server. ClientHello is responsible for sending the fundamental details required by the server to establish a secure connection.&lt;br&gt;
The ClientHello message carries the details such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SSL or TLS version&lt;/li&gt;
&lt;li&gt;Cryptographic algorithms&lt;/li&gt;
&lt;li&gt;Data compression methods supported by the client&lt;/li&gt;
&lt;li&gt;Client random&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The given handshake logs show that the ClientHello has been sent with TLS v1.2 which tells the server of the supported and preferred TLS version. Also, it shows the list of ciphers that are supported by the client.&lt;/p&gt;

&lt;p&gt;Forgot to mention. &lt;/p&gt;

&lt;p&gt;The TLS stands for Transport Layer Security who is the successor of SSL. The later versions of SSL come under the TLS.&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="k"&gt;***&lt;/span&gt; ClientHello, TLSv1.2
RandomCookie:  GMT: 1593979669 bytes &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 106, 130, 143, 152, 153, 26, 144, 152, 168, 252, 70, 107, 162, 143, 98, 21, 191, 157, 185, 58, 130, 231, 165, 65, 33, 110, 224, 91 &lt;span class="o"&gt;}&lt;/span&gt;
Session ID:  &lt;span class="o"&gt;{}&lt;/span&gt;
Cipher Suites: &lt;span class="o"&gt;[&lt;/span&gt;TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLS_RSA_WITH_AES_256_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_DSS_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_DSS_WITH_AES_128_GCM_SHA256]
Compression Methods:  &lt;span class="o"&gt;{&lt;/span&gt; 0 &lt;span class="o"&gt;}&lt;/span&gt;
Extension elliptic_curves, curve names: &lt;span class="o"&gt;{&lt;/span&gt;secp256r1, secp384r1, secp521r1, sect283k1, sect283r1, sect409k1, sect409r1, sect571k1, sect571r1, secp256k1&lt;span class="o"&gt;}&lt;/span&gt;
Extension ec_point_formats, formats: &lt;span class="o"&gt;[&lt;/span&gt;uncompressed]
Extension signature_algorithms, signature_algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA256withDSA, SHA224withECDSA, SHA224withRSA, SHA224withDSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA
Extension extended_master_secret
Extension renegotiation_info, renegotiated_connection: &amp;lt;empty&amp;gt;
&lt;span class="k"&gt;***&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the server receives this message, it selects a suitable cipher suite that it supports from the given cipher suite list by the client. The server will ignore other ciphers that are not recognized or supported. The selection process that happens here leads to the second step, ServerHello.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Server Hello
&lt;/h3&gt;

&lt;p&gt;As the name indicates, the ServerHello is sent by the server. The ServerHello message tells the client what are the connection parameters that have been selected by the server from the provided list.&lt;/p&gt;

&lt;p&gt;The server considers the received TLS version with the ClientHello and selects the highest supported version which is equal or lower to the client's suggestion. Also, it will select a cipher suite from the presented list of ciphers.&lt;/p&gt;

&lt;p&gt;Generally, the ServerHello consists of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Agreed SSL/TLS version&lt;/li&gt;
&lt;li&gt;Session ID&lt;/li&gt;
&lt;li&gt;Agreed cipher suite and other relevant details&lt;/li&gt;
&lt;li&gt;Server random
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;***&lt;/span&gt; ServerHello, TLSv1.2
RandomCookie:  GMT: 1593979669 bytes &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 204, 192, 95, 44, 21, 64, 253, 87, 10, 239, 52, 190, 190, 61, 186, 51, 125, 16, 68, 141, 170, 91, 232, 205, 148, 128, 78, 185 &lt;span class="o"&gt;}&lt;/span&gt;
Session ID:  &lt;span class="o"&gt;{&lt;/span&gt;95, 2, 51, 21, 21, 21, 188, 149, 248, 189, 8, 38, 152, 164, 142, 100, 130, 187, 177, 23, 237, 154, 136, 93, 124, 112, 147, 126, 43, 86, 219, 51&lt;span class="o"&gt;}&lt;/span&gt;
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
Compression Method: 0
Extension renegotiation_info, renegotiated_connection: &amp;lt;empty&amp;gt;
Extension extended_master_secret
&lt;span class="k"&gt;***&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the client and server don’t have any common attributes the SSL handshake fails at this point.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Server Certificate Chain
&lt;/h3&gt;

&lt;p&gt;The Certificate Chain message is sent by the server along with the ServerHello. This particular message consists of the server's SSL certificate and it’s the intermediate certificate chain.&lt;/p&gt;

&lt;p&gt;To establish the trust between both parties, the server should have a valid SSL certificate signed by a Certificate Authority (CA).&lt;/p&gt;

&lt;p&gt;Once the certificate is received, the client contacts the server's CA and verifies the server's digital certificate thus confirming the authenticity of the server. The verification process might consist of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Validating the certificate’s digital signature&lt;/li&gt;
&lt;li&gt;Verifying the certificate chain&lt;/li&gt;
&lt;li&gt;Checking for certificate details such as domain name, expiration date, etc.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;***&lt;/span&gt; Certificate chain
chain &lt;span class="o"&gt;[&lt;/span&gt;0] &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;
  Version: V3
  Subject: &lt;span class="nv"&gt;CN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ActiveMQ Artemis Server, &lt;span class="nv"&gt;OU&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Artemis, &lt;span class="nv"&gt;O&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ActiveMQ, &lt;span class="nv"&gt;L&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;AMQ, &lt;span class="nv"&gt;ST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;AMQ, &lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;AMQ
  Signature Algorithm: SHA256withRSA, OID &lt;span class="o"&gt;=&lt;/span&gt; 1.2.840.113549.1.1.11

  Key:  Sun RSA public key, 2048 bits
  modulus: 17909370440277738952478021743432069490529460393959126050805622971590660765692586361919607268411957926196894593987779661515762234267984346200511739419991266042217515340629051394016939807213747552584949772262005902231184424962174373631762755583097509054166650866644125680436982880019781047492697566821940066615518316518157033101020228431401518000223024317668304190076399662045036184270398732773568597958342161459714296835776954926256734783011948914891588288449919569310898632115411415768934785779564943363123191032516179643589537811762899108471543653043311642283642184737727344704476726058553680310548513037215719011553
  public exponent: 65537
  Validity: &lt;span class="o"&gt;[&lt;/span&gt;From: Sun Jul 05 22:36:37 IST 2020,
               To: Sat Oct 03 22:36:37 IST 2020]
  Issuer: &lt;span class="nv"&gt;CN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ActiveMQ Artemis Server, &lt;span class="nv"&gt;OU&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Artemis, &lt;span class="nv"&gt;O&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ActiveMQ, &lt;span class="nv"&gt;L&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;AMQ, &lt;span class="nv"&gt;ST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;AMQ, &lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;AMQ
  SerialNumber: &lt;span class="o"&gt;[&lt;/span&gt;    341a9018]

Certificate Extensions: 1
&lt;span class="o"&gt;[&lt;/span&gt;1]: ObjectId: 2.5.29.14 &lt;span class="nv"&gt;Criticality&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false
&lt;/span&gt;SubjectKeyIdentifier &lt;span class="o"&gt;[&lt;/span&gt;
KeyIdentifier &lt;span class="o"&gt;[&lt;/span&gt;
0000: 19 D8 C4 B1 B1 85 FA E1   65 97 80 90 EF 6C AE 56  ........e....l.V
0010: 14 6E DA E1                                        .n..
&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;]&lt;/span&gt;
  Algorithm: &lt;span class="o"&gt;[&lt;/span&gt;SHA256withRSA]
  Signature:
0000: 44 E5 D4 3F E8 7C 15 E7   B1 E8 F0 45 AB A3 EA 77  D..?.......E...w
0010: 1D 67 3C FC 5B 95 D0 98   F1 B9 28 6C E4 FC D1 6B  .g&amp;lt;.[.....&lt;span class="o"&gt;(&lt;/span&gt;l...k
0020: CD 7D 9F C3 4C D8 8F CB   E1 A1 63 24 EC E5 A3 5B  ....L.....c&lt;span class="nv"&gt;$.&lt;/span&gt;..[
0030: E6 18 12 46 7D 0F E4 14   25 08 B8 3B AB AF E2 CE  ...F....%..&lt;span class="p"&gt;;&lt;/span&gt;....
0040: A3 FE 93 8E 88 EB 97 62   59 71 3D 5D 92 D0 99 55  .......bYq&lt;span class="o"&gt;=]&lt;/span&gt;...U
0050: 68 E3 13 1A 7E AD 41 9E   32 DD C0 58 C7 08 81 E4  h.....A.2..X....
0060: C7 8B CF 57 69 A8 0C EA   74 5F 45 8C 6E D9 E2 D1  ...Wi...t_E.n...
0070: B6 E4 B4 D2 5F D0 BD FA   BA CB 98 7B B6 1D 9D E4  ...._...........
0080: 45 DA C9 09 19 71 BD B4   7C 44 CE 6A 48 13 75 A1  E....q...D.jH.u.
0090: 6D DD DC 48 65 0E 05 3B   BA AF 63 42 2E 9F 3B 29  m..He..&lt;span class="p"&gt;;&lt;/span&gt;..cB..&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
00A0: FE 8E 3D 07 03 04 C4 D7   65 DB 7A FA 45 C1 62 6B  ..&lt;span class="o"&gt;=&lt;/span&gt;.....e.z.E.bk
00B0: E8 E7 D1 A7 8E 6F 0D 1D   7F 3E 83 66 75 5B 60 45  .....o...&amp;gt;.fu[&lt;span class="sb"&gt;`&lt;/span&gt;E
00C0: 0E BC A1 8B B3 2D 50 1A   E5 3D 02 A5 37 D6 76 DB  .....-P..&lt;span class="o"&gt;=&lt;/span&gt;..7.v.
00D0: 5A A5 EE 26 B1 06 DC 57   F4 68 3F DA 0F C9 D4 30  Z..&amp;amp;...W.h?....0
00E0: BA B0 DA AD 94 24 B4 15   FF E5 DC 6E 1D 5D F9 58  .....&lt;span class="nv"&gt;$.&lt;/span&gt;....n.].X
00F0: D4 ED 31 9C 11 C0 C9 E8   29 5D F0 45 AF 93 9B CB  ..1.....&lt;span class="o"&gt;)]&lt;/span&gt;.E....

&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;***&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the client finds a valid certificate, you will receive a ‘Found trusted certificate’ message followed by the ‘Certificate chain’ at the client side logs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Found trusted certificate:
&lt;span class="o"&gt;[&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;
  Version: V3
  Subject: &lt;span class="nv"&gt;CN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ActiveMQ Artemis Server, &lt;span class="nv"&gt;OU&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Artemis, &lt;span class="nv"&gt;O&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ActiveMQ, &lt;span class="nv"&gt;L&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;AMQ, &lt;span class="nv"&gt;ST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;AMQ, &lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;AMQ
  Signature Algorithm: SHA256withRSA, OID &lt;span class="o"&gt;=&lt;/span&gt; 1.2.840.113549.1.1.11

  Key:  Sun RSA public key, 2048 bits
  modulus: 17909370440277738952478021743432069490529460393959126050805622971590660765692586361919607268411957926196894593987779661515762234267984346200511739419991266042217515340629051394016939807213747552584949772262005902231184424962174373631762755583097509054166650866644125680436982880019781047492697566821940066615518316518157033101020228431401518000223024317668304190076399662045036184270398732773568597958342161459714296835776954926256734783011948914891588288449919569310898632115411415768934785779564943363123191032516179643589537811762899108471543653043311642283642184737727344704476726058553680310548513037215719011553
  public exponent: 65537
  Validity: &lt;span class="o"&gt;[&lt;/span&gt;From: Sun Jul 05 22:36:37 IST 2020,
               To: Sat Oct 03 22:36:37 IST 2020]
  Issuer: &lt;span class="nv"&gt;CN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ActiveMQ Artemis Server, &lt;span class="nv"&gt;OU&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Artemis, &lt;span class="nv"&gt;O&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ActiveMQ, &lt;span class="nv"&gt;L&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;AMQ, &lt;span class="nv"&gt;ST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;AMQ, &lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;AMQ
  SerialNumber: &lt;span class="o"&gt;[&lt;/span&gt;    341a9018]

Certificate Extensions: 1
&lt;span class="o"&gt;[&lt;/span&gt;1]: ObjectId: 2.5.29.14 &lt;span class="nv"&gt;Criticality&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false
&lt;/span&gt;SubjectKeyIdentifier &lt;span class="o"&gt;[&lt;/span&gt;
KeyIdentifier &lt;span class="o"&gt;[&lt;/span&gt;
0000: 19 D8 C4 B1 B1 85 FA E1   65 97 80 90 EF 6C AE 56  ........e....l.V
0010: 14 6E DA E1                                        .n..
&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;]&lt;/span&gt;
  Algorithm: &lt;span class="o"&gt;[&lt;/span&gt;SHA256withRSA]
  Signature:
0000: 44 E5 D4 3F E8 7C 15 E7   B1 E8 F0 45 AB A3 EA 77  D..?.......E...w
0010: 1D 67 3C FC 5B 95 D0 98   F1 B9 28 6C E4 FC D1 6B  .g&amp;lt;.[.....&lt;span class="o"&gt;(&lt;/span&gt;l...k
0020: CD 7D 9F C3 4C D8 8F CB   E1 A1 63 24 EC E5 A3 5B  ....L.....c&lt;span class="nv"&gt;$.&lt;/span&gt;..[
0030: E6 18 12 46 7D 0F E4 14   25 08 B8 3B AB AF E2 CE  ...F....%..&lt;span class="p"&gt;;&lt;/span&gt;....
0040: A3 FE 93 8E 88 EB 97 62   59 71 3D 5D 92 D0 99 55  .......bYq&lt;span class="o"&gt;=]&lt;/span&gt;...U
0050: 68 E3 13 1A 7E AD 41 9E   32 DD C0 58 C7 08 81 E4  h.....A.2..X....
0060: C7 8B CF 57 69 A8 0C EA   74 5F 45 8C 6E D9 E2 D1  ...Wi...t_E.n...
0070: B6 E4 B4 D2 5F D0 BD FA   BA CB 98 7B B6 1D 9D E4  ...._...........
0080: 45 DA C9 09 19 71 BD B4   7C 44 CE 6A 48 13 75 A1  E....q...D.jH.u.
0090: 6D DD DC 48 65 0E 05 3B   BA AF 63 42 2E 9F 3B 29  m..He..&lt;span class="p"&gt;;&lt;/span&gt;..cB..&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
00A0: FE 8E 3D 07 03 04 C4 D7   65 DB 7A FA 45 C1 62 6B  ..&lt;span class="o"&gt;=&lt;/span&gt;.....e.z.E.bk
00B0: E8 E7 D1 A7 8E 6F 0D 1D   7F 3E 83 66 75 5B 60 45  .....o...&amp;gt;.fu[&lt;span class="sb"&gt;`&lt;/span&gt;E
00C0: 0E BC A1 8B B3 2D 50 1A   E5 3D 02 A5 37 D6 76 DB  .....-P..&lt;span class="o"&gt;=&lt;/span&gt;..7.v.
00D0: 5A A5 EE 26 B1 06 DC 57   F4 68 3F DA 0F C9 D4 30  Z..&amp;amp;...W.h?....0
00E0: BA B0 DA AD 94 24 B4 15   FF E5 DC 6E 1D 5D F9 58  .....&lt;span class="nv"&gt;$.&lt;/span&gt;....n.].X
00F0: D4 ED 31 9C 11 C0 C9 E8   29 5D F0 45 AF 93 9B CB  ..1.....&lt;span class="o"&gt;)]&lt;/span&gt;.E....

&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Server Key Exchange
&lt;/h3&gt;

&lt;p&gt;The ‘ServerKeyExchange’ message is an optional message which is sent by the server to the client. The client uses the details received from the Server Key Exchange message to generate the pre-master secret.&lt;/p&gt;

&lt;p&gt;This message is only required in the Elliptic Curve Diffie-Hellman (ECDH) key exchange algorithm and won’t be seen in other mechanisms such as RSA key exchange, which don't require the information from the server to generate the pre-master secret. The ECDH key exchange algorithm sends the following public key details to the client.&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="k"&gt;***&lt;/span&gt; ECDH ServerKeyExchange
Signature Algorithm SHA512withRSA
Server key: Sun EC public key, 256 bits
  public x coord: 46057439580226412250665263866147684562887286117348620148026818665523810505319
  public y coord: 25930488906832570201561097323128777249979681591509199039675514975479400287814
  parameters: secp256r1 &lt;span class="o"&gt;[&lt;/span&gt;NIST P-256, X9.62 prime256v1] &lt;span class="o"&gt;(&lt;/span&gt;1.2.840.10045.3.1.7&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s discuss the differences between these algorithms and handshakes based on them later.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Certificate Request
&lt;/h3&gt;

&lt;p&gt;The ‘CertificateRequest’ message is the first indication we get to differentiate the one-way SSL from the two-way SSL. During the one-way SSL, the client validates the authenticity of the server. The authenticity of the client is not checked. However, in two-way SSL, both parties validate the authenticity of each other.&lt;/p&gt;

&lt;p&gt;So how does the server validate the client?&lt;/p&gt;

&lt;p&gt;It’s kind of the same as how the client does it.&lt;/p&gt;

&lt;p&gt;At this step, the server sends the CertificateRequest with the details of expected certificate type, certificate signature algorithms, and certificate authorities. It’s the client's responsibility to send the certificate from its arsenal to the server matching the requirement. However, there is a wild card at this step. If the server sends an empty list of certificate authorities, depending on the client's implementation, it can decide whether to send the certificate or not.&lt;/p&gt;

&lt;p&gt;Here is what a Certificate Request looks like.&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="k"&gt;***&lt;/span&gt; CertificateRequest
Cert Types: RSA, DSS, ECDSA
Supported Signature Algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA256withDSA, SHA224withECDSA, SHA224withRSA, SHA224withDSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA
Cert Authorities:
&amp;lt;&lt;span class="nv"&gt;CN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;EI Server, &lt;span class="nv"&gt;OU&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;EI, &lt;span class="nv"&gt;O&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;EI, &lt;span class="nv"&gt;L&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;EI, &lt;span class="nv"&gt;ST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;EI, &lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;EI&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The client sends its certificate chain matching to the requirements sent in the Certificate Request.&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="k"&gt;***&lt;/span&gt; Certificate chain
chain &lt;span class="o"&gt;[&lt;/span&gt;0] &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;
  Version: V3
  Subject: &lt;span class="nv"&gt;CN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;EI Server, &lt;span class="nv"&gt;OU&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;EI, &lt;span class="nv"&gt;O&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;EI, &lt;span class="nv"&gt;L&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;EI, &lt;span class="nv"&gt;ST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;EI, &lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;EI
  Signature Algorithm: SHA256withRSA, OID &lt;span class="o"&gt;=&lt;/span&gt; 1.2.840.113549.1.1.11

  Key:  Sun RSA public key, 2048 bits
  modulus: 20633040407737278567218634330232059050042226479044722496122452505410479273023117031844484746505155564073294892298093888208868315188456270185531088712664441886338425740008444649208646876917816694847967760308554699673706712637838857175549988647511729487971524875773472297556010021422655352423126217625806863759012805189832944776623955038735096318822704111503458955521102855569127337450070103240845157800531714174178998060010010408282365398717630638484524135245861883501920626423778221475087217057744850665905219857063710661918813533021515797130163876841737728794450828239304431761997536237765605147373975769055502409267
  public exponent: 65537
  Validity: &lt;span class="o"&gt;[&lt;/span&gt;From: Sun Jul 05 23:32:01 IST 2020,
               To: Sat Oct 03 23:32:01 IST 2020]
  Issuer: &lt;span class="nv"&gt;CN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;EI Server, &lt;span class="nv"&gt;OU&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;EI, &lt;span class="nv"&gt;O&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;EI, &lt;span class="nv"&gt;L&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;EI, &lt;span class="nv"&gt;ST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;EI, &lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;EI
  SerialNumber: &lt;span class="o"&gt;[&lt;/span&gt;    3ded1c63]

Certificate Extensions: 1
&lt;span class="o"&gt;[&lt;/span&gt;1]: ObjectId: 2.5.29.14 &lt;span class="nv"&gt;Criticality&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false
&lt;/span&gt;SubjectKeyIdentifier &lt;span class="o"&gt;[&lt;/span&gt;
KeyIdentifier &lt;span class="o"&gt;[&lt;/span&gt;
0000: 9C 15 A6 4E AC 34 89 2A   8D AD 4E 9A 3B 56 81 73  ...N.4.&lt;span class="k"&gt;*&lt;/span&gt;..N.&lt;span class="p"&gt;;&lt;/span&gt;V.s
0010: 05 A3 40 4E                                        ..@N
&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;]&lt;/span&gt;
  Algorithm: &lt;span class="o"&gt;[&lt;/span&gt;SHA256withRSA]
  Signature:
0000: 5A E1 C2 5B 71 AC 72 50   D8 DE 0E 80 10 10 A6 B4  Z..[q.rP........
0010: D6 EC 39 2E DF 24 1D 81   5E E2 39 0F C0 C2 49 CC  ..9..&lt;span class="nv"&gt;$.&lt;/span&gt;.^.9...I.
0020: EE D9 5C 44 0A 07 26 23   EE 7E FC C0 32 01 7C 48  ..&lt;span class="se"&gt;\D&lt;/span&gt;..&amp;amp;#....2..H
0030: 4C CB 7D 56 CB F9 42 1D   75 06 3B 92 1B 8D DE 45  L..V..B.u.&lt;span class="p"&gt;;&lt;/span&gt;....E
0040: 4E 66 B6 5C 36 C2 07 1F   1C 7D D9 BC 09 FE F1 91  Nf.&lt;span class="se"&gt;\6&lt;/span&gt;...........
0050: BB 6B 3D 3B F9 5F 86 FB   B1 27 33 CD D0 5C 4F 5F  .k&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;._...&lt;span class="s1"&gt;'3..\O_
0060: 7A 9D 18 41 E3 32 BA 17   58 23 26 29 F2 A9 AE 00  z..A.2..X#&amp;amp;)....
0070: F7 39 64 37 89 D1 B9 D3   90 94 63 68 99 85 D7 22  .9d7......ch..."
0080: 39 E2 E8 BE BB EA 56 17   AF FC 24 14 3A 6C 23 8F  9.....V...$.:l#.
0090: E6 EC 97 A1 CA 8B 1F 7A   D7 E1 30 57 EE 92 F8 9D  .......z..0W....
00A0: 34 2E D4 CD 86 4C 19 B7   B8 3D 5B 0B 28 32 28 4D  4....L...=[.(2(M
00B0: FA AA 40 38 7D 1B 19 24   67 74 CC AD 82 CA 9E A5  ..@8...$gt......
00C0: 3B A5 36 A7 D7 B0 74 AC   96 8B 49 0B E8 5F E1 EB  ;.6...t...I.._..
00D0: 97 BB A1 DF B8 A6 8C 04   C0 1B 83 02 D2 5E F7 91  .............^..
00E0: 62 01 FC F9 35 81 4A BE   0A DF EE 78 8B 6D 9D 8E  b...5.J....x.m..
00F0: F9 3D 61 3E 93 F0 19 42   A3 7A 7F F8 B5 DF 42 F1  .=a&amp;gt;...B.z....B.

]
***
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the server finds a valid certificate, you will receive a ‘Found trusted certificate’ message followed by the ‘Certificate chain’ message at the server side logs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Found trusted certificate:
&lt;span class="o"&gt;[&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;
  Version: V3
  Subject: &lt;span class="nv"&gt;CN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;EI Server, &lt;span class="nv"&gt;OU&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;EI, &lt;span class="nv"&gt;O&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;EI, &lt;span class="nv"&gt;L&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;EI, &lt;span class="nv"&gt;ST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;EI, &lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;EI
  Signature Algorithm: SHA256withRSA, OID &lt;span class="o"&gt;=&lt;/span&gt; 1.2.840.113549.1.1.11

  Key:  Sun RSA public key, 2048 bits
  modulus: 20633040407737278567218634330232059050042226479044722496122452505410479273023117031844484746505155564073294892298093888208868315188456270185531088712664441886338425740008444649208646876917816694847967760308554699673706712637838857175549988647511729487971524875773472297556010021422655352423126217625806863759012805189832944776623955038735096318822704111503458955521102855569127337450070103240845157800531714174178998060010010408282365398717630638484524135245861883501920626423778221475087217057744850665905219857063710661918813533021515797130163876841737728794450828239304431761997536237765605147373975769055502409267
  public exponent: 65537
  Validity: &lt;span class="o"&gt;[&lt;/span&gt;From: Sun Jul 05 23:32:01 IST 2020,
               To: Sat Oct 03 23:32:01 IST 2020]
  Issuer: &lt;span class="nv"&gt;CN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;EI Server, &lt;span class="nv"&gt;OU&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;EI, &lt;span class="nv"&gt;O&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;EI, &lt;span class="nv"&gt;L&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;EI, &lt;span class="nv"&gt;ST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;EI, &lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;EI
  SerialNumber: &lt;span class="o"&gt;[&lt;/span&gt;    3ded1c63]

Certificate Extensions: 1
&lt;span class="o"&gt;[&lt;/span&gt;1]: ObjectId: 2.5.29.14 &lt;span class="nv"&gt;Criticality&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false
&lt;/span&gt;SubjectKeyIdentifier &lt;span class="o"&gt;[&lt;/span&gt;
KeyIdentifier &lt;span class="o"&gt;[&lt;/span&gt;
0000: 9C 15 A6 4E AC 34 89 2A   8D AD 4E 9A 3B 56 81 73  ...N.4.&lt;span class="k"&gt;*&lt;/span&gt;..N.&lt;span class="p"&gt;;&lt;/span&gt;V.s
0010: 05 A3 40 4E                                        ..@N
&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;]&lt;/span&gt;
  Algorithm: &lt;span class="o"&gt;[&lt;/span&gt;SHA256withRSA]
  Signature:
0000: 5A E1 C2 5B 71 AC 72 50   D8 DE 0E 80 10 10 A6 B4  Z..[q.rP........
0010: D6 EC 39 2E DF 24 1D 81   5E E2 39 0F C0 C2 49 CC  ..9..&lt;span class="nv"&gt;$.&lt;/span&gt;.^.9...I.
0020: EE D9 5C 44 0A 07 26 23   EE 7E FC C0 32 01 7C 48  ..&lt;span class="se"&gt;\D&lt;/span&gt;..&amp;amp;#....2..H
0030: 4C CB 7D 56 CB F9 42 1D   75 06 3B 92 1B 8D DE 45  L..V..B.u.&lt;span class="p"&gt;;&lt;/span&gt;....E
0040: 4E 66 B6 5C 36 C2 07 1F   1C 7D D9 BC 09 FE F1 91  Nf.&lt;span class="se"&gt;\6&lt;/span&gt;...........
0050: BB 6B 3D 3B F9 5F 86 FB   B1 27 33 CD D0 5C 4F 5F  .k&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;._...&lt;span class="s1"&gt;'3..\O_
0060: 7A 9D 18 41 E3 32 BA 17   58 23 26 29 F2 A9 AE 00  z..A.2..X#&amp;amp;)....
0070: F7 39 64 37 89 D1 B9 D3   90 94 63 68 99 85 D7 22  .9d7......ch..."
0080: 39 E2 E8 BE BB EA 56 17   AF FC 24 14 3A 6C 23 8F  9.....V...$.:l#.
0090: E6 EC 97 A1 CA 8B 1F 7A   D7 E1 30 57 EE 92 F8 9D  .......z..0W....
00A0: 34 2E D4 CD 86 4C 19 B7   B8 3D 5B 0B 28 32 28 4D  4....L...=[.(2(M
00B0: FA AA 40 38 7D 1B 19 24   67 74 CC AD 82 CA 9E A5  ..@8...$gt......
00C0: 3B A5 36 A7 D7 B0 74 AC   96 8B 49 0B E8 5F E1 EB  ;.6...t...I.._..
00D0: 97 BB A1 DF B8 A6 8C 04   C0 1B 83 02 D2 5E F7 91  .............^..
00E0: 62 01 FC F9 35 81 4A BE   0A DF EE 78 8B 6D 9D 8E  b...5.J....x.m..
00F0: F9 3D 61 3E 93 F0 19 42   A3 7A 7F F8 B5 DF 42 F1  .=a&amp;gt;...B.z....B.

]
check handshake state: client_key_exchange[16]
update handshake state: client_key_exchange[16]
upcoming handshake states: certificate_verify[15](optional)
upcoming handshake states: client change_cipher_spec[-1]
upcoming handshake states: client finished[20]
upcoming handshake states: server change_cipher_spec[-1]
upcoming handshake states: server finished[20]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  6. Server Hello Done
&lt;/h3&gt;

&lt;p&gt;The ‘Server Hello Done’ message indicates the end of ‘Server Hello’. By this point, the server has sent over all the details required to the client and is waiting for the client's response. You will see the after the Certificate Request message.&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="k"&gt;***&lt;/span&gt; ServerHelloDone
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  7. Client Key Exchange
&lt;/h3&gt;

&lt;p&gt;At this point, the client generates a random string of bytes called ‘pre-master secret’ based on the selected key exchange method selected during the initial ‘Hello’ messages. &lt;/p&gt;

&lt;p&gt;If RSA is used, the client generates the pre-master secret. Then the client encrypts the pre-master secret with the server's public key and transmits it to the server. Only the server has the matching private key to decrypt the message and get the pre-master secret generated by the client.&lt;/p&gt;

&lt;p&gt;If the Diffie-Hellman is used, the required Diffie-Hellman parameters are transmitted to allow both client and server to generate the same pre-master secret.&lt;/p&gt;

&lt;p&gt;Please be noted that the public keys are stored on digital certificates for secure transport and sharing. Hence the client receives the server's public certificate along with a Certificate Chain message.&lt;/p&gt;

&lt;p&gt;After having the pre-master key, both sides generate the master-key, or else we can say the symmetric session key, based on it.&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="k"&gt;***&lt;/span&gt; ECDHClientKeyExchange
ECDH Public value:  &lt;span class="o"&gt;{&lt;/span&gt; 4, 155, 208, 236, 141, 18, 15, 41, 223, 46, 75, 222, 216, 4, 182, 247, 86, 18, 14, 248, 5, 121, 129, 250, 130, 84, 247, 239, 96, 115, 63, 158, 23, 130, 248, 178, 245, 86, 154, 207, 194, 82, 194, 158, 138, 4, 216, 191, 74, 185, 66, 167, 181, 231, 6, 44, 189, 8, 85, 154, 134, 217, 118, 220, 9 &lt;span class="o"&gt;}&lt;/span&gt;
SESSION KEYGEN:
PreMaster Secret:
0000: CA 05 DD 3E 70 28 0C 66   33 52 7C CA 3C 09 80 22  ...&amp;gt;p&lt;span class="o"&gt;(&lt;/span&gt;.f3R..&amp;lt;..&lt;span class="s2"&gt;"
0010: BC 09 31 C8 D4 30 0B C9   C0 0D 7E 69 0C 4E A9 BE  ..1..0.....i.N..
CONNECTION KEYGEN:
Client Nonce:
0000: 5F 02 33 15 6A 82 8F 98   99 1A 90 98 A8 FC 46 6B  _.3.j.........Fk
0010: A2 8F 62 15 BF 9D B9 3A   82 E7 A5 41 21 6E E0 5B  ..b....:...A!n.[
Server Nonce:
0000: 5F 02 33 15 CC C0 5F 2C   15 40 FD 57 0A EF 34 BE  _.3..._,.@.W..4.
0010: BE 3D BA 33 7D 10 44 8D   AA 5B E8 CD 94 80 4E B9  .=.3..D..[....N.
Master Secret:
0000: 0F 72 A0 5D A8 38 1E 2B   1C C9 09 92 15 AA CE 40  .r.].8.+.......@
0010: 22 AD DA 52 9B B9 C1 50   18 6E 0A 0E 3B C7 5D D5  "&lt;/span&gt;..R...P.n..&lt;span class="p"&gt;;&lt;/span&gt;.].
0020: CE A6 6E F0 9F 07 4D 60   8D E8 6C 49 E3 DD 57 6F  ..n...M&lt;span class="sb"&gt;`&lt;/span&gt;..lI..Wo
Client MAC write Secret:
0000: 6B 3C 42 38 37 85 FE 92   CB 72 62 10 EA 78 22 33  k&amp;lt;B87....rb..x&lt;span class="s2"&gt;"3
0010: 76 D2 1D 33 A6 D3 C7 8A   83 78 F5 13 13 83 27 61  v..3.....x....'a
0020: 30 12 1D 1C E9 01 75 5D   FA 6B CE 1C 72 EE FB 9A  0.....u].k..r...
Server MAC write Secret:
0000: 85 49 6C 4D F1 9A A7 B6   C4 33 A2 6C 5D EB D0 39  .IlM.....3.l]..9
0010: 35 A7 AF 75 48 40 6E 59   F5 22 A0 37 EB B6 E9 AB  5..uH@nY."&lt;/span&gt;.7....
0020: A5 F5 00 29 37 82 5C 87   72 6D CD AC C8 38 D8 EF  ...&lt;span class="o"&gt;)&lt;/span&gt;7.&lt;span class="se"&gt;\.&lt;/span&gt;rm...8..
Client write key:
0000: 09 1D A3 90 C1 08 57 80   B5 58 16 69 F8 9E DC AB  ......W..X.i....
0010: 23 B2 47 CD 98 96 E1 27   69 64 E2 6E 68 07 EE E4  &lt;span class="c"&gt;#.G....'id.nh...&lt;/span&gt;
Server write key:
0000: 77 76 89 F8 93 EE 40 FA   1B 8B AA 31 03 34 D1 16  wv....@....1.4..
0010: 03 33 0A F3 81 65 24 20   D7 EC 8A BE 31 7F B0 8B  .3...e&lt;span class="nv"&gt;$ &lt;/span&gt;....1...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  8. Client Change Cipher Spec
&lt;/h3&gt;

&lt;p&gt;Then the client generates a ‘Change Cipher Spec’ message letting the server know that it’s going to switch to an encrypted communication based on the session key.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Thread-1 &lt;span class="o"&gt;(&lt;/span&gt;activemq-netty-threads&lt;span class="o"&gt;)&lt;/span&gt;, READ: TLSv1.2 Change Cipher Spec, length &lt;span class="o"&gt;=&lt;/span&gt; 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  9. Client Finished
&lt;/h3&gt;

&lt;p&gt;The ‘Finished’ message is sent by the client to the server indicating that the client’s side of the handshake has been completed. The client’s ‘Finished’ message is encrypted by the shared session key and it's the first message protected by it.&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="k"&gt;***&lt;/span&gt; Finished
verify_data:  &lt;span class="o"&gt;{&lt;/span&gt; 236, 172, 15, 118, 186, 177, 150, 21, 7, 82, 236, 97 &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;***&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This message consists of required data that provide the guarantee for the server that the handshake hasn’t been compromised.&lt;/p&gt;

&lt;h3&gt;
  
  
  10. Server Change Cipher Spec
&lt;/h3&gt;

&lt;p&gt;The server decrypts the received message and finds the pre-master secret sent by the client. Then it computes the session key based on the pre-master key, which will be used in the following communication.&lt;/p&gt;

&lt;p&gt;At this point, the server generates its own ‘Change Cipher Spec’ message to indicate that it’s also switching to encrypted communication.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Thread-1 &lt;span class="o"&gt;(&lt;/span&gt;activemq-netty-threads&lt;span class="o"&gt;)&lt;/span&gt;, WRITE: TLSv1.2 Change Cipher Spec, length &lt;span class="o"&gt;=&lt;/span&gt; 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  11. Server Finished
&lt;/h3&gt;

&lt;p&gt;At last, the server also generates a ‘Finished’ message encrypted by the session key. This marks the end of the server part of the communication as well as a successful SSL handshake.&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="k"&gt;***&lt;/span&gt; Finished
verify_data:  &lt;span class="o"&gt;{&lt;/span&gt; 183, 200, 213, 124, 127, 251, 136, 195, 116, 238, 43, 54 &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;***&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once this handshake is done, the server and client now can exchange messages that are symmetrically encrypted with the shared session key.&lt;/p&gt;

&lt;p&gt;Now you know about the general flow of SSL handshakes. But there can be some slight variations for it based on the used key exchange algorithm. There are mainly two key exchange algorithms used in TLS.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;RSA key exchange&lt;/li&gt;
&lt;li&gt;Diffie-Hellman key exchange&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s have a close look at both.&lt;/p&gt;

&lt;h2&gt;
  
  
  RSA vs Diffie-Hellman
&lt;/h2&gt;

&lt;p&gt;There are some fundamental differences between Diffie-Hellman and RSA. If we put in simple words, RSA can handle both the authentication based on digital signature and the secure key exchange whereas Diffie-Hellman only handles the key exchange. Hence the RSA can be named as the more capable method from the two.&lt;/p&gt;

&lt;p&gt;Often you will see that the Diffie-Hellman is often combined with Elliptic Curves making the Elliptic Curve Diffie-Hellman (ECDH). Including ECDH, there are four main branches of Diffie-Hellman.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Diffie-Hellman (DH)&lt;/li&gt;
&lt;li&gt;Diffie-Hellman Ephemeral (DHE)&lt;/li&gt;
&lt;li&gt;Elliptic Curve Diffie-Hellman (ECDH)&lt;/li&gt;
&lt;li&gt;Elliptic Curve Diffie-Hellman Ephemeral (ECDHE)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since the Diffie-Hellman is lacking the authentication part, it needs to be paired with a digital signature algorithm. Nowadays you will often see few modern variants of Diffie-Hellman such as ECDH and ECDHE are paired with Elliptic Curve Digital Signature Algorithm (ECDSA) or RSA.&lt;/p&gt;

&lt;h3&gt;
  
  
  RSA based Authentication and Key Exchange
&lt;/h3&gt;

&lt;p&gt;The authentication and key exchange processes of RSA have been entangled with each other. The key exchange is performed as a part of the RSA’s authentication process.&lt;/p&gt;

&lt;p&gt;If the RSA is used and the client receives the server certificate, a set of actions are performed to verify the validity of it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Validates the digital signature using the public key&lt;/li&gt;
&lt;li&gt;Check the certificate chain and verify that the server certificate is available in the client trust store or it descends from a root certificate in the trust store.&lt;/li&gt;
&lt;li&gt;Check the validity period of the certificate. If the certificate has been expired the handshake fails.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the certificate passes all the verifications, the client uses the public key received with the certificate to encrypt the pre-master key and send it over to the server.&lt;/p&gt;

&lt;p&gt;What if the client receives a different certificate which is yet to be valid than the actual server certificate.&lt;/p&gt;

&lt;p&gt;Since it’s a valid certificate, it passes the client’s verification of the certificate signature. But how does the client know that the server owns the private key that signed the certificate?&lt;/p&gt;

&lt;p&gt;The client sends back the pre-master key encrypted with the server’s public key. Hence, it only can be decrypted using the server’s private key. If the server can decrypt and get the correct pre-master key, it validates that the server owns the private and public key pair used in the process.&lt;/p&gt;

&lt;p&gt;That explains how the RSA based authentication happens, which lets us move for the key-exchange.&lt;/p&gt;

&lt;p&gt;Here is how it happens,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;During the Client Hello and Server Hello, both parties exchange two prime numbers called ‘client random’ and ‘server random’ respectively.&lt;/li&gt;
&lt;li&gt;The client generates the pre-master key, encrypts it using the server’s public key, and sends it over to the server.&lt;/li&gt;
&lt;li&gt;The server decrypts the received pre-master key using the corresponding private key.&lt;/li&gt;
&lt;li&gt;At this point, both parties should have client random, server random, and pre-master key.&lt;/li&gt;
&lt;li&gt;Using the aforementioned parameters, both client and server generate matching session keys.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It seems to be a good time to know how DH acts to accomplish these tasks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Diffie-Hellman based Authentication and Key Exchange
&lt;/h3&gt;

&lt;p&gt;As we have mentioned earlier, the DH cannot perform the authentication process by itself. Hence it associates with digital signature algorithms such as ECDSA or RSA.&lt;/p&gt;

&lt;p&gt;However, please be noted that, even though RSA uses the key pair for both authentication and key exchange, the DH uses the key pair only for the authentication.&lt;/p&gt;

&lt;p&gt;If the DH is in use, similar actions are performed as in the RSA by the client upon receiving the server certificate.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Validate the certificate signature&lt;/li&gt;
&lt;li&gt;Check the certificate chain&lt;/li&gt;
&lt;li&gt;Check the validity period and other relevant details&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How does the client validate the key pair?&lt;/p&gt;

&lt;p&gt;During the Client Hello and Server Hello, both parties exchange two prime numbers called ‘client random’ and ‘server random’ respectively. As we have mentioned earlier, the Server Key Exchange step is only specific to the DH handshake. Before the Server Key Exchange, the server takes the server randomly and the client random and the server's DH specific parameters and then encrypts them using the server’s private key which will work as the digital signature. Then the client uses the corresponding public key to verify that the server owns the private and public key pair used in the process.&lt;/p&gt;

&lt;p&gt;So how does the DH key exchange happen?&lt;/p&gt;

&lt;p&gt;Not like in RSA, the required parameters are transmitted to both parties to generate the same pre-master secret.&lt;/p&gt;

&lt;p&gt;Here is what happens,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Both parties exchange two prime numbers called client random (x) and server random (y) respectively during the client and server ‘Hello’ messages.&lt;/li&gt;
&lt;li&gt;The client selects a secret number called pre-master secret (a) and applies a modulo function as xa mod y. &lt;/li&gt;
&lt;li&gt;Similarly, the server selects its pre-master secret (b) and applies a modulo function as xb mod y.&lt;/li&gt;
&lt;li&gt;Let’s name the client’s result as A and server’s result as B.&lt;/li&gt;
&lt;li&gt;Both parties then exchange the value and apply another modular function. The client applies Ba mod y and the server applies Ab mod y.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the functions and values are applied correctly, both parties should have the same value which we called the session key. As we already know, the later communication between these two parties will be encrypted using the retrieved session key.&lt;/p&gt;

&lt;p&gt;That’s it then.&lt;/p&gt;

&lt;p&gt;Now we know the end to end details of how communication happens between client and server. We have discussed how the one-way SSL differs from the two-way SSL and how to identify it from SSL logs. Also, we have covered how the handshake varies based on the used key exchange method.&lt;/p&gt;

&lt;p&gt;The entire process is guaranteed to establish trust between both communicating parties. In the current era, the SSL is considered to be an essential part of secure communication. It’s fascinating to see how users put their faith in this protocol about the safety of their sensitive details that are being transferred through the internet.&lt;/p&gt;

&lt;p&gt;Stay safe! Be secure!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Sliding Pages With React.js</title>
      <dc:creator>asaf g</dc:creator>
      <pubDate>Tue, 03 Jul 2018 13:39:20 +0000</pubDate>
      <link>https://dev.to/asaf_g6/sliding-pages-with-react-js-1o5l</link>
      <guid>https://dev.to/asaf_g6/sliding-pages-with-react-js-1o5l</guid>
      <description>&lt;h2&gt;
  
  
  Make Them Slide!
&lt;/h2&gt;

&lt;p&gt;The popular way to achieve routing in React is using &lt;a href="https://github.com/ReactTraining/react-router"&gt;React Router v4&lt;/a&gt;. React Router works great, but it doesn't make the pages slide. Of course, you can use a package like &lt;a href="https://www.npmjs.com/package/react-router-page-transition"&gt;React Router Page Transition&lt;/a&gt; to make that happen.&lt;br&gt;&lt;br&gt;
We are not going to use either of that packages in this tutorial. Instead, we will roll our own and create a sliding pages router.&lt;br&gt;&lt;br&gt;
This tutorial is for learning purposes, If you want to use the final code in production it would require some more work.&lt;br&gt;&lt;br&gt;
The complete solution is on github and you can find it &lt;a href="https://github.com/asafg6/react-sliding-pages"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;You should be comfortable with HTML, Javascript, css and React.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 1 - Setup
&lt;/h2&gt;

&lt;p&gt;we'll use create-react-app. If you don't have React installed, &lt;a href="https://reactjs.org/docs/add-react-to-a-new-app.html"&gt;install it&lt;/a&gt;.  &lt;/p&gt;

&lt;p&gt;Let's create our new app:&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="nv"&gt;$ &lt;/span&gt;create-react-app react-sliding-pages
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alright! First step complete!&lt;br&gt;
Feel free to delete logo.svg, we won't be using it.&lt;br&gt;&lt;br&gt;
You can cd into the project's directory and run &lt;strong&gt;npm start&lt;/strong&gt;, so you can watch your progress.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 2 - Creating The Page Element
&lt;/h2&gt;

&lt;p&gt;Create a new file called page.js under the src directory.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;page.js&lt;/strong&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&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&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Page&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;constructor&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="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;super&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="p"&gt;}&lt;/span&gt;


    &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&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;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;
                &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;100vw&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;100%&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fixed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;top&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;left&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;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;translateX(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&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="nx"&gt;left&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;px)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;animationTimingFunction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ease-in&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;zIndex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;transform .8s ease-in-out&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
            &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="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="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/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;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;Page&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


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

&lt;/div&gt;



&lt;p&gt;There's a few things to pay attention to in this component.&lt;br&gt;&lt;br&gt;
First of all, this is a container component — we use &lt;strong&gt;this.props.children&lt;/strong&gt; to render all child components.&lt;br&gt;&lt;br&gt;
The other two are in the css:&lt;br&gt;&lt;br&gt;
The &lt;strong&gt;transformX&lt;/strong&gt; property is determined by the &lt;strong&gt;left&lt;/strong&gt; prop.&lt;br&gt;&lt;br&gt;
The transition and &lt;strong&gt;animationTimingFunction&lt;/strong&gt; controls the animation and makes the sliding happen.&lt;/p&gt;

&lt;p&gt;Now that we have our page component, we should try to use it.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 3 - Sliding The Page
&lt;/h2&gt;

&lt;p&gt;Let's take care of some crucial styling. Change the contents of App.css to this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;App.css&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;
&lt;span class="nc"&gt;.App&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;text-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.page&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;300px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;min-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin-right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;z-index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;15000&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;Change the contents of App.js to:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;App.js&lt;/strong&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&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&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./App.css&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;Page&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;./page&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="kd"&gt;constructor&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="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;


  &lt;span class="nx"&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;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&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;div&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;input&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&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="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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Page&lt;/span&gt; &lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;left&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;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;page&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;green&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nx"&gt;bla1&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;/Page&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;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;Play around with the input, try typing 1000 or -500 and see what happens. If everything went well, the page should slide across the screen.&lt;br&gt;&lt;br&gt;
So what did we do here?&lt;br&gt;&lt;br&gt;
We created a state variable called &lt;strong&gt;left&lt;/strong&gt; and passed it to our page component. When the input changes, it triggers the &lt;strong&gt;setState&lt;/strong&gt; method and changes the page's left property.&lt;br&gt;&lt;br&gt;
That's nice, but it's only one page. We need an element that will wrap our page components and switch them.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 4 - Creating The Nav Element
&lt;/h2&gt;

&lt;p&gt;This is the main part of our program and where the most logic is.&lt;br&gt;
Let's create our Nav element in small parts.  &lt;/p&gt;

&lt;p&gt;We'll start with an empty component. Create a new file called nav.js under the src directory.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;nav.js&lt;/strong&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&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&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Nav&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Component&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;Nav&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The plan is to place the current page in the middle of the screen and hide the other pages on the sides of the screen. To achieve that, we'll need to know the screen width.&lt;br&gt;
The &lt;strong&gt;left&lt;/strong&gt; prop worked well before, so we'll use it here as well.&lt;/p&gt;

&lt;p&gt;Let's create the constructor for the Nav component:  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;nav.js&lt;/strong&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="p"&gt;...&lt;/span&gt;

    &lt;span class="kd"&gt;constructor&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="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;super&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&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;innerWidth&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientWidth&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientWidth&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;left&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;width&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;left&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;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;left&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="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="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;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;page&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;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;left&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;We now have the screen's width in &lt;strong&gt;this.width&lt;/strong&gt;, an array of integers that represents the pages' left property and a page that represents the current page number.  &lt;/p&gt;

&lt;p&gt;Now let's add the &lt;strong&gt;move&lt;/strong&gt; method:  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;nav.js&lt;/strong&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="p"&gt;...&lt;/span&gt;

    &lt;span class="nx"&gt;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&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;left&lt;/span&gt; &lt;span class="o"&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;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slice&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;page&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nx"&gt;left&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="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;page&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="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;left&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;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;left&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="o"&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;width&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&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;i&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;left&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;left&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;    
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;page&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;Take a moment to read the code and understand what it does.  &lt;/p&gt;

&lt;p&gt;Basically, the code iterates on a copy of the left array and sets each page's left location according to the page number.&lt;/p&gt;

&lt;p&gt;Let's continue to the &lt;strong&gt;render&lt;/strong&gt; method.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;nav.js&lt;/strong&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="p"&gt;...&lt;/span&gt;

    &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pageElements&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Children&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&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="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;idx&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;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cloneElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;left&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;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;idx&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="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;pageElements&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;/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;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we use &lt;strong&gt;React.Children.map&lt;/strong&gt; to iterate over the page elements and add the left prop.  &lt;/p&gt;

&lt;p&gt;Now let's use our new Nav element in App.js.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;App.js&lt;/strong&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&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&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./App.css&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;Page&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;./page&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;Nav&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;./nav&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="kd"&gt;constructor&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="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&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="p"&gt;}&lt;/span&gt;



  &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&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;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&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;Nav&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;Page&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;page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;green&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="nx"&gt;bla1&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;/Page&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="nx"&gt;Page&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;page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;red&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="nx"&gt;bla1&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;/Page&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="nx"&gt;Page&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;page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="nx"&gt;bla1&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;/Page&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="nx"&gt;Page&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;page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;brown&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="nx"&gt;bla1&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;/Page&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;/Nav&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;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;span class="p"&gt;;&lt;/span&gt;


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

&lt;/div&gt;



&lt;p&gt;In case everything worked well, you should see the first page rendered in your browser. You can check the html source (using the browser's dev tools) and see that all the child elements are indeed rendered.  &lt;/p&gt;

&lt;p&gt;Alright, so we have all the pages but no access to the &lt;strong&gt;move&lt;/strong&gt; method. Let's add some buttons temporarily just to see that the slide works.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;nav.js&lt;/strong&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="p"&gt;...&lt;/span&gt;

    &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pageElements&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Children&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&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="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;idx&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;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cloneElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;left&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;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;idx&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;buttonElements&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Children&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&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="nx"&gt;buttons&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;idx&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;let&lt;/span&gt; &lt;span class="nx"&gt;newButton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cloneElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;onClick&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&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;newButton&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="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="o"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;buttonElements&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;/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="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;pageElements&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;/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;/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;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;App.js&lt;/strong&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="p"&gt;...&lt;/span&gt;

  &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;buttons&lt;/span&gt; &lt;span class="o"&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="mi"&gt;4&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&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="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;      &lt;span class="nx"&gt;buttons&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;button&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;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&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;Nav&lt;/span&gt; &lt;span class="nx"&gt;buttons&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;buttons&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;Page&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;page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;green&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="nx"&gt;bla1&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;/Page&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="nx"&gt;Page&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;page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;red&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="nx"&gt;bla1&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;/Page&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="nx"&gt;Page&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;page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="nx"&gt;bla1&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;/Page&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="nx"&gt;Page&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;page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;brown&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="nx"&gt;bla1&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;/Page&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;/Nav&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;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Try the buttons in your browser, the pages should slide.  &lt;/p&gt;

&lt;p&gt;Now that the basic functionality works, let's make our Nav element more router like.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5 - Implement Routing
&lt;/h2&gt;

&lt;p&gt;First, remove the buttons we used for testing. We don't need them.&lt;br&gt;
With that out of the way, create a new file called link.js under the src directory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;link.js&lt;/strong&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&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&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Link&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nx"&gt;go&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&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;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hash&lt;/span&gt; &lt;span class="o"&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="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&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;i&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;go&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/i&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;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;This component is pretty straight forward, it renders the component's children and changes the hash on a click according to the &lt;strong&gt;to&lt;/strong&gt; prop.&lt;/p&gt;

&lt;p&gt;Let's make our Nav component react to hash changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;nav.js&lt;/strong&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="p"&gt;...&lt;/span&gt;

    &lt;span class="kd"&gt;constructor&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="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;super&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&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;innerWidth&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientWidth&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientWidth&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;left&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;width&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;left&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;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;left&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="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="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;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;page&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;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;left&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;pages&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="p"&gt;...&lt;/span&gt;

    &lt;span class="nx"&gt;componentDidMount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;move&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;pages&lt;/span&gt;&lt;span class="p"&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;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)]);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;componentWillMount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&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;onhashchange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&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;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;newURL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;indexOf&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;newURL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slice&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="mi"&gt;1&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;move&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;pages&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;hash&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="nx"&gt;render&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;pageElements&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Children&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&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="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;idx&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;element&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cloneElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;left&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;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="na"&gt;from&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;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="na"&gt;eventer&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;eventer&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;pages&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;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;idx&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;element&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="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;pageElements&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;/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;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see we, are registering the pages to the &lt;strong&gt;pages&lt;/strong&gt; prop, so we can know which route belongs to which page.&lt;/p&gt;

&lt;p&gt;And finally use our new links in App.js.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;App.js&lt;/strong&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&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&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./App.css&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;Page&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;./page&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;Nav&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;./nav&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;Link&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;./link&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&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;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&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;div&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;Link&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/green&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;button&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;green&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Link&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="nx"&gt;Link&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/red&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;button&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;red&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Link&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="nx"&gt;Link&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/blue&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;button&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;blue&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Link&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="nx"&gt;Link&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/brown&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;button&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;brown&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Link&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="nx"&gt;Nav&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;Page&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="s2"&gt;/green&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;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;page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;green&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="nx"&gt;bla1&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;/Page&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="nx"&gt;Page&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="s2"&gt;/red&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;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;page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;red&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="nx"&gt;bla1&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;/Page&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="nx"&gt;Page&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="s2"&gt;/blue&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;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;page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="nx"&gt;bla1&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;/Page&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="nx"&gt;Page&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="s2"&gt;/brown&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;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;page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;brown&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="nx"&gt;bla1&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;/Page&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;/Nav&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;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;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Alright! We have a sliding router! But wait...&lt;br&gt;&lt;br&gt;
The pages that are off screen are still rendered. This might be good for you, if your app is pretty much static. But as we know, React components might do a whole lot of stuff.. Use the the network, do some calculations, animations... etc. We need some way to disable the component that are off screen.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 6 - Only Render What Is Visible
&lt;/h2&gt;

&lt;p&gt;This part is a bit tricky, we need the pages visible for the sliding effect but we don't want them to be rendered when they are off screen. For example, if the user goes from page 5 to page 1, we need to render all the pages for the sliding effect and then only render page 1.  &lt;/p&gt;

&lt;p&gt;We'll use an event mechanism, that will fire every time the page changes.&lt;br&gt;&lt;br&gt;
Add another class to nav.js .  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;nav.js&lt;/strong&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="p"&gt;...&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;MoveEvent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listeners&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="nx"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listeners&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;unregister&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listeners&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;splice&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;listeners&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;fire&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listeners&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a pretty standard event class. We will also add a &lt;strong&gt;from&lt;/strong&gt; prop, so that the page element will be able to tell if it's in transition or not.&lt;br&gt;
Let's pass the props to our page components from our Nav component.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;nav.js&lt;/strong&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="p"&gt;...&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Nav&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;constructor&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="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;super&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&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;innerWidth&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientWidth&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientWidth&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;left&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;width&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;left&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;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;left&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="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="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;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;page&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;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;left&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;pages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eventer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;MoveEvent&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&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;left&lt;/span&gt; &lt;span class="o"&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;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slice&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;page&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nx"&gt;left&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="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;page&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="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;left&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;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;left&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="o"&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;width&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&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;i&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;left&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;left&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;    
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;from&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;eventer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fire&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;componentDidMount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;move&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;pages&lt;/span&gt;&lt;span class="p"&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;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)]);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;componentWillMount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&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;onhashchange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&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;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;newURL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;indexOf&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;newURL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slice&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="mi"&gt;1&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;move&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;pages&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;hash&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;eventer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fire&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="nx"&gt;render&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;pageElements&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Children&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&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="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;idx&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;element&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cloneElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;left&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;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="na"&gt;from&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;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="na"&gt;eventer&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;eventer&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;pages&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;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;idx&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;element&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="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;pageElements&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;/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;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;Great, Now let's make the page understand if it needs to render children or not.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;page.js&lt;/strong&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&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&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// just a sleep util&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Page&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;constructor&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="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;super&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;shouldRenderChildren&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="nx"&gt;isVisible&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="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="nx"&gt;left&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&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="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="nx"&gt;left&lt;/span&gt; &lt;span class="o"&gt;&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;innerWidth&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="kc"&gt;false&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="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="nx"&gt;move&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="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="nx"&gt;left&lt;/span&gt; &lt;span class="o"&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="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;shouldRenderChildren&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reRender&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;reRender&lt;/span&gt;&lt;span class="p"&gt;()&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;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&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;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;shouldRenderChildren&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;isVisible&lt;/span&gt;&lt;span class="p"&gt;()});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&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;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;
                &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;100vw&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;100%&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fixed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;top&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;left&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;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;translateX(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&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="nx"&gt;left&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;px)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;animationTimingFunction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ease-in&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;zIndex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;transform .8s ease-in-out&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
            &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shouldRenderChildren&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&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="nx"&gt;children&lt;/span&gt;
                 &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/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;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;Page&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;...&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;isVisible&lt;/strong&gt; method returns whether or not the page is off screen. The &lt;strong&gt;reRender&lt;/strong&gt; method sleeps for 1 second and updates the &lt;strong&gt;shouldRenderChildren&lt;/strong&gt; state variable. When move is called the element will be fully rendered for 1 second and then it will disappear if it's off screen.  &lt;/p&gt;

&lt;p&gt;Now we just need to register to the move event.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;page.js&lt;/strong&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="p"&gt;...&lt;/span&gt;

    &lt;span class="nx"&gt;componentDidMount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eventer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;move&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;componentWillUnmount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eventer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;unregister&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;move&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;Awesome! Check your browser dev tools and see that off screen pages are not rendering any children. &lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7 (optional) - Customizing And Extending The Code
&lt;/h2&gt;

&lt;p&gt;There's a chance that your app needs the pages to behave differently.&lt;br&gt;&lt;br&gt;
For example, you can render each page's child components and pass them a prop telling them if they are visible or not. Whatever comes to mind really.&lt;br&gt;&lt;br&gt;
That part is totally up to you!&lt;br&gt;&lt;br&gt;
If you are extending or customizing the code, I would love to hear about your ideas and implementations.&lt;/p&gt;

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

&lt;p&gt;We created our own router with sliding pages, that's pretty cool. Of course our router is no match for React Router, which is much more fancy and also battle tested. Rolling your own can be a huge pain sometimes(no one likes reinventing the wheel), but it has a big advantage - you can code exactly what your app needs.&lt;br&gt;&lt;br&gt;
I hope you enjoyed, and of course, feel free to comment or share.&lt;br&gt;&lt;br&gt;
Thank you for reading. &lt;/p&gt;

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