Category Archives: Cheat sheet

Quick tutorials

Using mkcert to create locally-trusted development certificates.

mkcert git repo

Creating certificate files

  1. Navigate to desired location where the certificate will be created (for example $ mkdir local-ssh-certificates;cd local-ssh-certificates )
  2. Install mkcert tool: $ brew install mkcert
  3. Generate certificates for localhost : $ mkcert localhost
  4. Install local CA in the system thrust store (this does not work for Firefox) mkcert -install

Setting up Express server to use certificates

Make sure to replace /Users/toni/local-ssh-certificates with your real location.

var express = require('express');
var https = require('https');
var app = express();
const path = require('path');
const fs = require('fs');


app.use(express.static('src'))



  https.createServer({ 
    // replace with certificate location
    key: fs.readFileSync('/Users/toni/local-ssh-certificates/localhost-key.pem'),
    cert: fs.readFileSync('/Users/toni/local-ssh-certificates/localhost.pem')
  }, app).listen(5001);
  console.log('App listening on port 5001!');

 

Simple use of Java Script spread operator

Converting array into object

// The array
var numbers = [1,2,3];


var obj = {...numbers }

console.log(obj)
// result: {0:1, 1:2, 2:3}

 

Expanding object with new parameter

// The array
var person = {
  name: 'Jhon'
}

var obj = {...person, age: 23 }

console.log(obj)
// expected person to be: {name: 'John', age:23 }

 

Getting sum of an array

function sum(x, y, z) {
  return x + y + z;
}

const numbers = [1, 2, 3];

console.log(sum(...numbers));
// resunt: 6

 

regular JavaScript functions vs array functions

Does not have its own bindings to this or super, and should not be used as methods.

var obj1 = {
    a: 123,
    b: function() {
        return this.a;
    }
}

var obj2 = {
    a: 123,
    b: () => {
        return this.a;
    }
}

console.log("obj1: ", obj1.b());
console.log("obj2: ", obj2.b());

==========================================
result
==========================================

obj1:  123
obj2:  undefined

Using call/apply and bind

var obj1 = {
    a: 111,
    b: (a,b) => {
        return `${this.a} ${a} ${b}`;
    },
    c: function(a,b) {
        return `${this.a} ${a} ${b}`;        
    }
}

var obj2 = {
    a: 123
}

console.log("obj1: ", obj1.b.apply(obj2, ['one', 'two']));
console.log("obj1: ", obj1.b.bind(obj2)());


console.log("obj1: ", obj1.c.apply(obj2, ['one', 'two']));
console.log("obj1: ", obj1.c.bind(obj2, 'one', 'two')());

=====================================================
result
=====================================================
obj1:  undefined one two
obj1:  undefined undefined undefined
obj1:  123 one two
obj1:  123 one two

 

JavaScript call, bind and apply simple

According MDN all three methods are very similar, and at the end they produce very similar result.

  • they all accept this object as first parameter.
  • then apply accepts and array of arguments vs bind and call accept a sequence of arguments.

Function.prototype.apply()

The apply() method calls a function with a given this value, and arguments provided as an array

Function.prototype.bind()

The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called

 

const module = {
  getX: function(one, two) {
    return `${this.x} ${one} ${two}`;
  }
};


const obj = {x: '123'};


console.log( "call: ",module.getX.call(obj, 'ONE', 'TWO') );

console.log( "apply: ",module.getX.apply(obj, ['ONE', 'TWO']) );

var newFunc = module.getX.bind( obj, 'ONE', 'TWO');
console.log("bind: ", newFunc());


result should be the same.

call:  123 ONE TWO
apply:  123 ONE TWO
bind:  123 ONE TWO

 

How to solve “Can’t perform a React state update on an unmounted component”

The scenario

– Let’s imagine that you have a card component that you could show and hide with a button.
– When the component become visible an asynchronous function is called to get current time.
– Once the fetch is done, it will update the card showing current time.

The problem

– Let’s say that this asynchronous function is taking a few seconds to bring data back, and before it finishes the user decides to `hide` (or more appropriate thing to use is unmount) the card by clicking the button.
– when fetch is done, the asynchronous function will call setState to update the component that is no longer there and you will receive the nasty warning telling you that React can’t perform a React state update on an unmounted component.

And it makes perfect sense since the component and it’s DOM is not there any more.

 

The solution

– Use React refs to determine if the component is mounted or not.

./App.js

import "./styles.css";
import Card from "./card";
import React, { useState } from "react";

export default function App() {
  const [cardVisible, setCardVisible] = useState(true);
  const [buttonText, setButtonText] = useState("Hide card");

  const setVisibility = () => {
    setButtonText(buttonText === "Show card" ? "Hide card" : "Show card");
    setCardVisible(!cardVisible);
  };

  return (
    <div className="App">
      <button onClick={setVisibility}>{buttonText}</button>
      {cardVisible && <Card />}
    </div>
  );
}

./card.js

import React, { useEffect, useRef, useState } from "react";

const card = () => {
  const [data, setData] = useState("loading ...");
  const mounted = useRef(false);

  async function fetchData() {
    console.log("`fetchData` called!");
    fetch(
      "https://www.toni-develops.com/external-files/examples/service-workers/delayed-response.php"
    ).then((response) => {
      response.text().then(function (text) {
        console.log(">>>", mounted.current);
        if (mounted.current === null) return;
        console.log("Fetch response is available!");
        setData(text);
      });
    });
  }

  useEffect(() => {
    fetchData();
  });

  return (
    <div ref={mounted} className="card">
      <p>{data}</p>
    </div>
  );
};

export default card;
what we just did:

– Line 5 – we added mounted param which is a reference to any DOM object in this component. If the component is not mounted mounted.current will return null
– Line 26 – we just add the actually reference tag to any DOM object that is constantly visible in our component. In most cases this is just the card wrapping div.
– Line 14 – we just check if the component exist or not before performing stateUpdate

Obviously we could also use the old fashion DOM way and use querySelector to check if the element is actually there but I guess useRefs is the more “React way” of doing this.

The entire example could be seen here:

Using Nginx as a reverse proxy and add source code replacement

Task:

I have web app (in my case Node app running on port 3000)
I would add Nginx in front of it and will serve it on port 80.

Adding reverse proxy config.

Find Nginx.config file by executing: nginx -V

Edit nginx.conf and edit the server section

...
    server {
        listen       8081;
        server_name  toni-develops.com;
        location / {
            proxy_pass http://localhost:3000/;
        }
...

Line 5 tells enginx to intercept all requests / and proxy them from http://localhost:3000
If the request from example is /home Nginx will make request to http://localhost:3000/home

If for example we want to proxy only specific urls (let’s say only *.php) we could do this:

location ~ \.php {
    proxy_pass http://localhost:3000/
}

Add source code replacement

Nginx has to be built with sub_filter module.
The example below will override all localhost:3000 to toni-develops.com:80

...

server {
    listen       8081;
    server_name  toni-develops.com;


    location / {
        proxy_pass http://localhost:3000/;
        proxy_set_header Accept-Encoding "";
        proxy_buffers 8 1024k;  
        proxy_buffer_size 1024k;
        sub_filter 'localhost:3000'  'toni-develops.com:80';
        sub_filter_once off;            
    }

...

 

Simple caching using browser’s service workers.

A service worker API is relatively new technology, allowing for running a special type of web worker (a JavaScript), that can be installed in the browser and could provide special features to the website like caching data and allowing for offline load.

Service workers are also heavily used in progressive apps since they provide functionalities for caching resources and push notifications.

Before we jump into building an example app, let’s see what are the main service worker properties.

Service worker properties:

– Service workers are plain JavaScript APIs.

– Service workers run on separate thread so they can’t access the elements of the main page like the DOM elements but this is not the intend of how they are used.

– Service workers can listen on an events emitted from the browser and execute an appropriate script. In example a service worker could listen on browser fetch event and fetch the data or return it from cache.

Service worker lifecycle.

On a first page visit the only thing that happens is that service worker got installed. No code inside the service worker got executed, unless the user hit another page from this website or reloads the current page. Then service worker kicks in and could provide the extra functionality to the site.

Let’s get started by creating a simple web page, that will make an AJAX request to this service: https://www.toni-develops.com/external-files/examples/service-workers/delayed-response.php that will return the current time, and they display it.

The service intentionally delays the response 5 seconds so this way we could observe when we open the page for the first time how the response is delayed, since service worker is installing and don’t have the response cached. Then if we reload the page the service worker will intercept the request and will serve last cached response right away and then  will make a request to the service and update the page.

Building a caching layer for the web resources using service worker.

Let’s create the page.

index.html

<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>title</title>
    <script
          src="https://code.jquery.com/jquery-3.3.1.min.js"
          integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
          crossorigin="anonymous"></script>
    <link rel="stylesheet" href="style.css">
    <script src="script.js"></script>
  </head>
  <body>
    My fancy new site !
    <hr>
    <div id="container"></div>
  </body>
</html>

 

script.js

if ('serviceWorker' in navigator) {
  window.addEventListener('load', function() {
    navigator.serviceWorker.register('./sw.js').then(function(registration) {
      // Registration was successful
      console.log('ServiceWorker registration successful with scope: ', registration.scope);
    }, function(err) {
      // registration failed :(
      console.log('ServiceWorker registration failed: ', err);
    });
  });
}



$.ajax({url: "https://www.toni-develops.com/external-files/examples/service-workers/delayed-response.php", success: function(result){
  $("#container").html(result);
}});

 What’s happening here:
– line 1: we check if the browser supports service workers.
– line 2: added event listener, listening for load event and on load it installs the service worker. The rest is just error handling.
-line15:we make a request to the service using plain jQuery AJAX request.

style.css

body {
  background: silver
}

Now it’s time to write the actual service worker.

sw.js

var CACHE_NAME = 'my-site-cache-v1';
var urlsToCache = [
  './index.html',
  './style.css',
  './script.js',
  'https://www.toni-develops.com/external-files/examples/service-workers/delayed-response.php',
  'https://code.jquery.com/jquery-3.3.1.min.js'

];

self.addEventListener('install', event => {
  // Perform install steps
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(cache => {
        console.log('Opened cache');
        cache.addAll(urlsToCache);
      })
  );
});


self.addEventListener('fetch', event => {
  console.log("(9)served from service worker: ",event.request.url);
  // serve as soon as possible from cache
  event.respondWith(fromCache(event.request));
  // update cache
  event.waitUntil(  
    update(event.request)
  );
});


/**
 * 
 * Helper methods
 */

function fromCache(request) {
  return caches.open(CACHE_NAME).then(cache => {
    return cache.match(request);
  });
}


function update(request) {
  caches.open(CACHE_NAME).then( cache => {
    fetch(request).then( response => {
      cache.put(request, response)
    });
  });
}

What we just did:
– line 1: we specified the cache key (we have to make sure that it is unique)
– line 2: we created an array urlsToCache having all URLs that we want to cache. If one of the URLs fail, service worker will fail to install so we have to keep this url list short.
– line 11: added event listener, that on install event (when the service worker is invoked for the first time) will open the cache (line 14), and will add all urls to the cache (line 17) and then return the contents.
– line13: will simply prevent service worker to be killed before finishing with caching the resources.
– line 23: added fetch event. This will fires wherever a web page request a resource (*.js, *.css, images or in this case AJAX request)
– line 26: will return the asset right away from cache
– line29: will fetch the asset from the ‘slow’ service to update the cache for the next request.
Now let’s look at the helper methods:
fromCache function is simply opens the cache and finds the request key.
update function is opening the cache, fetches a fresh data from the service (or stores a fresh copy of web resource) and puts it back into the cache using request as a key.

Testing the project.

Open an empty tab in Chrome (comand + T), make sure that the dev tools are also open on the net tab (alt + comand + i), and the console drawer is visible (escape toggles the drawer)

Copy the example URL example found here and paste it into Chrome’s tab.

You will see the message “My fancy new site !” and after around 5 seconds current date and time will appear (- 5 seconds that took for the service to return the data)

Now service worker is installed. Reload the page and you will see that the current time will appear instantly from the cache. Observe the net tab and you will notice that the service worker also made a request to the service to update the data (the one that is pending on the picture below) and also web resources are now coming from the service worker (the size column).

Additionally if you want to clear the cache you could do it by clicking on the Application tab in the dev tools “Clear Storage” and then “clear site data”.

Simple use of Promises in JavaScript

Here is a simple and a bit silly example of using promises. In real life we could just move the logic into done and fail functions which are promises themselves but for the sake of explaining how promises work we are going to do this example.

you could see the example here.

 var promise = new Promise(function(resolveFunc, rejectFunc) {

    $.ajax({
      url: "https://www.toni-develops.com/external-files/examples/service-workers/delayed-response.php",
    })
      .done(function( data ) {
        resolveFunc(data);
      })
      .fail(function(error) {
          rejectFunc(error);
      });

});

promise.then(
    function(result) { // resolve func
        console.log('Success! Data: ', result);
}, function(error) {    // reject function
    console.log("Error! ", error);
})

console.log("Promise was called, and once it's fulfilled the code inside the 'then' function will be executed!");

What’s happening here:
– Line 1 creates a new promise, which does AJAX request and calls done or fail functions.
– If execution is successful and done function is called, it also invokes resolveFunc passing the result data.
– Line15 is where the promise has been called, and the bodies of resolveFunc (line 16) and  rejectFunc (line 18) are defined and passed to the promise.

Run the code and you should see first the message “Promise was called, and once it’s fulfilled the code inside the ‘then’ function will be executed!
Five seconds later the newly fetched content will be shown since the service intentionally takes 5 seconds to return the data for testing purposes.

What if we want to make it much easier? Let’s use async and await

async function fetchData() {
    var result = await fetch('https://www.toni-develops.com/external-files/examples/service-workers/delayed-response.php');
    return result;
}


(async () => {
    var r = await fetchData();
    console.log("ONE::", r);    
    console.log("DONE !");
})();

 

Listen for DOM changes using Mutation Observer

If we ever needed to listen for DOM events, one of the first options that comes to our mind might be to use setTimeout and periodically check the contents of the tag that we are interested in. Like in this example:

function myTest() {
    setTimeout(function() {
        console.log("Beep ...");
        if(document.getElementById('root').innerHTML == 'Loading ...') {
            myTest();
        }
        else {
            // do something 
            alert("READY!");
        }
    }, 1000);
}

But this is intense JavaScript process, which could be done using more elegant way with the help of Mutation Observer. 

Using Mutation Observer we could subscribe for different types of DOM events and trigger function on change.

example code:

<html>
  <body>    
    <div id="root">loading ...</div>

    <script>
      setTimeout(function() {
        document.getElementById('root').innerHTML = "My content is loaded!";
      }, 3000);
    </script>

    <script>
      var targetNode = document.getElementById('root');
      var config = { attributes: true, childList: true, subtree: true, characterData:true };
      var observer = new MutationObserver(function() {
        alert("#root div changed!");  
        // stop observing
        observer.disconnect();      
      });

      observer.observe(targetNode, config);
    </script>
  </body>
</html>

 what is happening here:
– created a div tag with id=’root’ and added ‘Loading …’ text.
– created MutationObserver (line 14) to listen for DOM changes in ‘root’ folder.
– specified which DOM events will trigger the function in config param (line 13)

– after 3 sec. setTimeout event fires and changes the content of the ‘root’ div, triggering DOM change event which will cause the function set in MutationObserver (line 14) to be executed.
– after showing the alert we could optionally disconnect and unsubscribe for DOM change events for this tag.

Here are some of the most used config properties

Mutation observer init properties:

At a minimum, one of childListattributes, and/or characterData must be true when you call observe(). Otherwise, a TypeError exception will be thrown.

attributeFilter Optional
An array of specific attribute names to be monitored. If this property isn’t included, changes to all attributes cause mutation notifications. No default value.
attributeOldValue Optional
Set to true to record the previous value of any attribute that changes when monitoring the node or nodes for attribute changes; see Monitoring attribute values in MutationObserver for details on watching for attribute changes and value recording. No default value.
attributes Optional
Set to true to watch for changes to the value of attributes on the node or nodes being monitored. The default value is false.
characterData Optional
Set to true to monitor the specified target node or subtree for changes to the character data contained within the node or nodes. No default value.
characterDataOldValue Optional
Set to true to record the previous value of a node’s text whenever the text changes on nodes being monitored. For details and an example, see Monitoring text content changes in MutationObserver. No default value.
childList Optional
Set to true to monitor the target node (and, if subtree is true, its descendants) for the addition or removal of new child nodes. The default is false.
subtree Optional
Set to true to extend monitoring to the entire subtree of nodes rooted at target. All of the other MutationObserverInit properties are then extended to all of the nodes in the subtree instead of applying solely to the target node. The default value is false.