All posts by webammer_anand

Password Strength Meter In React

By Glad Chinda

Initial View

Some time ago I developed a tutorial showing how to create a password strength meter in an AngularJS application using the zxcvbn JavaScript library by Dropbox. Since React has become the most widely used JavaScript framework in the last few years, I thought it would be helpful to develop a similar tutorial for React applications. If you are interested in the AngularJS article, you can take a look at: Password Strength Meter in AngularJS.

In this tutorial, we will create a simple form with fields for fullname, email and password. We will perform some lightweight form validation and also use the zxcvbn library to estimate the strength of the password in the form while providing visual feedback.

Here is a demo of what we would have created by the end of this tutorial.

Why Measure Password Strength?

Passwords are commonly used for user authentication in most web applications and as such, it is required that passwords be stored in a safe way. Over the years, techniques such as one-way password hashing – which involves salting most of the times, have been employed to hide the real representation of passwords being stored in a database.

Although password hashing is a great step in securing password, the user still poses a major challenge to password security. A user who uses a very common word as password makes the effort of hashing fruitless, since a bruteforce attack can crack such password in a very short time. Infact, if highly sophisticated infrastructure is used for the attack, it may even take split milliseconds, depending on the password complexity or length.

Many web applications today such as Google, Twitter, Dropbox, etc insist on users having considerably strong passwords either by ensuring a minimum password length or some combination of alphanumeric characters and maybe symbols in the password.

How then is password strength measured? Dropbox developed an algorithm for a realistic password strength estimator inspired by password crackers. This algorithm is packaged in a JavaScript library called zxcvbn. In addition, the package contains a dictionary of commonly used English words, names and passwords.

Getting Started

Pre-requisites

Before we begin, ensure that you have a recent version of Node installed on your system. We will use yarn to run all our NPM scripts and to install dependencies for our project, so also ensure that you have Yarn installed. You can follow this Yarn installation guide to install yarn on your system. Also, we will use the popular create-react-app package to generate our new React application.

Run the following command to install create-react-app on your system if you haven’t installed it already.

npm install -g create-react-app

Create new Application

Start a new React application using the following command. You can name the application however you desire.

create-react-app react-password-strength

NPM >= 5.2

If you are using npm version 5.2 or higher, it ships with an additional npx binary. Using the npx binary, you don’t need to install create-react-app globally on your system. You can start a new React application with this simple command:

npx create-react-app react-password-strength

Install Dependencies

Next, we will install the dependencies we need for our application. Run the following command to install the required dependencies.

yarn add bootstrap zxcvbn isemail prop-types
yarn add -D npm-run-all node-sass-chokidar

We have installed node-sass-chokidar as a development dependency for our application to enable us use SASS. For more information about this, see this guide.

Now open the src directory and change the file extension of all the .css files to .scss. The required .css files will be compiled by node-sass-chokidar as we continue.

Modify the NPM Scripts

Edit the package.json file and modify the scripts section to look like the following:

"scripts": {
  "start:js": "react-scripts start",
  "build:js": "react-scripts build",
  "start": "npm-run-all -p watch:css start:js",
  "build": "npm-run-all build:css build:js",
  "test": "react-scripts test --env=jsdom",
  "eject": "react-scripts eject",
  "build:css": "node-sass-chokidar --include-path ./src --include-path ./node_modules src/ -o src/",
  "watch:css": "npm run build:css && node-sass-chokidar --include-path ./src --include-path ./node_modules src/ -o src/ --watch --recursive"
}

Include Bootstrap for Default Styling

As you might have noticed, we installed the bootstrap package as a dependency for our application to get some default styling. To include Bootstrap in the application, edit the src/index.js file and add the following line before every other import statement.

import "bootstrap/dist/css/bootstrap.min.css";

Start the Application

yarn start

The application is now started and development can begin. Notice that a browser tab has been opened for you with live reloading functionality to keep in sync with changes in the application as you develop.

At this point, your application view should look like the following screenshot:

Building the Components

Remember we intend to create a simple form with fields for fullname, email and password and also perform some lightweight form validation on the fields. We will create the following React components to keep things as simple as possible.

  • FormField – Wraps a form input field with its attributes and change event handler.

  • EmailField – Wraps the email FormField and adds email validation logic to it.

  • PasswordField – Wraps the password FormField and adds the password validation logic to it. Also attaches password strength meter and some other visual cues to the field.

  • JoinForm – The fictitious Join Support Team form that houses the form fields.

Go ahead and create a components directory inside the src directory of the application to house all our components.

The FormField Component

Create a new file FormField.js in the src/components directory and add the following code snippet to it.

import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';

class FormField extends Component {

  // initialize state
  state = { value: '', dirty: false, errors: [] }

  hasChanged = e => {
    e.preventDefault();

    // destructure props - assign default dummy functions to validator and onStateChanged props
    const { label, required = false, validator = f => f, onStateChanged = f => f } = this.props;

    const value = e.target.value;
    const isEmpty = value.length === 0;
    const requiredMissing = this.state.dirty && required && isEmpty;

    let errors = [];

    if (requiredMissing) {
      // if required and is empty, add required error to state
      errors = [ ...errors, `${label} is required` ];
    } else if ('function' === typeof validator) {
      try {
        validator(value);
      } catch (e) {
        // if validator throws error, add validation error to state
        errors = [ ...errors, e.message ];
      }
    }

    // update state and call the onStateChanged callback fn after the update
    // dirty is only changed to true and remains true on and after the first state update
    this.setState(({ dirty = false }) => ({ value, errors, dirty: !dirty || dirty }), () => onStateChanged(this.state));
  }

  render() {
    const { value, dirty, errors } = this.state;
    const { type, label, fieldId, placeholder, children } = this.props;

    const hasErrors = errors.length > 0;
    const controlClass = ['form-control', dirty ? hasErrors ? 'is-invalid' : 'is-valid' : '' ].join(' ').trim();

    return (
      <Fragment>
        <div className="form-group px-3 pb-2">
          <div className="d-flex flex-row justify-content-between align-items-center">
            <label htmlFor={fieldId} className="control-label">{label}</label>
            {/** Render the first error if there are any errors **/}
            { hasErrors && <div className="error form-hint font-weight-bold text-right m-0 mb-2">{ errors[0] }</div> }
          </div>
          {/* Render the children nodes passed to component */}
          {children}
          <input type={type} className={controlClass} id={fieldId} placeholder={placeholder} value={value} onChange={this.hasChanged} />
        </div>
      </Fragment>
    );
  }

}

FormField.propTypes = {
  type: PropTypes.oneOf(["text", "password"]).isRequired,
  label: PropTypes.string.isRequired,
  fieldId: PropTypes.string.isRequired,
  placeholder: PropTypes.string.isRequired,
  required: PropTypes.bool,
  children: PropTypes.node,
  validator: PropTypes.func,
  onStateChanged: PropTypes.func
};

export default FormField;

We are doing a handful of stuffs in this component. Let’s try to break it down a little bit:

  • Input State
    First, we initialized state for the form field component to keep track of the current value of the input field, the dirty status of the field, and any existing validation errors. A field becomes dirty the moment its value first changes and remains dirty.

  • Handle Input Change
    Next, we added the hasChanged(e) event handler to update the state value to the current input value on every change to the input. In the handler, we also resolve the dirty state of the field. We check if the field is a required field based on props, and add a validation error to the state errors array if the value is empty.

    However, if the field is not a required field or is required but not empty, then we delegate to the validation function passed in the optional validator prop, calling it with the current input value, and adding the thrown validation error to the state errors array (if there is any error).

    Finally, we update the state and pass a callback function to be called after the update. The callback function simply calls the function passed in the optional onStateChanged prop, passing the updated state as its argument. This will become handy for propagating state changes outside the component.

  • Rendering and Props
    Here we are simply rendering the input field and its label. We also conditionally render the first error in the state errors array (if there are any errors). Notice how we dynamically set the classes for the input field to show validation status using built-in classes from Bootstrap. We also render any children nodes contained in the component.

    As seen in the component’s propTypes, the required props for this component are: type ('text' or 'password'), label, placeholder and fieldId. The remaining components are optional.

The EmailField Component

Create a new file EmailField.js in the src/components directory and add the following code snippet to it.

import React from 'react';
import PropTypes from 'prop-types';
import { validate } from 'isemail';

import FormField from './FormField';

const EmailField = props => {

  // prevent passing type and validator props from this component to the rendered form field component
  const { type, validator, ...restProps } = props;

  // validateEmail function using the validate() method of the isemail package
  const validateEmail = value => {
    if (!validate(value)) throw new Error('Email is invalid');
  };

  // pass the validateEmail to the validator prop
  return <FormField type="text" validator={validateEmail} {...restProps} />
};

EmailField.propTypes = {
  label: PropTypes.string.isRequired,
  fieldId: PropTypes.string.isRequired,
  placeholder: PropTypes.string.isRequired,
  required: PropTypes.bool,
  children: PropTypes.node,
  onStateChanged: PropTypes.func
};

export default EmailField;

In the EmailField component, we are simply rendering a FormField component and passing an email validation function to the validator prop. We are using the validate() method of the isemail package for the email validation.

Also notice that all other props except the type and validator props are transferred from the EmailField component to the FormField component.

The PasswordField Component

Create a new file PasswordField.js in the src/components directory and add the following code snippet to it.

import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import zxcvbn from 'zxcvbn';

import FormField from './FormField';

class PasswordField extends Component {

  constructor(props) {

    super(props);
    const { minStrength = 3, thresholdLength = 7 } = props;

    // set default minStrength to 3 if not a number or not specified
    // minStrength must be a a number between 0 - 4

    this.minStrength = typeof minStrength === 'number'
      ? Math.max( Math.min(minStrength, 4), 0 )
      : 3;

    // set default thresholdLength to 7 if not a number or not specified
    // thresholdLength must be a minimum value of 7

    this.thresholdLength = typeof thresholdLength === 'number'
      ? Math.max(thresholdLength, 7)
      : 7;

    // initialize internal component state
    this.state = { password: '', strength: 0 };
  }

  stateChanged = state => {

    // update the internal state using the updated state from the form field

    this.setState({
      password: state.value,
      strength: zxcvbn(state.value).score
    }, () => this.props.onStateChanged(state));

  };

  validatePasswordStrong = value => {
    // ensure password is long enough
    if (value.length <= this.thresholdLength) throw new Error("Password is short");

    // ensure password is strong enough using the zxcvbn library
    if (zxcvbn(value).score < this.minStrength) throw new Error("Password is weak");
  };

  render() {
    const { type, validator, onStateChanged, children, ...restProps } = this.props;
    const { password, strength } = this.state;

    const passwordLength = password.length;
    const passwordStrong = strength >= this.minStrength;
    const passwordLong = passwordLength > this.thresholdLength;

    // dynamically set the password length counter class
    const counterClass = ['badge badge-pill', passwordLong ? passwordStrong ? 'badge-success' : 'badge-warning' : 'badge-danger'].join(' ').trim();

    // password strength meter is only visible when password is not empty
    const strengthClass = ['strength-meter mt-2', passwordLength > 0 ? 'visible' : 'invisible'].join(' ').trim();

    return (
      <Fragment>
        <div className="position-relative">
          {/** Pass the validation and stateChanged functions as props to the form field **/}
          <FormField type="password" validator={this.validatePasswordStrong} onStateChanged={this.stateChanged} {...restProps}>
            <span className="d-block form-hint">To conform with our Strong Password policy, you are required to use a sufficiently strong password. Password must be more than 7 characters.</span>
            {children}
            {/** Render the password strength meter **/}
            <div className={strengthClass}>
              <div className="strength-meter-fill" data-strength={strength}></div>
            </div>
          </FormField>
          <div className="position-absolute password-count mx-3">
            {/** Render the password length counter indicator **/}
            <span className={counterClass}>{ passwordLength ? passwordLong ? `${this.thresholdLength}+` : passwordLength : '' }</span>
          </div>
        </div>
      </Fragment>
    );
  }

}

PasswordField.propTypes = {
  label: PropTypes.string.isRequired,
  fieldId: PropTypes.string.isRequired,
  placeholder: PropTypes.string.isRequired,
  required: PropTypes.bool,
  children: PropTypes.node,
  onStateChanged: PropTypes.func,
  minStrength: PropTypes.number,
  thresholdLength: PropTypes.number
};

export default PasswordField;

About zxcvbn

We finally got to use the zxcvbn JavaScript password strength estimator package in this component. The package exports a zxcvbn() function that takes a (password: string) as its first argument and returns an object with several properties for the password strength estimation. In this tutorial, we would be concerned only with the score property, which is an integer from 0 - 4 (useful for implementing a strength bar).

  • 0 – too guessable
  • 1 – very guessable
  • 2 – somewhat guessable
  • 3 – safely unguessable
  • 4 – very unguessable
console.log(zxcvbn('password').score); // 0

See the following video on testing the zxcvbn() method on the browser’s console.

Here is a breakdown of what is going on in the PasswordField component.

  • Initialization
    In the constructor(), we created two instance properties: thresholdLangth and minStrength from their corresponding prop passed to the component. The thresholdLength is the minimum password length before it can be considered considerably long. It defaults to 7 and cannot be lower. The minStrength is the minimum zxcvbn score before the password is considered to be strong enough. Its value ranges from 0-4. It defaults to 3 if not specified appropriately.

    We also initialized the internal state of the password field to store the current password and password strength.

  • Handling Password Changes
    We defined a password validation function that will be passed to the validator prop of the underlying FormField component. The function ensures that the password length is longer than the thresholdLength and also has a min zxcvbn() score of the specified minStrength.

    We also defined a stateChanged() function which will be passed to the onStateChanged prop of the FormField component. This function retrieves the updated state of the FormField component and uses it to compute and update the new internal state of the PasswordField component.

    A callback function to be called after the internal state update. The callback function simply calls the function passed in the optional onStateChanged prop of the PasswordField component, passing the updated FormField state as its argument.

  • Rendering and Props
    Here we simply rendered the underlying FormField component alongside some elements for input hint, password strength meter and password length counter.

    The password strength meter indicates the strength of the current password based on the state and is configured to be dynamically invisible if the password length is 0. The meter will indicate different colors for different strength levels.

    The password length counter indicates when the password is long enough. It shows the password length if the password is not longer than the thresholdLength, otherwise it shows the thresholdLength followed by a plus(+).

    The PasswordField component accepts two additional optional fields: minStrength and thresholdLength as defined in the component’s propTypes.

The JoinForm Component

Create a new file JoinForm.js in the src/components directory and add the following code snippet to it.

import React, { Component } from 'react';

import FormField from './FormField';
import EmailField from './EmailField';
import PasswordField from './PasswordField';

class JoinForm extends Component {

  // initialize state to hold validity of form fields
  state = { fullname: false, email: false, password: false }

  // higher-order function that returns a state change watch function
  // sets the corresponding state property to true if the form field has no errors
  fieldStateChanged = field => state => this.setState({ [field]: state.errors.length === 0 });

  // state change watch functions for each field
  emailChanged = this.fieldStateChanged('email');
  fullnameChanged = this.fieldStateChanged('fullname');
  passwordChanged = this.fieldStateChanged('password');

  render() {
    const { fullname, email, password } = this.state;
    const formValidated = fullname && email && password;

    // validation function for the fullname
    // ensures that fullname contains at least two names separated with a space
    const validateFullname = value => {
      const regex = /^[a-z]{2,}(s[a-z]{2,})+$/i;
      if (!regex.test(value)) throw new Error('Fullname is invalid');
    };

    return (
      <div className="form-container d-table-cell position-relative align-middle">
        <form action="/" method="POST" noValidate>

          <div className="d-flex flex-row justify-content-between align-items-center px-3 mb-5">
            <legend className="form-label mb-0">Support Team</legend>
            {/** Show the form button only if all fields are valid **/}
            { formValidated && <button type="button" className="btn btn-primary text-uppercase px-3 py-2">Join</button> }
          </div>

          <div className="py-5 border-gray border-top border-bottom">
            {/** Render the fullname form field passing the name validation fn **/}
            <FormField type="text" fieldId="fullname" label="Fullname" placeholder="Enter Fullname" validator={validateFullname} onStateChanged={this.fullnameChanged} required />

            {/** Render the email field component **/}
            <EmailField fieldId="email" label="Email" placeholder="Enter Email Address" onStateChanged={this.emailChanged} required />

            {/** Render the password field component using thresholdLength of 7 and minStrength of 3 **/}
            <PasswordField fieldId="password" label="Password" placeholder="Enter Password" onStateChanged={this.passwordChanged} thresholdLength={7} minStrength={3} required />
          </div>

        </form>
      </div>
    );
  }

}

export default JoinForm;

The JoinForm component wraps the form field components that make up our form. We initialized state to hold the validity of the three form fields: fullname, email and password. They are all false initially – that is invalid.

We also defined state change watch functions for each field to update the form state accordingly. The watch function checks if there are no errors in a field and updates the form internal state for that field to true – that is valid. These watch functions are then assigned to the onStateChanged prop of each form field component to monitor state changes.

Finally, we rendered the form. Notice that we added a validation function to the fullname field to ensure that at least two names separated by a space and containing only alphabet chars are provided.

The App Component

Up till this point, the browser still renders the boilerplate React application. We will go ahead to modify the App.js file in the src directory to render the JoinForm inside the AppComponent.

The App.js file should look like the following snippet:

import React from 'react';
import JoinForm from './components/JoinForm';
import './App.css';

const App = () => (
  <div className="main-container d-table position-absolute m-auto">
    <JoinForm />
  </div>
);

export default App;

Levelling up with SASS

We are one step away from the final look and feel of our application. At the moment, everything seems to be a little out of place. We will go ahead to define some style rules in the src/App.scss file to spice up the form.

The App.scss file should look like the following snippet:

/* Declare some variables */
$primary: #007bff;

// Password strength meter color for the different levels
$strength-colors: (darkred, orangered, orange, yellowgreen, green);

// Gap width between strength meter bars
$strength-gap: 6px;

body {
  font-size: 62.5%;
}

.main-container {
  width: 400px;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
}

.form-container {
  bottom: 100px;
}

legend.form-label {
  font-size: 1.5rem;
  color: desaturate(darken($primary, 10%), 60%);
}

.control-label {
  font-size: 0.8rem;
  font-weight: bold;
  color: desaturate(darken($primary, 10%), 80%);
}

.form-control {
  font-size: 1rem;
}

.form-hint {
  font-size: 0.6rem;
  line-height: 1.4;
  margin: -5px auto 5px;
  color: #999;

  &.error {
    color: #C00;
    font-size: 0.8rem;
  }
}

button.btn {
  letter-spacing: 1px;
  font-size: 0.8rem;
  font-weight: 600;
}

.password-count {
  bottom: 16px;
  right: 10px;
  font-size: 1rem;
}

.strength-meter {
  position: relative;
  height: 3px;
  background: #DDD;
  margin: 7px 0;
  border-radius: 2px;

  // Dynamically create the gap effect
  &:before,
  &:after {
    content: '';
    height: inherit;
    background: transparent;
    display: block;
    border-color: #FFF;
    border-style: solid;
    border-width: 0 $strength-gap 0;
    position: absolute;
    width: calc(20% + #{$strength-gap});
    z-index: 10;
  }

  // Dynamically create the gap effect
  &:before {
    left: calc(20% - #{($strength-gap / 2)});
  }

  // Dynamically create the gap effect
  &:after {
    right: calc(20% - #{($strength-gap / 2)});
  }
}

.strength-meter-fill {
  background: transparent;
  height: inherit;
  position: absolute;
  width: 0;
  border-radius: inherit;
  transition: width 0.5s ease-in-out, background 0.25s;

  // Dynamically generate strength meter color styles
  @for $i from 1 through 5 {
    &[data-strength='#{$i - 1}'] {
      width: (20% * $i);
      background: nth($strength-colors, $i);
    }
  }
}

We have succeeded in adding the styles required by our application. Notice the use of generated CSS content in the .strength-meter:before and .strength-meter:after pseudo-elements to add gaps to the password strength meter.

We also used the Sass @for directive to dynamically generate fill colors for the strength meter at different password strength levels.

The final app screen should look like this:

Final View

With validation errors, the screen should look like this:

Final View with Errors

And without any errors – that is all fields are valid, the screen should look like this:

Final View without Errors

Conclusion

In this tutorial, we have been able to create a password strength meter based on the zxcvbn JavaScript library in our React application. For a detailed usage guide and documentation of the zxcvbn library, see the zxcvbn repository on Github. For a complete code sample of this tutorial, checkout the password-strength-react-demo repository on Github. You can also get a live demo of this tutorial on Code Sandbox.

Source:: scotch.io

Sharing Slides Online

By John Papa

We often share slides online. There are several tools that handle this, but none seem to retain all of the intended experience. Why so hard?!

For example, many of them do not retain animations. Even if they do retain some animations, some are almost always lost. This is likely because the tools we create them with don’t handle them in a consistent manner. I use a lot of subtle transitions, animations, and animated gifs in my presentations – and often these are part of the presentation’s experience.

Here is a quick comparison of some of the slide sharing tools.

Notice I did not include some others that allow you to create slides in HTML. The baseline for this comparison is that I want to create my slides in a tool such as keynote, powerpoint or google slides. Those three prove to be the highest quality and easiest tools to design and create slides quickly. While tools like prezi are very cool, I prefer the more powerful tools listed above.

Site link Retains Animations Full Screen Fonts Retained Animated GIFs Retained Custom Links
Google Slides https://slides.google.com> Most Yes No No Yes
Slides.com https://slides.com> No Yes Yes Yes No
Speaker Deck https://speakerdeck.com> No No Yes Yes No
Slide Share https://www.slideshare.net> No Yes Yes Yes No

Google Slides are very cool for sharing slides. You create them online and they can do quite a lot. I find them a notch behind PowerPoint and Keynote for some animations and transitions, so I still use Keynote and PowerPoint for creating slides. When I upload slides (powerpoint, keynote, or pdf) from those tools into Google Slides, most of the experience is retained. Often the transitions, some animations, and fonts are lost. It’s worth noting that a custom link can be created using a bit.ly or other link sharing tools. I use a custom domain of jpapa.me for mine.

I also like Slides.com a lot. It allows uploading a powerpoint or pdf file, but all animations are lost. However, unlike Google Slides, the fonts are retained in slides.com.

So which do I use? Depends on whether I feel more strongly that the experience is better with the fonts or the with the animations and animated GIFs.

If I am missing a better experience, feel free to add your constructive comment.

Source:: johnpapa

Weekly Node.js Update - #14 - 04.20, 2018

By Tamas Kadlecsik

Weekly Node.js Update - #14 - 04.20, 2018

Below you can find RisingStack‘s collection of the most important Node.js news, updates, projects & tutorials from this week:

Transactions and promises in Node.js

Let’s suppose that we have a database which need to be consistently updated with some batch of data, and a Node.JS application which executes queries in database. How to handle these without any bugs?

Consumer Driven Contract Testing with Node.js & Pact

Watch our keynote to become familiar with the concepts of contract testing and get to know a small library called Pact, that can help integrating contract testing into your current software development workflow.

Yarn vs npm – which Node package manager to use in 2018?

Let’s take a look at the state of Node.js package managers and what they can do for you! We’ll also try to help you to pick one between npm and yarn!

Debugging JavaScript/TypeScript Node apps with Chrome DevTools, VS Code and WebStorm 🐞🔫

How to use Node Inspector to debug both JavaScript and TypeScript Node.js applications using Chrome DevTools, Visual Studio Code and WebStorm? Check it out in this post.

Unlocking the JavaScript Code Interview (an Interviewer Perspective)

Read some tips and tricks to get ready for a JavaScript coding interview and rock your next one!

Creating Simple API in Node.js

In this article, we are going to learn how to create a simple API in Node.js and using MS SQL as a data source on which we are going to perform CRUD operation.

Handling Microservices with Kubernetes – Online Training

We have good news! After receiving a lot of emails asking us to host online trainings, we are happy to announce our two days of ONLINE training, to master Kubernetes.

Previously Node.js Updates:

In the previous Weekly Node.js Update, we collected great articles, like:

  • Introducing Hapi Pal;
  • Node.js can HTTP/2 push!;
  • Consumer Driven Contract Testing with Node.js & Pact;
  • DevOps 101 (not just) from a Node.js Perspective;

& more…

We help you to stay up-to-date with Node.js on a daily basis too. Check out our Node.js news page and its Twitter feed!

Source:: risingstack.com

Why You Shouldn’t Necessarily Start with a Monolith

By Jake Lumetta

For your consideration: monolith vs. microservices

Conventional wisdom counsels starting out with a monolith, but are there exceptions? I asked some top CTOs about their experiences to determine what to consider when making a decision between starting with a monolith versus using microservices straightaway.

My good friend Darby Frey recently kicked off a greenfield project after assuming his new role as Senior Platform Engineering Lead of Gamut. Despite starting out with monolith at his previous company Belly, he discovered that — in the right circumstances — starting with a monolith isn’t always the best way to go.

“As one does, I allowed much of my thinking in my early days [at my new company] to be influenced by my previous company,” Darby told me.

“I was firmly a member of Team Monolith. [I thought] let’s build a single application and just pull things apart later if we start to feel pain.” – Darby Frey

At Belly, Darby and his team broke down their monolith into a fairly large microservices architecture. They managed to get it to a good place, but only after months of trials and tribulations migrating to microservices.

With this experience fresh in his mind, he approached his new project at Gamut a bit more cautious of microservices.

While this was a greenfield project, Darby’s team was small, and he had aggressive timelines, so on the surface, a monolith seemed like the obvious choice.

“[But with this new project], I was anxious to not repeat the mistakes of the past.”

And with that, he found himself faced with a decision we all struggle with, should we start with a monolith or microservices and how do we decide?

Knowing the Difference: Monolith vs Microservices

The terms monolith and microservices get tossed around a lot, but it’s important to remember that “System architectures lie on a spectrum,” as Zachary Crockett, CTO of Particle told me during an interview.

“When discussing microservices, people tend to focus on one end of that spectrum: many tiny applications passing too many messages to each other. At the other end of the spectrum you have a giant monolith doing too many things. For any real system, there are many possible service oriented architectures between those two extremes.” he explained.

Meaning of Monolith

A monolithic application is built as a single, unified unit. Often a monolith consists of three parts:

  • database
  • client-side user interface (consisting of HTML pages and/or JavaScript running in a bowser)
  • server-side application

Another characteristic of a monolith is that it’s often one massive code base. Server side application logic, front end client side logic, background jobs, etc, are all defined in the same code base.

This means if developers want to make any changes or updates, they need to build and deploy the entire stack all at once.

A monolith isn’t a dated architecture that we need to leave in the past. In certain circumstances, a monolith is ideal. I spoke to Steven Czerwinski, Head of Engineering at Scaylr and former Google employee, to better understand this.

“Even though we had had these positive experiences of using microservices at Google, we [at Scaylr] went [for a monolith] route because having one monolithic server means less work for us as two engineers,” he explained. This was back in the early beginnings of Scalyr.

In other words, because his team was small, a unified application was more manageable in comparison to splitting everything up into microservices.

Monolith Pros and Cons

Pros

Fewer cross-cutting concerns: a major advantage associated with monolithic architecture is that you only need to worry about cross-cutting concerns, such as logging or caching, for one application.

Less operational overhead: focusing your finances on one application means that there’s only one application that you need to set up logging, monitoring and testing for. A monolith is also generally less complex to deploy since you aren’t organizing multiple deployments.

Easier testing: with a monolith, automated tests are easier to set up and run because everything is under the same roof. With microservices, tests will need to accommodate for different applications on different runtime environments — which can get complex.

Performance: a monolith can also boast performance advantages in comparison to microservices. That’s often because a monolith uses local calls instead of an API call across a network.

Cons

Overly-tight coupling: while monoliths can help you avoid entanglement as previously mentioned, a monolith becomes more vulnerable to entanglement the larger it grows. Because everything is so tightly coupled, isolation of services within the monolith becomes arduous, making life difficult when it comes to independent scaling or code maintenance.

Harder to understand: it’s common to find that monoliths are more difficult beasts to understand in comparison to microservices, a problem which rears its head when on-boarding new team members. This is sometimes a direct result of the tight coupling, or perhaps dependencies and side-effects which are not obvious when you’re looking at a particular service or controller.

Microservices

The developer community has done itself a disservice with the naming of this architecture. The problem is that that there is nothing inherently “micro” about microservices per se. While they tend to be smaller than the average monolith, they do not have to be tiny. Some are, but size is relative and there’s no standard of unit of measure across organizations.

There is no industry consensus of what exactly microservices are. Nevertheless, here’s my take on the definition of microservices:

Microservice architecture refers to the concept of developing a single application as a suite of small services, in contrast to developing them as one, large ‘monolith.’

Each of those broken-up, individualized services run on their own process, communicating with lightweight mechanisms, often an HTTP resource API. Fully-fledged microservices are independently deployable, and yet can work in tandem when necessary.

Microservices pros and cons

Pros

Better organization: microservice architectures are typically better organized, since each microservice has a very specific job, and is not concerned with the jobs of other components.

Decoupled: decoupled services are also easier to recompose and reconfigure to serve the purposes of different apps (for example, serving both the web clients and public API). They also allow for fast, independent delivery of individual parts within a larger, integrated system.

Performance: under the right circumstances, microservices can have performance advantages depending on how they’re organized because it’s possible to isolate hot services and scale them independent of the rest of the app.

Fewer mistakes: Microservices enable parallel development by establishing a hard-to-cross boundary between different parts of your system. By doing this, you make it hard – or at least harder – to do the wrong thing: namely, connecting parts that shouldn’t be connected, and coupling too tightly those that need to be connected.

Cons

Cross-cutting concerns across each service: As you’re building a new microservice architecture, you’re likely to discover lots of cross-cutting concerns that you did not anticipate at design time. You’ll either need to incur the overhead of separate modules for each cross-cutting concern (i.e. testing), or encapsulate cross-cutting concerns in another service layer that all traffic gets routed through. Eventually, even monolithic architectures tend to route traffic through an outer service layer for cross-cutting concerns, but with a monolithic architecture, it’s possible to delay the cost of that work until the project is much more mature.

Higher operational overhead: Microservices are frequently deployed on their own virtual machines or containers, causing a proliferation of VM wrangling work. These tasks are frequently automated with container fleet management tools.

Practical Considerations for Choosing Microservices or a Monolith

Although it’s important to have a general sense of the pros and cons of monoliths and microservices, knowing those doesn’t necessarily guide decision-making. To help with that, I asked dozens of CTO’s that have made this decision how and why they made the decision they made. Distilled below are several key considerations you should make when deciding for your own organization.

Consideration #1: Are you in familiar territory?

Darby and his team at Gamut were able to delve directly into microservices because he had experience with eCommerce platforms, and his company had a wealth of knowledge concerning the needs and demands of their customers. If he was traveling down an unknown path on the other hand, a monolith may have actually been the safer option.

Often startups are born out of pains experienced at previous companies. In those scenarios sometimes it’s quite clear scaling is going to be a primary requirement, especially in infrastructure based services like cloud log management.

Consideration #2: Is your team prepared?

Does your team have experience with microservices? What if you quadruple the size of your team within the next year, are microservices ideal for that situation? Evaluating these dimensions of your team is crucial to the success of your project.

Julien Lemoine, CTO at Algolia, chimed in on this point:

“We have always started with a microservices approach. The main goal was to be able to use different technology to build our service, for two big reasons:

1) We want to use the best tool for each service. Our search API is highly optimized at the lowest level and C++ is the perfect language for that. That said, using C++ for everything is a waste of productivity, especially to build a dashboard!

2) The want the best talents and using only one technology would limit our options. This is why we have different languages in the company.”

If your team is prepared, starting with microservices is wise as it allows you to get used to the rhythm of developing in a microservice environment, right from the start.

Consideration #3: How’s your infrastructure?

In reality, you’re going to need cloud-based infrastructure to make microservices work for your project.

“[Previously], you would want to start with a monolith because you wanted to deploy one database server. The idea of having to set up a database server for every single microservice and then scale out was a mammoth task. Only a huge, tech-savvy organization could do that,” David Strauss, CTO of Pantheon explained to me.

“Whereas today with services like Google Cloud and Amazon AWS, you have many options for deploying tiny things without needing to own the persistence layer for each one.”

Consideration #4: What’s your business risk tolerance?

“Every time we consider introducing a new service, we have to consider the operational cost of doing so. Each new service adds to the complexity of the infrastructure and makes it a bit harder to reason about service relationships within the system.” — Oleksiy Kovyrin, Head of Swiftype SRE, Elastic

You may think microservices is the “right” way to go as a tech-savvy startup with high ambitions. But microservices pose a business risk. David Strauss explained:

“A lot of teams overbuild their project initially; everyone wants to think their startup will be the next unicorn and that they should, therefore, build everything with microservices or some other hyper-scalable infrastructure. But that’s usually wrong, almost all the time,” he said.

One example of this from his early days at Pantheon was a system that was limited to a single VM. They thought it would be a month or two until they’d be forced to scale it. It ended up being over a year — and they ended up scaling it a completely different way than they had anticipated.

He went on to say that, in these cases, the areas that you thought you needed to scale are probably not the parts that will need to scale first, and that results in misplaced effort even for the systems that will need to scale.

Context, context, context

“Know thyself” is a crucial mantra for teams looking to make a decision about microservices versus a monolith. Through trial, error, and success, CTOs described what worked best for them given their specific context, and I’ve distilled this into scenarios that indicate that you should strongly consider one architectural approach over another.

When to start with a monolith

Your team is at founding stage: Your team is small, between 2-5 members, and is thus unable to tackle a broader and high-overhead microservices architecture.

You’re building an unproven product or proof of concept: Are you building an unproven product in the market? If it’s a new idea, it’s likely going to pivot and evolve over time, so a monolith is ideal to allow for rapid product iteration. Same applies to a proof of concept where your goal is just to learn as much as possible as quickly as possible, even if you end up throwing it away.

You have no microservices experience: If your team has no prior experience with microservices, unless you can justify taking the risk of learning “on the fly” at such an early stage, it’s likely another sign you should stick to a monolith to start.

When to start with microservices

You require quick, independent service delivery: If it’s snappy, isolated service delivery that you need, microservices are your best bet. However, depending on the size of your team, it can take some time before you see any service delivery gains versus starting with monolith.

A piece of your platform needs to be extremely efficient: If your business is doing intensive processing of petabytes of log volume, you’ll likely want to build that service out in a very efficient language (i.e. C++) while your user dashboard may be built in Ruby on Rails.

You plan to scale your team: Starting with microservices gets your team used to developing in separate small teams from the beginning, and having teams separated by service boundaries makes scaling your development organization easier.

Take-away

Do not attempt to take on microservices just because other engineering teams are having success with them or because microservices seem like a hot topic. Your own context, evaluated against the above considerations, is the key to deciding if you should start with monolith or microservices.

For more content like this, check out our free eBook, Microservices for Startups.

Source:: scotch.io

Build an Amazon-Like Product Preview App using Vue.js

By Chris Nwamba

If you have ever used online stores like Amazon or eBay, you have definitely used the preview feature. It shows you images or videos of the product so you know what to expect before making a purchase.

In this article, we are going to examine how to build a single page Amazon-like preview app
with Vue.js

What we will build won’t look exactly like the Amazon website, but will exhibit the product preview characteristics.

Dependencies

To build this app, we are going to use a Node server for the back-end and Vue.js for our front-end. Before we get to work, you need to verify that you have a couple of things installed on your machine:

Building the Front-end

We going to use Vue.js to build the front-end. Vue.js is a progressive JavaScript framework that is quick and easy to use.

Installing Vue.js

You are going to need Vue.js installed on your machine. You can confirm your installation by running:

    vue --version

If you get a version number as a result then you have Vue.js installed. If not, it is recommended that you install the Vue CLI by running:

    npm install --global vue-cli

To create the frontend server, run the following :

    mkdir preview-app
    vue init webpack frontend

This creates a vue example project which we are now going to tweak and adjust.

Installing The Node Modules

We are going to use axios to make get requests from one of our Vue.js components so install it by running the following in the frontend directory:

    cd frontend
    npm install axios

Creating the Listing Component

Listing Component

This Listing component is responsible for showing all the products we have in the store and adding a link to the view for the product.

To create the Listing component, we run the following :

    touch Listing.vue

In the Listing.vue , we need to first import the axios module:

    <script>
    import axios from 'axios'
    //...

And now we use the module to fetch the product listing :

    //...
    export default {
      name: 'Listing',
      data () {
        return {
          products : []
        }
      },
      mounted : function(){
        axios.get('http://localhost:3128/products').
        then( result => {
          console.log( result );
          this.products = result.data;
        })
      }
    }
    </script>

We can see above that once the component is mounted, we make a call to our back-end server to fetch the available products and then assign it to the product data of the component.

The template for the component looks like this :

    <template>
      <div class="listing container">
        <div class="title" style="margin-bottom:40px;">
          <h1>Products on Sale</h1>
        </div>
        <div class="row">
          <div class="col-sm-2">
            <h2>#</h2>
          </div>
          <div class="col-sm-8">
            <h2>PRODUCT NAME</h2>
          </div>
          <div class="col-sm-2">
            <h2>GO TO</h2>
          </div>
        </div>

        <template v-for="product in products">
          <div class="row" style="margin-bottom:20px;">
            <div class="col-sm-2" >
              <p>{{ product.id }}</p>
            </div>
            <div class="col-sm-8">
              <p>{{ product.name }}</p>
            </div>
            <div class="col-sm-2">
              <router-link :to="{path: '/product/'+product.id }">View Product</router-link>
            </div>
          </div>
        </template>
      </div>
    </template>

In the template above, we list out the products as divs and add an action button that takes you to the single product page itself.

Creating the Preview Component

Product Preview Component

Product Preview Component

The Preview component is responsible for displaying data and images related to the selected product from the previous view. When the component is created, we make a get request to the backend server to fetch all the data for the particular id and then display the media in the form of a carousel on the right side of the screen.

Create the Preview.``v``ue file by running :

    touch Preview.vue

In the Vue.js file, we first import the axios module :

    <script>
    import axios from 'axios'
    //...

Now, we build the component :

    //...
    export default {
      name: 'Preview',
      data () {
        return {
          media :[],
          product_name : "",
          product_desc : "",
          product_price : ""
        }
      },
      mounted : function(){
        // now we get all the related infomation for the particular product id
        axios.get(`http://localhost:3128/getProductInfo/${this.$route.params.id}`)
        .then( res => {
          this.media = res.data.media;
          this.product_name = res.data.product_name;
          this.product_desc = res.data.product_desc;
          this.product_price = res.data.product_price;

        })
      },
      methods : {
        initializePlayer : function(){
          console.log('here')
          var cld = cloudinary.Cloudinary.new({ cloud_name: "og-tech", secure: true});
          var demoplayer = cld.videoPlayer('video-player');
        }
      }
    </script>

After the post request is made, the model is updated with the data that was returned as a JSON response on the back-end.

Our view has a template that looks as follows :

    <template>
      <div class="preview">
        <div class="row">
          <div class="col-sm-6">
            <!--  this part will contain the product info -->
            <h1> {{ product_name }} </h1>
            <div>
              <p> {{ product_desc }} </p>
              <p> Price : ${{ product_price }} </p>
            </div>
          </div>
          <div class="col-sm-6">
            <!--  this part will contain the images -->
            <div id="demo" class="carousel slide" data-ride="carousel">
              <!-- Indicators -->
              <ul class="carousel-indicators">
                <template v-for="single_media in media">
                  <template v-if="single_media.id == 0">
                    <li data-target="#demo" v-bind:data-slide-to="single_media.id" class="active"></li>
                  </template>
                  <template v-else>
                    <li data-target="#demo" v-bind:data-slide-to="single_media.id"></li>
                  </template>
                </template>
                <!-- <li data-target="#demo" data-slide-to="0" class="active"></li>
                <li data-target="#demo" data-slide-to="2"></li> -->
              </ul>
              <!-- The slideshow -->
              <div class="carousel-inner">
                <template v-for="single_media in media">
                  <template v-if="single_media.id == 0">
                    <div class="carousel-item active">
                      <template v-if="single_media.type == 'image'">
                        <img class="img-responsive single-image" v-bind:src="single_media.url"/>
                      </template>
                      <template v-else>
                       <video
                        id="video-player"
                        controls
                        class="single-image cld-video-player cld-video-player-skin-dark"
                        v-bind:data-cld-source="single_media.url"
                        >
                        </video> 
                      </template>
                    </div>
                  </template>
                  <template v-else>
                    <div class="carousel-item">
                      <template v-if="single_media.type == 'image'">
                        <img class="img-responsive single-image" v-bind:src="single_media.url"/>
                      </template>
                      <template v-else>
                        <video
                        id="video-player"
                        controls
                        class="single-image cld-video-player cld-video-player-skin-dark"
                        v-bind:data-cld-source="single_media.url"
                        >
                        </video>
                      </template>
                    </div>
                  </template>
                </template>
              </div>
              <!-- Left and right controls -->
              <a class="carobbusel-control-prev" href="#demo" data-slide="prev">
                <span class="carousel-control-prev-icon"></span>
              </a>
              <a class="carousel-control-next" href="#demo" data-slide="next"  v-on:click="initializePlayer()">
                <span class="carousel-control-next-icon"></span>
              </a>
            </div>  
          </div>
        </div>

      </div>
    </template>

In the template above, what we want to achieve is to display the media for the particular product. If you take a look at when we built the component, we make a request to the backend and then send the response to the Vue component.

We need to know if the media being displayed is an image or a video. So we check in the template;

    //..
    <template v-if="single_media.type == 'image'">
      <img class="img-responsive single-image" v-bind:src="single_media.url"/>
    </template>
    <template v-else>
     <video
      id="video-player"
      controls
      class="single-image cld-video-player cld-video-player-skin-dark"
      v-bind:data-cld-source="single_media.url"
      >
      </video> 
    </template>
    //..

If it has type of image, we display the image in the carousel but if type is a video, we use the Cloudinary VIdeo Player to display the video. To initialize the video player, we add v-on:click event to the > button.
Once the button is clicked, the video player is initialized with the video.

PS: Cloudinary’s video player also playing videos by tags and playing playlists. You can read more about it here.

The preview view has some scoped styling as follows :

    <style scoped>
      h1, h2 {
        font-weight: normal;
      }
      ul {
        list-style-type: none;
        padding: 0;
      }
      li {
        display: inline-block;
        margin: 0 10px;
      }
      a {
        color: #42b983;
      }
      .carousel-inner{
        height : 500px;
      }
      .carousel-item{
        height : 100%;
      }
      .single-image{
        width : 100%;
        height: 100%;
        object-fit : fill;
      }
      #demo{
        margin-left: 30px;
        margin-right: 30px;
      }
    </style>

Building the Back-end

To build our back-end, we need to change directory to the root directory of our application and then install the node modules:

    cd preview-app 
    npm install cors express body-parser dotenv request connect-multiparty cloudinary

Once this is done, you have successfully installed all the modules necessary for you to build the project.

Create a server.js file

Now we need to create a file that will contain the instructions for our server to work
In your video-suggestion directory,

    touch server.js

This will be the start-up file that will be referenced when your server is running
In your server.js file, you need to

Import the node modules

    require('dotenv').config()
    const cors       = require('cors')
    const express    = require('express')
    const bodyParser = require('body-parser')
    const multipart  = require('connect-multiparty')
    const request    = require('request')
    const cloudinary = require('cloudinary')

    //...

Once you have imported your node modules, you can then use them freely all through your script.

Create your express app

Now we create our express app instance by adding the following to the server.js

    //...

    const app = express()

    //...

Load the middlewares

We load the middlewares in our server.js by adding the following

    //...

    app.use(cors())
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: false }));
    const multipartMiddleware = multipart();

    //...

Here, we set our app to use cors . We also instructed the app the parse the requests in JSON format.

Configure the Cloudinary Client

We need to configure our cloudinary client using your CLOUD_NAME, API_KEY and API_SECRET

    //...

    cloudinary.config({
        cloud_name: 'CLOUDINARY_CLOUD_NAME', 
        api_key: 'CLOUDINARY_API_KEY', 
        api_secret: 'CLOUDINARY_API_SECRET'
    });

    //...

Once this is done, then we have successfully configured our Cloudinary client.

Create app routes

Our back-end server is very simple, it’s an express web server with two major routes:

  • /products – Lists all the products available for sale.
  • /getProductInfo – Returns data for the selected product.
    //...
    app.get('/products', multipartMiddleware, function(req, res){
      return res.json([
        {id: '1', name: 'UltraLight Mechanical Keyboard'},
        {id: '121', name: 'IPhone X'},
        {id: '23', name: 'Tesla S'},
        {id: '42', name: 'Work Shoes'}
      ]);
    });

    app.get('/getProductInfo/:id', multipartMiddleware, function(req, res){
      console.log( req.params.id );
      return res.json({
        media:        [
          {
            id:       '0',
            type:     'image',
            url:      'https://static.pexels.com/photos/265631/pexels-photo-265631.jpeg'
          },
          [...]
          {
            id:       '3',
            type:     'video',
            url:      
                'http://res.cloudinary.com/og-tech/video/upload/s--ZWPqo282--/v1514966645/sea_turtle-short_z1pr4o.mp4'
          },
        ],
        product_name: 'Ultra Thin Mechanical Keyboard',
        product_desc: 'This keyboard gives you the clack to your click',
        product_price: '200'
      })
    });

    //...

In the above, we see the routes returning responses in JSON format for it to be further used at the frontend. You may have observed that a lot (all) the data returned to the user was static. In a real-world application, you would return dynamic data to the user.

The /productInfo route accepts the id of your product so that is what you would use to identify what data to serve instead of just returning static json data. In other words, you can make further query to your database or cloud storage to fetch the information and return the data in the format used above.

Configure Application Port

Now we set the port we want the app to listen on:

    [...]

    let port = 3128 || process.env.PORT;

    app.listen(port, function () {
      console.log('App listening on port ' + port + '!');
    });

Application Demo

Conclusion

In this article we have see how to leverage Cloudinary’s image and video capabilities using Vue.js to build an Amazon-like preview app for products.

You also can head over here if you want to find out more about optimizing images served on your website f and more about improving your store’s SEO by engineering better Google mobile search ranking through image optimization.

Now you can use concepts shared here in building your own application for the #NextBillionUsers

Here a link to the GitHub repository for more references.

Source:: scotch.io