Check if string has all unique characters

Task

Implement an algorithm to determine if a string (of characters from ‘a’ to ‘z’) has all unique characters or not.

Example 1:

var s = "abcde";
returns true;

Example 2:

var s = "abcade";
returns false;

Solution

Solution 1: The brute force solution will be to iterate through all characters and compare with all other characters.

function areCharactersUnique(s) {
    for(let i=0; i < s.length; i++) {
        for(let j=0; j < s.length; j++) {
            if(i == j)
                continue;
            if(s[i] == s[j]) {
                return false;
            }
        }

    }
    return true;
}

var s = "abcade";

console.log(areCharactersUnique(s));

Solution 2: Using an array (or hashMap table) with key equal to the ASCII character code.

function areCharactersUnique(s) {
    var checker = new Array(26);
    for(let i=0; i < s.length; i++) {
        var pos = s[i].charCodeAt(0) - 'a'.charCodeAt(0);
        if(typeof checker[pos] != 'undefined') {
            return false;
        }
        checker[pos] = 1;
    }
    return true;
}

var s = "abcde";

console.log(areCharactersUnique(s));

Let’s make it more challenging and prohibit the use of additional data structures like count array, hash, etc.

Solution 3: Using bitwise operations to store into 32 bit if one of all 26 characters is presented or not.
We have 26 letters (from a to z). Let’s imagine that we could have 26 empty slots that we could set up to true if the character exists, pretty much as if we have a hashTable.
for simplicity I will use only 6 slots (from a to G) instead of all 26 that represent the whole alphabet.
In addition we have to mention that the slots are actually 32 (this is usually the length of an integer in JavaScript but we need only 26)

6 5 4 3 2 1 0
G F E D C B A
false false false false false false false

Given the string: ‘ABCG’ for example we will end up with this matrix.

6 5 4 3 2 1 0
G F E D C B A
true false false false true true true

But this could be stored into 32bit value using bitwise operations. The binary representation of the matrix above will be:  1000111

The solution:

function areCharactersUnique(s) {
    var checker = 0;

    for(let i=0; i < s.length; i++) {
        // Charcode of a is 97 but we want to start with 0
        var val = s[i].charCodeAt(0) - 'a'.charCodeAt(0);
        // & - Sets each bit to 1 if both bits are 1
        // examples: 
        // 1 & 10 = 0
        // 1 & 101 = 1
        if(checker & ( 1 << val)) {
            return false;
        }

        // | - Sets each bit to 1 if one of two bits is 1
        // examples:
        // 1 | 10 = 11
        // 1 | 1 = 1
        checker = checker | ( 1 << val);
    }
    return true;
}

what we just did:
– we started with creating a loop to go through all characters
– we set up an empty value checker to store if the character is used or not (this is the binary representation of the matrix above)
– (line 6) grabbing the value for each letter in the string but removing ‘a’ = 97 so ‘a’ character will be equal to 0 and z = 26
– (line 19) we are setting the position of the character into the checker to true using bitwise shift left (1 << a) and preserving other already set positions using bitwise | ‘or’
– (line 11) using the same technique but with bitwise & ‘and’ we check if the character position is set to true or not.

Here is a step by  step example for ‘ABCG’ character:
– initially checker = 0 // or the binary representation is '00000000...0'
– we are going to insert a using Zero fill left shift. This is basically going to add ‘1’ followed by as many ‘0’ to the right of the checker as the value of ‘a’ is. In this case 0, so schecker = 1 // binary '00000000...1

– next step inserting ‘b’ follows the same procedure: b = 1, (1 << b) = 2 '000000...10' but we also want to preserve whatever was already inserted so we use bitwise ‘|’ ‘or’ which sets each bit to 1 if one of two bits is 1.
so
checker = checker | (1 << b) = 2
or the binary representation will be:
checker = '00000000...1' | (1 << b) = '000000000...11'

and the same for the rest of the characters

var a = 0;
var b = 1;
var c = 2;
var d = 3;
var e = 4;
var f = 5;
var g = 6;

var s = "abcg";
var checker = 0; 

checker = checker | (1 << a);   // 1
checker = checker | (1 << b);   // 11
checker = checker | (1 << c);   // 111
checker = checker | (1 << g);   // 1000111

Let’s modify the problem, and ask to return the index of the first unique character in the string.
For example for string ‘abcac’ the return will be the index of b – ‘1’
This problem is asked in Leetcode

/**
 * @param {string} s
 * @return {number}
 */
var firstUniqChar = function(s) {
    
    let lastSingle = null;
    let hashMap = {};
    for(var i = 0;i < s.length; i ++) {
        var val = s[i];
        hashMap[val] =  hashMap[val] == undefined ? i: 'not-unique';        
    }

    for(let i=0; i < s.length; i++) {
        var key = s[i];
        if(hashMap[key] != 'not-unique') {
            return hashMap[key];
        }
    }
    return -1;

}

 

LRU Cache

Table of Contents

Task

Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and put.

get(key) – Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
put(key, value) – Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.

The cache is initialized with a positive capacity.

Follow up:
Could you do both operations in O(1) time complexity?

Example:

LRUCache cache = new LRUCache( 2 /* capacity */ );

cache.put(1, 1);
cache.put(2, 2);
cache.get(1);       // returns 1
cache.put(3, 3);    // evicts key 2
cache.get(2);       // returns -1 (not found)
cache.put(4, 4);    // evicts key 1
cache.get(1);       // returns -1 (not found)
cache.get(3);       // returns 3
cache.get(4);       // returns 4

This problem was taken from Leetcode

Solution

The brute force solution will be to use array, to push every new element at the top, and on ‘get’ to pop out the element and to put it at the top of the array.

A better solution will be to use hashmap where the element retrieval will be O(1) (constant) but the hashmap is not keeping track of the order of the elements. To solve this problem we are going to link elements in the hashnmap table with double linked list, where each element will point to its previous and next sibling.
On every ‘get’ operation we are going to re-link the element and it’s siblings.

When the cache reaches the capacity we are going to remove the least used node from the bottom.

put(1,1) put(2,2) get(1) put(3,3) get(2) put(4,4) get(1) get(3) get(4)
return 1 -1 -1 3 4
result 1 2,1 1,2 3,1 => (2) 3,1 4,3 => (1) 4,3 3,4 4,3

 

class LRUCache {

  constructor(capacity) {
    
        this.head = null;
        this.tail = null;
        this.capacity = capacity;
        this.count = 0;
    this.hashMap  = new Map();    
  }

 
  get(key) {
    var node = this.hashMap.get(key);
    if(node) {
      if(node == this.head) {
        // node is already at the head, just return the value
        return node.val;
      }			
      if(this.tail == node && this.tail.prev) {
        // if the node is at the tail,
        // set tail to the previous node if it exists.
        this.tail = this.tail.prev;
        this.tail.next = null;
      }
      // link neibouring nodes together
      if(node.prev)
        node.prev.next = node.next;
      if(node.next)
        node.next.prev = node.prev;			
      // add the new head node
      node.prev = null;
      node.next = this.head;
      this.head.prev = node;
      this.head = node;

      return node.val;
    }
    return -1;
  }

  put(key, val) {
    this.count ++;
    var newNode = { key, val, prev: null, next: null };

    if(this.head == null) {
      // this.hashMap is empty creating new node
      this.head =  newNode;
      this.tail = newNode;
    }
    else {
      var oldNode = this.hashMap.get(key);
      if(oldNode) {
        // if node with the same key exists, 
        // clear prev and next pointers before deleting the node.
        if(oldNode.next) {
          if(oldNode.prev)
            oldNode.next.prev = oldNode.prev;
          else
            this.head = oldNode.next;
        }
        if(oldNode.prev) {					
          oldNode.prev.next = oldNode.next;
          if(oldNode == this.tail)
            this.tail = oldNode.prev;
        }
        // removing the node
        this.hashMap.delete(key);
        this.count --;				
      }

      // adding the new node and set up the pointers to it's neibouring nodes			
      var currentHead = this.head;
      currentHead.prev = newNode;				
      newNode.next = currentHead;
      this.head = newNode;

      if(this.tail == null)
        this.tail = currentHead;

      if(this.count == this.capacity + 1) {
        // remove last nove if over capacity
        var lastNode = this.tail;
        this.tail = lastNode.prev;
        if(!this.tail) {
          //debugger;
        }
        this.tail.next = null;
        this.hashMap.delete(lastNode.key);
        this.count --;
      }

    }
    this.hashMap.set(key, newNode);
    return null;
  }
}

 

Trapping Rain Water

Table of Contents

Task

Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining.


image was borrowed from leetcode

The above elevation map is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped. Thanks Marcos for contributing this image!

Example:

Input:

 [0,1,0,2,1,0,1,3,2,1,2,1]

Output:

 6

This problem was taken from Leetcode

Solution

 

The brute force approach: for each element we go to the right and find the maximum height of the bar, then we go to the left and do the same.

For any element the maximum amount of the water that could be trapped will be the minimum of left height and right height, minus the height of the bar.

So for the array [0,1,0,2,1,0,1,3,2,1,2,1] we go all the way to the right and calculate the max right value, starting from first element ‘0’ max right will be 0. ‘1’ – max right is ‘1’ and so on.
We repeat the same from last element ‘1’ to the first one.

Then the trapped water for the first column will be:  min(maxRight, maxLeft) – theArrayElement[n]

the array 0 1 0 2 1 0 1 3 2 1 2 1
max right 0 1 1 2 2 2 2 3 3 3 3 3
max left 3 3 3 3 3 3 3 3 2 2 2 1
collected
water
0 0 1 0 1 2 1 0 0 1 0 0

 

The complexity will be O(n2)

/**
 * @param {number[]} height
 * @return {number}
 */
var trap = function(height) {
    if(height.length < 2)
        return 0;

    let findMaxLeft = function(idx, height) {
        let max = 0;
        for(let i =idx;i >= 0; i --) {
            max = Math.max(max, height[i]);
        }
        return max;
    }

    let findMaxRight = function(idx, height) {
        let max = 0;
        for(let i = idx;i < height.length; i ++) {
            max = Math.max(max, height[i]);
        }
        return max;
    }  

    let collectedWater = 0;
    for(let i = 0;i < height.length; i ++) {

        const maxLeft = findMaxLeft(i, height);
        const maxRight = findMaxRight(i, height);

        let min = Math.min(maxLeft, maxRight);
        collectedWater += (min - height[i]);
    }

    return collectedWater;
};

The better solution: find all max left and max right with one loop, then do a second loop for each element in the array, and calculate trapped water.

/**
 * @param {number[]} height
 * @return {number}
 */
var trap = function(height) {
    let maxLeftArray = [], maxRightArray = [];
    let maxLeft = 0, maxRight = 0;
    const ln = height.length;
    let trappedWater = 0;

    for(let i = 0;i < height.length; i ++) {
        maxLeftArray[i] = Math.max(height[i], maxLeft);
        maxLeft = maxLeftArray[i];

        maxRightArray[ln - i - 1] = Math.max(height[ln - i - 1], maxRight);
        maxRight = maxRightArray[ln - i - 1];
    }

    for(let i = 0;i < height.length; i ++) {
        trappedWater += Math.min(maxLeftArray[i], maxRightArray[i]) - height[i];
    }
    return trappedWater;

};
what we just did:

– With one loop find the max left and right bar on each side.
– for any element the maximum amount of the water that could be trapped will be the minimum of left height and right height, minus the height of the bar.

Web Components: create text field with autosuggest dropdown and dictionary

What are web components?

Web components are new reusable components that add new functionalities to a standard components (ie: img, input, table, h, p, div, etc.) or create new components using and combining the existing standard components. You could read more here: web components

How to create custom web component ?

The simplest idea of how to create a web component is this: (although this could be highly customised, and done in many different ways, for the purpose of this exercise to be as simple as possible we will explore the simplest approach):

  1. Create custom class that will handle the presentational logic of the component.
  2. Add the custom tag in the document.
  3. Add the styles and the HTML markup to the main DOM. This is usually done by adding the shadow DOM of the new component to the document’s DOM.

Let’s make a real useful web component, while going to the process

Create a Text Field component with auto suggest drop down drawer and dictionary of the suggested words.

Final product will look like this:

Day:
Month:

First We will

Create the HTML and the CSS layout.

Create a new file

./text-box-with-dropdown.js

var template = `
<style>
  .wrapper {
    display: inline-grid;
  }
  #drawer {
    cursor: pointer;
    border: 1px solid silver;
    background: #f4f4f4;
  }
  .selectedRow {
    color: white;
    background: #606062;
  }
  p {
    margin: 1px;
    border-bottom: 1px solid silver;
  }
  p:last-child {
    border-bottom: none;
  }  
</style>

<div class="wrapper">
  <input type="text" id='textfield'>
  <div id='drawer'>
  </div>
</div>
`;

We added the CSS, and the HTML markup which consists of a wrapper div, a text field, and a ‘drawer’ div, which will show the suggested words.

Add web component’s class.

Next, In the same file create a class to handle the events.

class TextboxWithDropdown extends HTMLElement {  

  constructor() {
    // Always call super first in constructor
    super();
    this._shadowRoot = this.attachShadow({ 'mode': 'open' });
  }

  connectedCallback() {  
    this._shadowRoot.innerHTML = template; 
  }
}

And now let’s attach the newly created web component to the document DOM

window.customElements.define('textbox-with-dropdown', TextboxWithDropdown);

Now we are going to create the actual HTML document to view the component.

./index.html

<!DOCTYPE html>
<html lang="en" prefix="og=https://ogp.me/ns#" itemType="https://schema.org/WebPage" data-reactroot=""></html>
  <head>
    <script src="./text-box-with-dropdown1.js"></script>
    <style>
      body {
            padding: 40px;
            padding-bottom: 40px;
            background-color: #f5f5f5;
      }    
    </style>
  </head>

  <body>
    Day: <textbox-with-dropdown id="txt1" dictionary="1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31" value='1'></textbox-with-dropdown>
    Month: <textbox-with-dropdown id="txt2" dictionary="January,February,March,April,May,June,July,August,September,October,November,December"></textbox-with-dropdown>
  </body>
</html>

 

What we just did:
– we created simple HTML document
– Added two instances of our new WEB component textbox-with-dropdown
– Passed a property with a list of all days of the month to the first component and set it’s value=’1′ which will be the default parameter.
– Passed months of the year as a property to the second component.

So far the component will be visible but not quite functional. Let’s add all that we need to make the component functional.

First let’s discuss connectedCallback hook. It is invoked each time the custom element is appended into a document-connected element, while attributeChangedCallback is invoked when one of the custom element’s attributes is added, removed, or changed. How we are going to use this? We are going to move all initialization logic to connectedCallback
Then we are going to use attributeChangedCallback to listen to attribute changes and update the component. For example if you use the dev tools and inspect the component and edit the dictionary attribute, our component will update accordingly.

Next we are going to add a function that will accept a prefix parameter, which will be whatever the user starts typing in the text field and will filter the dictionary and return only matching words (or numbers).

We will also add keyUp events, so the user will be able to use ‘up’ and ‘down’ keys to navigate through the words list, and in addition we will add mousemove events to highlight the words where the mouse is.

Go back to text-box-with-dropdown.js and add these functionalities.

./text-box-with-dropdown.js

var template = `
<style>
  .wrapper {
    display: inline-grid;
  }
  #drawer {
    cursor: pointer;
    border: 1px solid silver;
    background: #f4f4f4;
  }
  .selectedRow {
    color: white;
    background: #606062;
  }
  p {
    margin: 1px;
    border-bottom: 1px solid silver;
  }
  p:last-child {
    border-bottom: none;
  }  
</style>

<div class="wrapper">
  <input type="text" id='textfield'>
  <div id='drawer'>
  </div>
</div>
`;

class TextboxWithDropdown extends HTMLElement {  

  constructor() {
    // Always call super first in constructor
    super();
    // and attach the component
    this._shadowRoot = this.attachShadow({ 'mode': 'open' });
  }

  connectedCallback() {
    // and when the component is mounted, do the rest to make it work
    this.selectedIndex = 0;
    this.filteredWordsCount = 0;
    this.isDrawerOpen = false;

    this._shadowRoot.innerHTML = template;
    this.textfield = this._shadowRoot.getElementById("textfield");
    this.dictionary = this.getAttribute("dictionary").split(',');
    this.textfield.value = this.getAttribute("value");
    this.textfield.addEventListener("keyup", function(e) {
      this.keyUp(e);
    }.bind(this));    
  }

  static get observedAttributes() {
    // on attributes changed by the browser dev tools this will reflect the changes
    return ["dictionary", "value"];
  }  

  get value() {
   // return the value
    return this.textfield.value;
  }

  attributeChangedCallback(name, oldValue, newValue) {
    //Custom square element attributes changed.
    this.dictionary = newValue.split(',');
  }

  selectHighlight(i) {
    this._shadowRoot.getElementById('row-' + this.selectedIndex).classList.remove("selectedRow");
    this._shadowRoot.getElementById('row-' + i).classList.add("selectedRow");
    this.selectedIndex = i;
  }

  keyUp(e) {
    if(e.keyCode == 13) {
      this.rowSelected(e);
      return;
    }
    if(e.keyCode == '38' || e.keyCode == '40') {
      this.arrowUpDown(e);
      return;
    }
    var prefix = this._shadowRoot.getElementById('textfield').value;
    if(prefix == '') {
      this._shadowRoot.getElementById('drawer').innerHTML = '';
      this.selectedIndex = 0;
      this.filteredWordsCount = 0;
      return;
    }
    if(this.isDrawerOpen == true)
      return;
    var words = this.filterWords(prefix);
    this._shadowRoot.getElementById('drawer').innerHTML = words.join('');
    // attach the events
    var c = 0;
    words.map(function(row, i) {
      var row = this._shadowRoot.getElementById('row-' + i);
      row.addEventListener("mousemove", function() {
        this.selectHighlight(i);
      }.bind(this));
      row.addEventListener("click", function(e) {
        this.rowSelected(e);
      }.bind(this));
    }.bind(this));
    // select first row if any
    if(words.length > 0)
      this._shadowRoot.getElementById('row-0').classList.add("selectedRow");
  }  

  arrowUpDown(e) {
    if(this.selectedIndex > -1)
      this._shadowRoot.getElementById('row-' + this.selectedIndex).classList.remove("selectedRow");    
    if(e.keyCode == '38' && this.selectedIndex > 0) {
      // arrow up
      this.selectedIndex --;
    }
    else if(e.keyCode == '40' && this.selectedIndex < this.filteredWordsCount - 1) {
      // arrow down
      this.selectedIndex ++;
    }
    this._shadowRoot.getElementById('row-' + this.selectedIndex).classList.add("selectedRow");
    e.preventDefault();
    return false;
  }

  rowSelected(e) {
    if(this.filteredWordsCount == 0)
      return;
    this._shadowRoot.getElementById('textfield').value = this._shadowRoot.getElementById('row-' + this.selectedIndex).innerText;
    this._shadowRoot.getElementById('drawer').innerHTML = '';
    this.filteredWordsCount = 0;
    this.selectedIndex = 0;
    e.preventDefault();
    return false;    
  }

  //business logic comes here. Bad idea!. Separate this in a diffrent class. But for the simplicity of the example we will keep it here.
  filterWords(prefix) {
    prefix = prefix.toLowerCase();
    var result = [];
    for(var i=0; i < this.dictionary.length;i ++) {
      var wordArray = this.dictionary[i].toLowerCase();
      for(var j=0; j < prefix.length && j < wordArray.length; j ++) {
        if(prefix[j] != wordArray[j]) {
          break;
        }
      }
      if(prefix.length == j) {
        var wordRow = '<p id="row-' + result.length + '">' + this.dictionary[i] + '</p>';
        result.push(wordRow);
      }
    }
    this.filteredWordsCount = result.length;
    return result;
  }  

}



window.customElements.define('textbox-with-dropdown', TextboxWithDropdown);

What we just did:
– in connectedCallback function we set up:
this.selectedIndex which will point to the selected word in the drawer
this.filteredWordsCount storing the number of word matched
this.isDrawerOpen
this._shadowRoot.innerHTML is set up with the HTML layout that we created in the beginning of the file.
this.textfield is set up with the value of value attribute. this._shadowRoot is the way how we are referring to the root of the component.
this.dictionary stores an array of all dictionary words that we pass using the dictionary property.
– added event listener to the text field, which will respond on keyUp and keyDown and will manipulate the highlighted word.
– (line 56) observedAttributes function returns a list of the attributes that we need to observe. Ie on adding or removing words through browser’s dev tools.
– (line 61) this function is called every time when the value of value attribute is called.Ie when  document.getElementById('txt1').value is called.
– (line 66) attributeChangedCallback is called whenever the observed parameters that we set up in observedAttributes function. Once the dictionary parameter is changed we are updating this.dictionary
– (line 71) selectHighlight function is called on mousemove over the words in the drawer.
– (line 77) keyUp(e) function responds to key press and is responsible to call rowSelected() on enter key, or arrowUpDown() on button up or down. If any other key is pressed filterWords(prefix)is called, prefix is the whatever the user started to type in the textfield. Then when the new words list is returned, we attach mousemove event (line 101), and click event (line 104)
arrowUpDown() simply move the highlighter up or down.
rowSelected() is called when a word is selected either with mouse click or when enter key is pressed.

 

 https://github.com/ToniNichev/WebComponents-text-box-with-dropdown.git

Array VS Hash Table

Hash table tutorial

Find element in Array

function fuindInArray() {
  var t0 = performance.now();

  for(var q = 0; q < data2.length; q++) {
      if( data2[q] == '106112407') {
          console.log(data2["106112407"]);
          break;
      }
  }

Find element in Hash Table

function findInHashtable() {
  var t0 = performance.now();

  console.log(data1["106112407"]);

  var t1 = performance.now();
  document.querySelector('#result1').value = "Call took " + (t1 - t0) + " milliseconds.";
}

 


Sort an array

Task

Given an array of integers nums, sort the array in ascending order.

Example 1:

Input:

 [5,2,3,1]

Output:

 [1,2,3,5]

Example 2:

Input:

[5,1,1,2,0,0]

Output:

[0,0,1,1,2,5]

 

This problem was taken from Leetcode

Solution

The brute force solution.

The brute force solution could be to make two loops and iterate through each elements in the array and repeatedly swapping the adjacent elements if they are in wrong order. This approach is called Bubble sort.

var nums = [5,4,6,1,2,3];


/**
 * @param {number[]} nums
 * @return {number[]}
 */
var sortArray = function(nums) {

  for(var i = 0; i < nums.length - 1;i++) {
    for(var j=0;j < nums.length - 1; j++) {
      if(nums[j] > nums[j+1]) {
        var tmp = nums[j];
        nums[j] = nums[j + 1];
        nums[j + 1] = tmp;
      }
    }
  }
  return nums;
}

nums = sortArray(nums);
console.log(nums);

In the worst case scenario the complexity will be O(n*n) since we have to iterate n*n times where n is the number of elements in the array.

A better performing solution is to keep splitting the array into two halves till we have single elements. Then we start merging the arrays and sorting at the same time. This is called merge sort algorithm.

The diagram is borrowed from Wikipedia.

 

Merge sort algorithm implementation:

/**
 * @param {number[]} nums
 * @return {number[]}
 */
var sortArray = function(nums) {
  function mergeArray(nums, start, mid, end) {
    var i = start, j = mid + 1;
    var tempArr = [];
    // compare till we reach either end of one of the halves
    for(var k = start;(i < mid+1 && j < end+1); k++) {
        if(nums[i] <= nums[j]) {
          tempArr.push(nums[i]);
          i++;           
        }
        else {
          tempArr.push(nums[j]);
          j ++;            
        }       
    }    
    
    // add the rest from the first half 
    for(var k = j;k < end + 1; k++) {
      tempArr.push(nums[k]);
    }         
    // add the rest from the second half 
    for(var k = i;k < mid + 1; k++) {
      tempArr.push(nums[k]);
    }         

    // set up nums with sorted values
    for(var k = start;k < end+1; k++) {
      nums[k] = tempArr[k - start];      
    }
  }

  function mergeSort(nums, start, end) {
    var mid = Math.floor((start + end) / 2);
    if(start < end) {
        mergeSort(nums, start, mid);
        mergeSort(nums, mid + 1, end);
        mergeArray(nums, start, mid, end);
    }
  }
  mergeSort(nums, 0, nums.length - 1);
  return nums;
}
var nums = [5,4,6,1,2,3];
var result = sortArray(nums);
console.log(result);

What we just did?
– started to split the array by half (line 39,40) which recursively calls mergeSort and keep splitting on smaller and smaller pieces till the array has only 1 element (line 37)

mergeSortcall sequence:

Caller Start End
Initial Call 0 5
L 0 2
L 0 1
L 0 0
R 1 1
R 2 2
R 3 5
L 3 4
L 3 3
R 4 4
R 5 5

Majority element in array

Task

Given an array of size n, find the majority element. The majority element is the element that appears more than ⌊ n/2 ⌋ times.

You may assume that the array is non-empty and the majority element always exist in the array.

Example 1:

Input:

 [3,2,3]

Output:

 3

Example 2:

Input:

 [2,2,1,1,1,2,2]

Output:

 2

This problem was taken from Leetcode

Solution

The solution:

Create an object (or associative array, depends of the language), iterate through all elements in the array adding them to the newly created object using the element value as a key. If element exists increase the value +1.
Keep track of mostly repeated element and return it at the end.

var arr = [3, 3, 4, 2, 4, 2, 4, 4];


/**
 * @param {number[]} nums
 * @return {number}
 */
var majorityElement = function(nums) {
  var elements = {};
  var majorityElement = nums[0];
  var majorityElementCount = 1;
  for(var i in nums) {
  	var element = nums[i];
  	elements[element] = typeof elements[element] == 'undefined' ? 1 : elements[element] + 1;
  	if(elements[element] > majorityElementCount) {
  		majorityElement = element;
  		majorityElementCount = elements[element];
  	}
  }    
  return majorityElement;
};

console.log(">>", majorityElement(arr));

– Create an object (line 9)
– Iterate through each element in the array feeling up the object with the elements from the array where the element value would be the key of the element (line 14)
– Each time when the element exists, add + 1
– Keep track of mostly repeated element (Lines 16-17)

Could we optimize the code? Slightly. When we add + 1 we could check if the value is already greater than the length of the array / 2 and if se we know that this is the majority element because no other element could have greater value.

...
    if(elements[element] > nums.length / 2) {
        return element;
    }
...

 

Creating loader component and set up one CSS per brand.

branch-name:  
Click To Copy

 

Previous solution was great but not perfect. We still add a CSS of two brands in one CSS file and loading all CSS for all brands per each component.

Could we do it better and load only the necessary CSS for each component for the particular branch ? Yers we could. The idea about bundle splitting is that one CSS file will be created per each component.

So in order to have one CSS file per brand we have to

Create a wrapper component per each brand.

Let’s start with

The Home component.

We are going to move the component’s code from index.js to a new file called renderer.js and repurpose index.js to be a wrapper component, which will load brand specific sub component, that will pass the style object back to the renderer component in renderer.js. If it sounds a bit confusing don’t worry. Follow that tutorial and it will get clear.

./src/components/Home/renderer.js

import React from 'react';

const Renderer = ({styles, title}) => {
  return (
    <div>
      <div className={styles.wrapper}>{title}</div>
    </div>
  );
}

export default Renderer;

The code in renderer file is pretty similar to that we had in index.js with one exception: we are going to pass the css as a property to this component.
And just to demonstrate how we could render different layout per each brand we are going to pass the title property as well.

Now the index.js will become our Home component wrapper, which will dynamically load either ./brands/one or ./brands/two sub component, which on the other hand will load our ./renderer.js component, passing the appropriate CSS for the selected brand.

./src/components/Home/index.js

import React from 'react';
import Loadable from 'react-loadable';
import Loading from '../Loading';

const one = Loadable({
  loader: () => import ('./brands/one'),
  loading: Loading
});

const two = Loadable({
  loader: () => import ('./brands/two'),
  loading: Loading
});

const components = {
  one,
  two
}

const Home = ( {subDomain} ) => {
  const Component = components[subDomain];
  return (
      <Component />
  )
}
export default Home;

what we just did:
– we crated a wrapper component, that will conditionally load the helper component for the current brand (lines 5 and 10)
-we render the appropriate sub component, based on the brand name.

Let’s create the helper sub components that will load the brand specific CSS and pass it to the renderer component and render it.

These components will look quite similar:

./src/components/Home/brands/one/index.js

import React from 'react';
import styles from './styles.scss';
import Renderer from '../../renderer.js'

export default () => {
  return (
    <Renderer styles={styles} title="This is my home section rendered for One!" />
  )
}

./src/components/Home/brands/two/index.js

import React from 'react';
import styles from './styles.scss';
import Renderer from '../../renderer.js'

export default () => {
  return (
    <Renderer styles={styles} title="This is my home section rendered for Two!" />
  )
}

what we just did:
– we imported brand specific CSS in each of the components (line 2)
– imported the renderer component (line 3)
– rendered the renderer component, passing the CSS and the title property (line 7)

Open the ./dist folder and look at 1.css and 2.css contents:

./dist/1.css

.one-wrapper{background-image:url(/dist/images/b5c0108b6972494511e73ad626d1852f-home.png);height:500px}.one-wrapper h2{color:#000}

./dist/2.css

.two-wrapper{background-image:url(/dist/images/a005b97826d5568577273d214dd5f89a-home.png);height:800px}.two-wrapper h2{color:#00f;font-size:50px}

Webpack created two files with the corresponding CSS: one-wrapper and two-wrapper containing only the CSS needed for each brand.

Open the browser and give it a try. The result should be what we saw in the previous chapter, but this time only the brand specific CSS is loaded.

Nice! Now we have Webpack created these two CSS files, but the class names are one-wrapper and two-wrapper which comes from the lead folder name, which now instead of been ./Home is ./Home/one and /Home/two  What will happen if we want to make another component brand specific?

The Greetings component

Let’s do the same changes:

./src/components/Greetings/renderer.js

import React, { Component } from 'react';
import { connect } from 'react-redux';


const CHANGE_USERNAME = 'CHANGE_USERNAME';
const TOGGLE_EDIT_MODE = 'TOGGLE_EDIT_MODE';

class Greetings extends Component {

  constructor(props) {
    super(props); 
  }
  

  doneEditUsername() {
    let newName = document.querySelector('#inputField').value;
    this.props.changeUserName(newName);
    this.props.toggleLogInPopup();
  }

  usernameChanged(el) {
    let newName = el.target.value;    
    this.props.changeUserName(newName);
  }

  onToggleEditMode() {
    this.props.toggleLogInPopup();
  }

  render() {
    let element = <h2 onClick={() =>{   this.onToggleEditMode()  }}>Hello:  {this.props.userName}</h2>;
    if(this.props.editMode)
      element = <h2>Type new name:<input type="text" id='inputField' value={this.props.userName} onChange={(el) => { this.usernameChanged(el);}} /><button onClick={() =>{ this.doneEditUsername() }}>done</button></h2>
    return (
      <div>
        <div className={this.props.styles.wrapper}>
          {element}
        </div>
      </div>);
  }
}

const mapStateToProps = ( storeState ) => {
  return {  
    userName: storeState.user.userName,
    editMode: storeState.user.editMode
  }
}

const mapDispatchToProps = dispatch => {
  return {
    toggleLogInPopup: () => {
      dispatch({type: TOGGLE_EDIT_MODE});
    },
    changeUserName: (userName) => {
      dispatch({type: CHANGE_USERNAME, data: userName});
    }
  }
};


export default connect(
  mapStateToProps,
  mapDispatchToProps
)(Greetings);

what we just did:
– we just moved the code from ./index.js to ./renderer.js
– we removed the CSS import since we are passing CSS as a property
– we changed the div class name to come from the passed property (line 36)

The rest is the same like in Home component.

The index component will actually look exactly the same:

./src/components/Greetings/index.js

import React from 'react';
import Loadable from 'react-loadable';
import Loading from '../Loading';



const one = Loadable({
  loader: () => import ('./brands/one'),
  loading: Loading
});

const two = Loadable({
  loader: () => import ('./brands/two'),
  loading: Loading
});

const components = {
  one,
  two
}

const Home = ( {subDomain} ) => {

  const Component = components[subDomain];
  return (
      <Component />
  )
}
export default Home;

Let’s load different ‘home’ pictures for each brand.
Move the home picture in ./images/home.png to ./images/one/home.png and add another image for ./images/two/home.png (you could either download some png or use the one in this branch)

./src/components/Greetings/brands/one/styles.scss

.wrapper {
  background-image:url('../../../../images/one/home.png');
  height: 500px;
  h2 {
    color: black;
  }
}

./src/components/Greetings/brands/two/styles.scss

.wrapper {
  background-image:url('../../../../images/two/home.png');
  height: 800px;
  h2 {
    color: blue;
    font-size: 50px;
  }
}

Here we have to adjust the relative path to the images since this component goes two levels deeper and we moved the images into a brands folders (line 2)

And the helper sub components are the same like in Home component.

./src/components/Greetings/brands/one/index.js

import React from 'react';
import styles from './styles.scss';
import Renderer from '../../renderer.js'

const One = () => {
  return (
    <Renderer styles={styles} />
  )
}

export default One;

./src/components/Greetings/brands/two/index.js

import React from 'react';
import styles from './styles.scss';
import Renderer from '../../renderer.js'

const One = () => {
  return (
    <Renderer styles={styles} />
  )
}

export default One;

Start the server and go to http://one.localhost:3006/home and you will notice that the Home component height increased. Why this happened?

Let’s open http://one.localhost:3006/dist/1.css and look at the class names:

.one-wrapper{background-image:url(/dist/images/b5c0108b6972494511e73ad626d1852f-home.png);height:500px}.one-wrapper h2{color:#000}

Somehow the one-wrapper has background-image:url(/dist/images/b5c0108b6972494511e73ad626d1852f-home.png) and height:500px that belongs to the Greetings component.

Why this is happening? Because of the way how we set up class name structure in Css-Loader. If you look at webpack.base.config.js  you will see that the localIdentName which is the CSS className is constructed by adding the folder name, and the actual local identifier ‘[folder]-[local]’

 ./src/webpack.base.config.js

...
      // SCSS
      {
        test: /\.scss$/,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              modules: true,
              importLoaders: 2,
              localIdentName: '[folder]-[local]',
              sourceMap: true
            }
          },
...

But the folder name now is ‘one’ or ‘two’ for both components since it takes only the leaf folder name. Let’s fix this by

Make brand component names unique.

Go to src/Home/brands/one and rename it to src/Home/brands/OneHome and src/Home/brands/two to be src/Home/brands/TwoHome
and do the same for the greetings component: src/Greetings/brands/one => src/Greetings/brands/OneGreetings and src/Greetings/brands/Two => src/Greetings/brands/TwoGreetings

Next let’s make the appropriate changes in both: Home and Greeting component:

./src/Home/index.js

import React from 'react';
import Loadable from 'react-loadable';
import Loading from '../Loading';

const one = Loadable({
  loader: () => import ('./brands/OneHome'),
  loading: Loading
});

const two = Loadable({
  loader: () => import ('./brands/TwoHome'),
  loading: Loading
});

const components = {
  one,
  two
}

const Home = ( {subDomain} ) => {

  const Component = components[subDomain];
  return (
      <Component />
  )
}
export default Home;

and

./src/Greetings/index.js

import React from 'react';
import Loadable from 'react-loadable';
import Loading from '../Loading';



const one = Loadable({
  loader: () => import ('./brands/OneGreetings'),
  loading: Loading
});

const two = Loadable({
  loader: () => import ('./brands/TwoGreetings'),
  loading: Loading
});

const components = {
  one,
  two
}

const Home = ( {subDomain} ) => {

  const Component = components[subDomain];
  return (
      <Component />
  )
}
export default Home;

Run the project and check /dist/3.css 

.OneHome-wrapper--t4U5b{background:#8d8dac;color:#fff;text-align:center;font-family:MyFont}

it contains only CSS for the Home component.

Adding a hash in CSS class names

As an extra step we could also add a hash for each class name. This will make class names unique per component, so if accidentally happened to have two components with the same names their CSS won’t colide.

This could be achieved by simply adding a hash directive in localIdentName in CSS-loader config [folder]-[local]–[hash:base64:5]

const getEnvironmentConstants = require('./getEnvironmentConstants');
const webpack =require('webpack');

module.exports = {
  mode: 'development',
  devtool: 'eval-source-map',
  entry: [
    '@babel/polyfill',    
    './src/index.js',
  ],
  output: {
    filename: '[name]-bundle.js',
    publicPath: '/dist/',
  },  
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader"
        }
      },

      // SCSS
      {
        test: /\.scss$/,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              modules: true,
              importLoaders: 2,
              localIdentName: '[folder]-[local]--[hash:base64:5]',
              sourceMap: true
            }
          },
          {
            loader: 'postcss-loader',
            options: {
              plugins: () => [require('autoprefixer')()],
              sourceMap: true
            },
          },
          {
            loader: 'sass-loader',
            options: {
              outputStyle: 'expanded',
              sourceMap: true
            }
          }
        ],
      },
      // images
      {
        test: /\.(png|jp(e*)g|svg)$/,  
        use: [{
            loader: 'url-loader',
            options: { 
                limit: 8000, // Convert images < 8kb to base64 strings
                name: 'images/[hash]-[name].[ext]'
            } 
        }]
      },
      //File loader used to load fonts
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/,
        use: ['file-loader']
      }                    
    ]
  },
  plugins: [
    new webpack.DefinePlugin({ 'process.env' : getEnvironmentConstants() } ),  
  ]
};

Run the project again and the home component should look like before. Open http://one.localhost:3006/dist/1.css and you will see how the has was appended to the class names.

branch-name:  
Click To Copy

 

Adding multiple brands and applications

branch-name:  
Click To Copy

 

Let’s make the task more challenging and assume that we are going to have two different Brands (or apps)

one.localhost.com,
two.localhost.com,

for the most of the cases they will do the same thing but the styling will be different, so let’s add ability for our components to be styled in different ways, depending of the brand.

Passing the sub-domain to the PageLayout component

Let’s add new parameter to store the default brand.

./.env

APP_NAME=Webpack React Tutorial
GRAPHQL_URL=http://localhost:4001/graphql
PROD_SERVER_PORT=3006
DEFAULT_BRAND=one

and make it available to the front end.

./getEnvironmentConstants.js

...
const frontendConstants = [
  'APP_NAME',
  'GRAPHQL_URL',
  'PROD_SERVER_PORT',
  'DEFAULT_BRAND'
];
...

Now, let’s pass the sub domain to the PageComponent. We have to do this in two different places: one for the client side, and one on the SSR.

./components/App/index.js

import React from 'react';
import PageLayout from '../../containers/PageLayout';
import { ApolloProvider } from 'react-apollo';
import { ApolloClient } from 'apollo-client';
import { HttpLink } from 'apollo-link-http';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import { Provider } from 'react-redux';
import { createStore} from 'redux';
import reducers from '../../reducers';

const styles = require('./styles.scss');

const store = createStore(reducers, {});

export default () => {
  const GRAPHQL_URL = process.env.GRAPHQL_URL;
  const client = new ApolloClient({
    link: new HttpLink({ uri:  GRAPHQL_URL }),
    cache: new InMemoryCache().restore(window.__APOLLO_STATE__),
  }); 
  
  const subDomain = window.location.host.split('.').length == 1 ? process.env.DEFAULT_BRAND : window.location.host.split('.')[0];
  return (
    <div className={styles.appWrapper}>
      <Provider store={store}>
        <ApolloProvider client={client}>
          <Router>
            <Switch>
            <Route exact path="*" render={(props) => <PageLayout {...props} subDomain={subDomain} />} />
            </Switch>
          </Router>
        </ApolloProvider>
      </Provider>
    </div>        
  );
}

 what we just did:
– (line 23) getting the sub domain
– (line 30) passing extra parameter with the subDomain to the PageComponent

Do the same for the SSR

./components/App/ssr-index.js

import React from 'react';
import PageLayout from '../../containers/PageLayout';
import { StaticRouter,  Route, Switch } from 'react-router-dom';
import { ApolloProvider } from 'react-apollo';
import { Provider } from 'react-redux';
import { createStore} from 'redux';
import reducers from '../../reducers';
import fetch from 'isomorphic-fetch';

import styles from './styles.scss';

const store = createStore(reducers, {});

export default ( {req, client} ) => {
  const subDomain = req.headers.host.split('.').length == 1 ? process.env.DEFAULT_BRAND : req.headers.host.split('.')[0];
  const context = {};
  return (
    <div className={styles.appWrapper}>
      <Provider store={store}>   
        <ApolloProvider client={client}>            
          <StaticRouter location={ req.url } context={context}>
            <Switch>
              <Route exact path="*" render={(props) => <PageLayout {...props} subDomain={subDomain} />} />  
            </Switch>            
          </StaticRouter>
        </ApolloProvider>
      </Provider>
    </div>
  );
}

 what we just did:
– (line 23) getting the sub domain, this time from the express request object, since this is happening on the server side.
– (line 30) passing extra parameter with the subDomain to the PageComponent

 

Now this will work fine for the production build, but if you run yarn start-api it will break with  Invalid Host header message.  This is a security feature and we need to tell Webpack dev server that we are going to have sub-domains.
This could be done by passing disableHostCheck: true and since we are using WebpackDevServer only for development this should be safe enough.

./server-api.js

import WebpackDevServer from 'webpack-dev-server';
import webpack from 'webpack';
import config from './webpack.api.config.js';
require('dotenv').config();

console.log(">>>" + process.env.GRAPHQL_URL);

const compiler = webpack(config);
const server = new WebpackDevServer(compiler, {
  hot: true,
  publicPath: config.output.publicPath,
  historyApiFallback: true,
  disableHostCheck: true,
});
server.listen(8080, 'localhost', function() {});

For the CLI config, if will look like this: --disable-host-check

./package.json

...
    "start-cli": "webpack-dev-server --disable-host-check --hot --history-api-fallback --config webpack.cli.config.js",
...

 

 

Passing brand name to the components

This could be achieved in many different ways:
– we could either use redux and add the brand property there, exposing it to all connected components (which we will do later in this tutorial)
– or we could simply pass it as a property from the PageLayout component.

Let’s do the second one since it is straight forward.

./containers/PageLayout/index.js

import React, { Component } from 'react';
import ComponentList from './ComponentList';
import Loading from '../../components/Loading';
import query from './query';
import { graphql } from 'react-apollo';
const styles = require('./styles.scss');
class PageLayout extends Component {
    constructor(props) {
      super(props);      
    } 
  
    render() {
      if(!this.props.data.getPageByUrl) {
        return (<Loading />);
      }     

      const subDomain = this.props.subDomain;

      const allLayout = this.props.data.getPageByUrl.layout.map((layoutList) => {
        const layout = layoutList.components.map((component, id , components) => {
          const componentName = component.name;        
          const ChildComponent = ComponentList[componentName];
          if(typeof ChildComponent === 'undefined') {
            return(
              <div key='{id}' className={styles.error}>Can't find {componentName} component!</div>
            );
          }
          return (
              <ChildComponent key={componentName} subDomain={subDomain}  />
          );
        });
        return layout;
      });
      return(
        <div className={styles.app}>
          {allLayout}
        </div>
      );
    }
}
export default graphql(query, {
    options(props) {
      return {
        variables: {
          url: props.history.location.pathname
        },
      };
    },
  })(PageLayout);

 

Adding brand specific styling to the component

Coming up with a good naming convention and folder structure is very important, but I will leave this to you to research.

I would propose the simplest one:

component
|- brands
|  |_ one
|     |- styles.scss
|  |_ two
|     |- styles.scss
|- index.js

./components/Home/index.js

import React from 'react';

const Home = ( {subDomain} ) => {
  const styles = require(`./brands/${subDomain}/styles.scss`);

  return (
    <div>
      <div className={styles.wrapper}>This is my home section!</div>
    </div>
  )
}
export default Home;

yarn start

hit one.localhost:3006/home and then two.localhost:3006/home and you will notice the difference right away!

But how this was achieved without re-rendering the component?

Let’s look at component’s css file (it might be 1.css or different number but look at the net tab and make sure that the CSS contains something like this):

.one-wrapper{background:#8d8dac;color:#fff}.one-wrapper,.two-wrapper{text-align:center;font-family:MyFont}.two-wrapper{background:#fff;color:#000}

– first brand has .one-wrapper{background:#8d8dac;color:#fff} and the second has two-wrapper{background:#fff;color:#000} and all CSS that is in common is added like this: .one-wrapper,.two-wrapper{text-align:center;font-family:MyFont} so no repeating CSS if it’s the same between brands.
Basically now the css file for this component will have all styling for both brands.
This is nice but not perfect. We still load unnecessarily the styles for the brands that we are not in to. Let’s see how to fix this in the next chapter.

branch-name:  
Click To Copy

 

 

 

Adding html.js component

branch-name:  
Click To Copy

 

Let’s clean up the code a bit and move the html code from ./ssr-server.js to a separate component called html.js.

./html.js

import React from 'react';

const Html = ({ content, cssBundles, jsBundles, apolloClient }) => (
  <html lang="en">
  <head>
    <meta charSet="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Server Side Rendering and Bundle Splitting</title>
    <link
    href="/dist/main.css"
    rel="stylesheet"
    as="style"
    media="screen, projection"
    type="text/css"
    charSet="UTF-8"
  />

    {
      cssBundles.map( (bundle) => 
        (<link
          href={`${bundle.publicPath}`}
          rel="stylesheet"
          as="style"
          media="screen, projection"
          type="text/css"
          charSet="UTF-8"
        />))
    }

    {jsBundles.map( ( {file}) => (<script src={`/dist/${file}`}>{file}</script>) )}
  </head>
  <body cz-shortcut-listen="true">
    <div id="root" dangerouslySetInnerHTML={{ __html: content }} />
    <script dangerouslySetInnerHTML={{
          __html: `window.__APOLLO_STATE__=${JSON.stringify(apolloClient.cache.extract())}`}} />
  
    <script src="/dist/main-bundle.js"></script>
  </body>
</html>  

);

export default Html;

what we just did:
– we created a plain react component that will accept 3 parameters:
    – content [string]: rendered components returned from react-apollo  renderToStringWithData(…)
    – cssBundles [array of CSS bundle objects]:
    – jsBundles [array of js bundle objects]:
apolloClient [Object]:
An instance of the Apollo client.

 

And now, let’s remove the HTML coder from ./server.js and add the new component instead, passing all necessary parameters.

./server-js

import React from 'react';
import express from 'express';
import App from './src/components/App/ssr-index';
import Loadable from 'react-loadable';
import manifest from './dist/loadable-manifest.json';
import { getDataFromTree } from "react-apollo";
import { ApolloClient } from 'apollo-client';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { renderToStringWithData } from "react-apollo"
import { createHttpLink } from 'apollo-link-http';
import { getBundles } from 'react-loadable/webpack';
import ReactDOMServer from 'react-dom/server';
import Html from './html.js';

const PORT = process.env.PROD_SERVER_PORT;
const app = express();

app.use('/server-build', express.static('./server-build'));
app.use('/dist', express.static('dist')); // to serve frontent prod static files
app.use('/favicon.ico', express.static('./src/images/favicon.ico'));

app.get('/*', (req, res) => {

  const GRAPHQL_URL = process.env.GRAPHQL_URL;
  const client = new ApolloClient({
    ssrMode: true,
    link: createHttpLink({
     uri: GRAPHQL_URL,
     fetch: fetch,
     credentials: 'same-origin',
     headers: {
       cookie: req.header('Cookie'),
     },
   }), 
    cache: new InMemoryCache()
  });    

  // Prepare to get list of all modules that have to be loaded for this route
  const modules = [];
  const mainApp = (
    <Loadable.Capture report={moduleName => modules.push(moduleName)}>
      <App req={req} client={client} />
    </Loadable.Capture>    
  );

  // Execute all queries and fetch the results before continue
  getDataFromTree(mainApp).then(() => {        
    // Once we have the data back, this will render the components with the appropriate GraphQL data.
    renderToStringWithData(<App req={req} client={client} />).then( (HTML_content) => {
      // Extract CSS and JS bundles
      const bundles = getBundles(manifest, modules); 
      const cssBundles = bundles.filter(bundle => bundle && bundle.file.split('.').pop() === 'css');
      const jsBundles = bundles.filter(bundle => bundle && bundle.file.split('.').pop() === 'js');
    
      const html = <Html content={HTML_content} cssBundles={cssBundles} jsBundles={jsBundles} apolloClient={client} />;

      res.status(200);
      res.send(`<!doctype html>\n${ReactDOMServer.renderToStaticMarkup(html)}`);
      res.end(); 
    });    



  }).catch( (error) => {
    console.log("ERROR !!!!", error);
  });
});

Loadable.preloadAll().then(() => {
  app.listen(PORT, () => {
    console.log(`? Server is listening on port ${PORT}`);
  });
});
branch-name:  
Click To Copy