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

 

 

Sorting algorithms

Task

Sort an array of integers in descending order.

Example:

Given an array of 4 elements

 [3,15,1,5]

Produce an array that will look like this:

 [1,3,5,15]

 

Solution

Brute force using the “selection sort” algorithm.

  1. Starting with the first number 3 we assume that this is our smallest number since we don’t know the others.
  2. Then we iterate through the whole array comparing 3 with other numbers.
  3. If we find number that is smaller than 3 (in our case 1) this will become our smallest number, and we continue comparing it to the end of the array.
  4. when we reach the end of the array we swap the first number, that we assumed that is the smallest one with the newly discovered smallest number (in our case number 1 at third position), and the array will look like this now: [1,15,3,5]
  5. Now as we know for sure that the number at the first position (number 1) is the smallest one, we can start from position 2 and repeat steps 2 to 5 till we checked all numbers in the array.

 

function sortArray(list) {
    var smallestIndex;    
    for(var i = 0; i < list.length; i ++) {
        smallestIndex = i;
        for(var ii = i + 1; ii < list.length;ii ++) {
            smallestIndex = list[ii] < list[smallestIndex] ? ii : smallestIndex;
        }
        var larger = list[i];
        list[i] = list[smallestIndex];
        list[smallestIndex] = larger;

    }
    return list;
}

var listArray = [3,15,1,5];
var result = sortArray(listArray);

console.log(result);

 

Better approach:

Merge sort algorithm.

Let’s consider this example with adding more numbers: [3,15,1,5,4,9]

3,15
1,5
--------
9,4


1,3,5,15	| 1
4,9			

3,5,15		| 1,3
4,9			

5,15		
4,9		| 1,3,4

5,15
9		| 1,3,4,5

15
9		| 1,3,4,5,9

15		| 1,3,4,5,9,15

coming soon…

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 !");
})();

 

Selenium and PHP – Write a snapshot comparing tool

The Agenda

This tutorial explains how to write a script that would tale a list of URLs, and create a snapshot images with them. Next time when you run the script it will compare the images and alert if there are some differences.

This is very helpful while active developing  because it could identify unexpected changes in the pages and potential errors.

Run Selenium standalone server

Download Selenium Standalone Server from here

You could put the jar file wherever you want but I personally prefer to keep things more organized and to put it in my home directory.

cp selenium-server-standalone-3.141.59.jar ~/.

Also we could create a shell script to start the server.

./start-selenium.sh

java -jar selenium-server-standalone-3.141.59.jar

Start the server ./start-selenium.sh and check if the server is running by navigating the browser to : http://localhost:4444/wd/hub/static/resource/hub.html

Install PHP composer.

Next step will be to install composer in our home folder, since we will need it to install the webDriver. Create a new shell scripts with the following contents:

php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('sha384', 'composer-setup.php') === '48e3236262b34d30969dca3c37281b3b4bbe3221bda826ac6a9a62d6444cdb0dcd0615698a5cbe587c3f0fe57a54d8f5') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"

then add execute rights chmod +x script.sh and run the script. This will install the composer.

install webDriver

composer require facebook/webdriver

Install chrome driver

brew cask install chromedriver

And now let’s write some PHP code.

<?php

 
use Facebook\WebDriver\Remote\DesiredCapabilities;
use Facebook\WebDriver\Remote\RemoteWebDriver;
use Facebook\WebDriver\WebDriverBy;
use Facebook\WebDriver\WebDriverDimension;
use Facebook\WebDriver\WebDriverExpectedCondition;
use Facebook\WebDriver\WebDriverPoint;
 
$composer_dir = '/Users/toninichev/composer';
require_once $composer_dir . '/vendor/autoload.php';
 
$host = 'http://127.0.0.1:4444/wd/hub'; // this is the default port
 
$driver = RemoteWebDriver::create($host, DesiredCapabilities::chrome());
 
// Set size
$driver->manage()->window()->setPosition(new WebDriverPoint(0,0));
$driver->manage()->window()->setSize(new WebDriverDimension(1280,800));

 
function takeScreenshot($driver, $url, $id) {
    // Navigate to the page
    $driver->get($url);
    
    $driver->wait(3);
    
    // Take a screenshot
    $driver->takeScreenshot(__DIR__ . "/screenshots/scr" . $id . "-tmp.png");
}

$urls = array('https://www.toni-develops.com/', 'https://www.toni-develops.com/2017/04/27/git-bash-cheatsheet/', 'https://www.toni-develops.com/webpack/', 'https://www.toni-develops.com/algorithms/');
//$urls = array('https://www.toni-develops.com/', 'https://www.toni-develops.com/2017/04/27/git-bash-cheatsheet/');

$html = '';

for($i = 0; $i < count($urls); $i++) {
    takeScreenshot($driver,$urls[$i], $i);   

    $a = sha1_file(__DIR__ . "/screenshots/scr" . $i . "-tmp.png");
    $b = file_exists(__DIR__ . "/screenshots/scr" . $i . ".png") ? sha1_file(__DIR__ . "/screenshots/scr" . $i . ".png") : null;
    
    if($a == $b || $b == null) {
        $className = "match";
    }else {
        $className = "noMatch";
    }

    rename(__DIR__ . "/screenshots/scr" . $i . "-tmp.png", __DIR__ . "/screenshots/scr" . $i . ".png");
    $html .= '<div class="picWrapper ' .$className . '"><div><input type="test" value="' . $urls[$i] . '" readonly /></div><img  src="screenshots/scr' . $i . '.png"/></div>';
}


// Close the Chrome browser
$driver->quit();
?>

<html>
<head>
<style>
    .picWrapper input {
        width: 100%;
        text-align:center;
    }

    .picWrapper {
        text-align: center;
    }

    .match {
        background: green;
    }

    .noMatch {
        background: red;
    }


</style>
</head>
<body>

    <?php
        echo $html;
    ?>
      
</body>
</html>