Category: JavaScript (ES6+)

Babel and Webpack for compiling and bundling JavaScript ES6 (ES6/ ES7/ ES8)

In this article i am going to explain how to use the Babel compiler  for compiling the javascript from ES6(or higher ES version) to ES5 compliant version. In addition, the webpack will be used for  executing barbel compiler and bundling the multiple javascript dependencies into a single file.

The majority of the internet browsers are supported to run ES5 compliant JavaScript. Therefore if you develop your application with ES6 or any other latest ECMAScript version, you may need to compile or transform it into ES5 compliant version for running it in most of the available browsers.

 

What is Babel?

Babel is a JavaScript transpiler (or known as javascript compiler). Babel enables us to write modern JavaScript that will be “transpiled” to widely-supported ES5 JavaScript. We call this process as “transpiling”.

Want to know more about Babel? Click here 

 

Start the project with NPM 

NPM is stands for Node Package manager. As the name implies , it is the package manager for JavaScript. This is installed when you install the NodeJs in your development environment.  NPM contains a large number of reusable JavaScript packages and modules.

to check and verify the NPM installation in your development environment, you can run the following command in the terminal . It will display the NPM version if it is already installed.

npm -v

 

If you do not have npm installed in your machine, you can refer the official website (www.npmjs.com)  for getting the instructions for installing it.

So once the installation is verified, we can create the JavaScript project with NPM with following command. This will create a standard package.json file for the project.

npm init

 

Screen Shot 2018-01-27 at 6.52.03 PM.png

What is package.json file?

This is the file that contains the all important information about your project(package). it contains information about project name, version, author, license, main script, list of dependencies, how to build the project, how to start the project etc..

Please refer the official documentation for more information.

The generated package.json file for this project can be shown as below.

 

Here you can see that main script file is main.js . So we need to create it. In addition i have created two other JavaScript files and do some ES6 based javascript codings to demonstrate the beauty of the ES6 and Webpack bundler.

 

calculator.js

Here is the beauty of the ES6. we can have a class with both static and non-static methods.

 

welcome.js

returns the welcome message by concatenating the user given name.

 

main.js

 

window object represents the browser window. if any property (variable, function or class) is assigned to the window, then it can be accessed through the browser. That is why we have assigned the properties (class and methods) for the window object here.

 

index.html 

you can see that we have imported the main.js file here. That file contains the ES6 based javascript and that is not compiled down to ES5.

when you loading the page on browser, you might get following error in the browser console.

main.js  Uncaught SyntaxError: Unexpected token export

 

This means that your browser is not supported for ES6  and it cannot understand the syntaxes written in ES6 style. Therefore we need to transform the ES6 style code into browser understandable ES5 style code. In this situation, Babel comes to play role of traspiling the source code.

 

Setting up Babel 

We need to install following few dependencies for getting the babel compiler for the project.

  • babel-core :- includes the babel core modules
  • babel-loader  :-  loader for running the ES6+ and JSX with webpack. This will be configured in the webpack.config.js
  • babel-preset-env :- (or any other preferred preset). The preset will also be configured in the webpack.config.js or can be defined in .babelrc file
  • babel-polyfill :- A polyfill is a piece of code, that replicate the fully ES6+ environment into the targeted runtime environment. Therefore some of the transpiled ES6+ based methods and objects can be executed in ES5 environment without any runtime error.  If you want to learn more about babel-polyfill, please click here to go to my article on that.

 

Here is a good article to learn more about babel.

https://kleopetrov.me/2016/03/18/everything-about-babel/

 

What is the purpose of barbel preset?

presets are plugins that enable the features and support for particular language. for example, If the JavaScript code is based on ES6, we need to tell the babel transpiler that the source code is based on ES2015. So it will enables the required features for transforming the ES6 code to ES5.  if the source codes is based on reactjs, we need to enable the react preset.

For more information about “preset”, please visit the official website.

https://www.npmjs.com/package/babel-preset-env

https://babeljs.io/docs/plugins/#presets 

 

Why do we enable “babel-preset-env” without enabling “babel-preset-es2015” ?

This is a good point. This preset will automatically detect the ECMAScript version of your source code and enable the related features for compiling the source code into ES5 version.

babel-preset-env is the latest babel preset that compiles ES2015+ (ES6, ES7, ES8 ) down to ES5 by automatically determining the Babel plugins needed based on your targeted browser or runtime environments.

Without any configuration options, babel-preset-env behaves exactly the same as babel-preset-latest (or babel-preset-es2015, babel-preset-es2016, and babel-preset-es2017 together).

In our case, we are trying to compile the ES6 code into ES5. So here babel-preset-env can be used.

We will install all the required dependencies for the babel with following command. This command should be run in your project directory.

npm install --save-dev babel-core babel-loader babel-preset-env

 

–save :-

This will install the given dependencies in the project locally. that means the dependencies are installed in the node_modules directory that is located inside your project directory.

If you want to install it in globally, use -g flag. Then the dependencies will be installed in the /usr/local/lib/node_modules directory as global dependencies. 

 

–save-dev :-

install the dependencies locally as dev dependencies. If you open the package.json, you can notice that the installed dependencies have been categorized under devDependencies. The dev dependencies are used only for development purpose and those should be omitted when the package is released for the production. Otherwise the final distributed package will contains overhead/unnecessary dependencies that are not required in runtime (production environment).  dependencies will be included in the final distribution and devDependencies will be neglected.

Please refer the following snapshot of package.json.

"devDependencies": {
  "babel-loader": "^7.1.2",
  "babel-core": "^6.26.0",
  "babel-preset-env": "^1.6.1"
}

 

 

Setting up Webpack

Here i am assumed that you have the basic knowledge and understanding about webpack. If you don’t have, please go and refresh your knowledge about webpack.

I have found that below articles are useful for beginners who want to learn webpack.

https://tutorialzine.com/2017/04/learn-webpack-in-15-minutes

https://blog.andrewray.me/webpack-when-to-use-and-why/

 

So we will be moving forward with setting up webpack. First we need to install the webpack dependencies for the project and there are two dependencies required.

  • webpack
  • webpack-dev-server

These dependencies can be installed with following command.

npm install webpack webpack-dev-server --save-dev

 

After installing the webpack dependencies, the devDependencies of the package.json should looks like below.

"devDependencies": {
  "babel-core": "^6.26.0",
  "babel-loader": "^7.1.2",
  "babel-preset-env": "^1.6.1",
  "webpack": "^3.10.0",
  "webpack-dev-server": "^2.11.1"
}

 

So once the dependencies are installed, we need to create a webpack.config.js file and do the necessary configuration for the webpack.

 

Adding webpack.config.js

Add the webpack.config.js file in the root of your project. The sample configuration for the webpack.config.js can be given as follows.

With Webpack, running your JavaScript and JSX through Babel is a simple as adding the babel-loader to your webpack.config.js.

 

webpack.config.js

 

Here are the important things to note from the webpack.config.js

  •  The entry point of the app has been named as app.js
  •  The output file will be app.bundle.js and it will be stored in the build directory.
  •  babel-loader has been added as a loader for handling  .js and .jsx file (match of the regular expression)
  • node_modules directory will be excluded by the babel-loader when webpack is running.
  • babel-preset-env  (presets: [env])  has been added in the webpack configuration. Therefore .babelrc  file is not required for this setup.

 

Hint:
You can commit the  preset configuration in the webpack.config.js and 
replace it with .babelrc file.

 

Adding the build command for package.json

In the package.json we need to specify the build command as “build” “webpack” under the “scripts“.

"scripts": {
  "build": "webpack -p",
  "test": "echo \"Error: no test specified\" && exit 1"
},

 

weback  -p  :- run the webpack in production mode. this will minify the javascript code in the output file.  If you do not use the -p option, then your generated file will not be minified.

This is the finally modified  package.json file of our application.

 

All the related project files and configuration files has been created. So finally, our project structure should looks like below.

Screen Shot 2018-01-28 at 10.05.23 PM.png

 

Building the project with webpack

Now it is the time to build out project with webpack.  So we need to make sure that our javascript files that are in ES6 syntaxes are transform into ES5 with babel (with babel-loader) and  set of javascript dependencies are bundled as one single file (the purpose of webpack). We can run the following command in the command line.

npm run build

 

when you run the build command, it will execute the command given in the package.json under the build script.

"scripts": {
  "build": "webpack -p"
}

 

Since we have used webpack -p , the webpack will be ruin in the production mode.  the output file will contain the minified version of the javascript source file.

 

You can refer the following screenshot for further understanding.

Screen Shot 2018-01-28 at 10.07.41 PM.png

The related javascript source files are compiled and bundled into the build/app.bundle.js  file . You can use that build file in your HTML to import the javascript methods and functionalities.

 

This is the final project structure (after executing the webpack build) and i have given it for your further understanding.

Screen Shot 2018-01-28 at 10.19.05 PM.png

 

Test the app.bundle.js with index.html file 

 

Now we can add the app.bundle.js for the index.html file as a script and run it on browser.

 

Run on browser will give you the following output.  That means our ES6+ syntaxes are compiled down to ES5 and working as we expected.

 

Screen Shot 2018-01-30 at 1.33.05 PM.png

 

You can see that the console.logs are printed as we expected and the result is published to browser. You can play with chrome console to check whether the classes and methods has been assigned/attached to the window. (If you observe the Chrome console output in the screenshot, you can see that i have done it)

 

How to get the Source Code and Run it?

Now we have come to the end of the article.  The source code of this article can be found at GitHub.

click here to download the source code. 

 

Steps by Step guide for building and running the project

Get the source files from the GitHub.

git clone git@github.com:chathurangat/webpack-barbel-for-es6.git

 

Go inside the project directory.

cd webpack-barbel-for-es6

 

Install the dependencies for the first time (locally).

npm install --save

 

Run the webpack build task.

npm run build

 

If you have any further inquiry related to this article, please feel free to contact me.

Thanks

Chathuranga Tennakoon

 

What is babel-polyfill and why it is important?

 

babel-polyfill will emulate a full ES6 environment. For example, without the polyfill, the following code:

function allAdd() {
    return Array.from(arguments).map((a) => a + 2);
}

will be transpiled to:

function allAdd() {
    return Array.from(argument).map(function (a) {
        return a + 2;
    });
}

This code will not work everywhere, because Array.from in not supported by every browser:

Uncaught TypeError: Array.from is not a function

To solve this problem we need to use a polyfill. A polyfill is a piece of code, that replicate the native API that does not exist in the current runtime.

To include the Babel polyfill, we need to install it:

npm install babel-polyfill --save-dev

 

Use the babel-polyfill in your source code

To include the polyfill you need to require it at the top of the entry point to your application. in order to use babel-polyfill withj your applciation, you can use one of following three methods.

 

method 01

With require

require("babel-polyfill");

 

method 02

If you are using ES6’s import syntax in your application’s entry point, you should instead import the polyfill at the top of the entry point to ensure the polyfills are loaded first.

With ES6 import.

import "babel-polyfill";

 

method 03

With webpack.config.js, add babel-polyfill to your entry array:

module.exports = {
  entry: ["babel-polyfill", "./app/js"]
};

JavaScript ES6+ : Syntaxes for implementing private methods, private properties, static properties and static methods in JavaScript class

In this article i am going to explain how to use private methods, properties and static methods and properties in ES6+ based JavaScript class. If you have previous programming experience with OOP (Object Oriented Programming) Language, you may have used private, public and static methods and properties. Today we will look at how the same functionality is achieved with JavaScript.

Lets start our article here.

 

Private methods.

private methods are used only within the class and they are intended to be used by the methods within the class. since the access level is private, those methods cannot be invoked from outside of the application.

 

Why do we need private methods?

First of all we should look at the reason behind the need of the private methods. Those reasons can be described as follows.

  • prevent the code duplication

In your software development life, you might have seen that there are some common logic in a class that need to be reused in more than one method of the same class. So if we do not separate those logic/codings into a separate method, we have to duplicate them in every method. In such case we might need a private method.

  • Improve the code readability and cleanliness. 

Sometimes you might have noticed that there some methods which are lengthy due to many number of code lines. Therefore it is very difficult to read the method contents. Therefore the readability of the method goes down. If you observe those methods carefully,  you can find some similar set of logics that can be separated into groups. So separating those similar logics (groups) into a private methods, may improve the readability of your source code.

Therefore it is good idea to separate and group the similar logic into a private methods which will improve the cleanliness, reusability and readability of your source code.

Ok. enough theories.  Lets look at some coding examples here.

for the demonstration purpose, i will use simple example from java programming language and convert it into the the JavaScript ES6. Then you will be able to understand them easily by comparing each of them.

 

Private members 

First we will look at how to add a private property (member variable) for a class. In java, this can be simply achieved as follows.

 

public class Sample
{
 private String privateProperty;

 public String getPrivateProperty(){
   return privateProperty;
 }
}

 

The same thing can be achieved with JavaScript ES6 is as follows.

let  privateProperty;

class Sample
{
    getPrivateProperty()
    {
        return privateProperty;
    }
}

 

If you want to declare a private property in ES6, it should be declared outside of the class.  Then even if the class is instantiated, the private property cannot be accessed because, it does not belong to the scope of the class.

 

Static properties and methods

In java we can add static members and static methods as follows.

public class Sample
{
    static String staticProperty;
 
    //getter for the static property
    public String getPrivateProperty()
    {
        return staticProperty;
    }

    //another static method 
    public static String sayHello(){
        return "hello";
    }
}

 

The same thing can be achieved with javascript as follows.

let staticProperty;

class Sample
{
    //getter for the staticProperty
    static getStaticProperty()
    {
        return staticProperty;
    }

    //we can add static modifier for methods to make them as static methods
    static sayHello()
    {
      return "hello";
    }
}

 

In java we can  add the static modifier to member variable for making it as a static field. But in javascript, we cannot add such modifiers.  The only way to achieve static filed is to add a static getter for the field the need to be set as static.

static modifier can be added for the methods to make them as static.

 

Private methods

In java private methods can be declared with private access modifier. please refer the below code segment.

public class Sample
{
    public String displayWelcomeMessage(){
        return this.sayHello();
    }

    private String sayHello(){
        return "hello";
    }
}

 

But in javascript, you have to declare it as follows.

let methods = {
    //the multiple private methods can be added here (by comma seperated)
    sayHello(){
        return "hello";
    }
};

class Sample {
    displayWelcomeMessage() {
        return methods.sayHello();
    }
}

 

 

After reading this article, i believe that you got a good understanding of how to declare private and static fields(members) in javascript ES6. In addition, you should have a good understanding of how to declare static methods in a class. In you need any clarification regarding this article, feel free to contact me.

 

 

ES6+ : var, let and const for variable declarations in JavaScript

var, let and const are keywords used to declare variables in javascript.  var and let describes about the access level (or scope) of the declared variable and const keyword determine whether the value of a variable can be re-assigned.  as the name implies, const keyword is used to declare constant in javascript program. we will look at them in detailed in the following sections.

 

Global and Local  variable declaration with var

var keyword is used to declare the variable in javascript. The most of the resources says that var is used to declare a global variable (globally accessible variable) in javascript. I cannot completely agree with this statement as the access level/scope is determined by the place where the variable is declared.

How to determine the variable scope or access level?

  • If the variable is declared outside a function, it can be used by any function within the same scope. Therefore the variable scope is global (for any function).
  • In the variable is declared inside a function, then it can be accessible only within that method. Therefore the variable scope is known as local (only for that function).

 

Global Scope

Please refer the below example where the “age” has been declared to be a global scope variable.

var age = 20;

function printAge() {
    console.log("age is " + age);
}

function printAgeCategory() {
    if (age >= 18) {
        console.log("adult");
    }
    else {
        console.log("child");
    }
}

printAge(); // will print "age is 20"
printAgeCategory(); // will print "adult"

 

Local Scope

Please refer the below example where the “age” has been declared to be a global scope variable (only for printAge function).

function printAge() {
    var age = 20;
    console.log("age is " + age);
}

function printAgeCategory() {
    if (age >= 18) {
        console.log("adult");
    }
    else {
        console.log("child");
    }
}

printAge(); // will print "age is 20"
printAgeCategory(); // Uncaught ReferenceError: age is not defined

 

printAgeCategory cannot access the age variable as it is declared within the printAge function. it has the local scope within the printAge function and can be accessed only within that function.

 

What is the reason behind introducing let in ES6?

After going through the above example, i am pretty sure that you have the following feeling and you might be questioning yourself about the reason behind “let” keyword for declaring variables.

You might be thinking of “var keyword can be used to declare variables which can have either global or local access. So, why do we need an additional variable declaration keyword like “let“?  What is the real usage of it ?”

 

Let me explain. 

 

Consider the below example.

for (var index = 0; index < 3; index++) {
    console.log("inside for loop [" + index + "]");
}

console.log("outside for loop [" + index + "]");

 

The result/output of above example can be given as follows.

inside for loop [0]
inside for loop [1]
inside for loop [2]
outside for loop [3]

 

Did you notice a wired behaviour by examining about output?  Can you notice that variable index is accessed from outside of the for loop ?  Isn’t it wired?  It is intended to be developed as local variable inside the for loop block. but unfortunately it is not. The solution is to move forward with block scope variables.

ES6 (ECMAScript 2015) has identified above issue and has introduced block scope variable declaration with “let” keyword.

 

“let” keyword for variable declaration in ES6

 

let keyword helps to declare block-scope variables. These variables are scoped in the braces {} (block) .

So the above program can be re-written with let keyword as follows.

for (let index = 0; index < 3; index++) {
    console.log("inside for loop [" + index + "]");
}

console.log("outside for loop [" + index + "]");

 

The result will be as follows.

inside for loop [0]
inside for loop [1]
inside for loop [2]
Uncaught ReferenceError: index is not defined

 

Since the index variable is declared with let, it has the blocked scope within the for loop. Therefore it cannot be accessed outside of the for loop. Trying to access it outside from the block may throw ReferenceError.

 

const

As the name implies the const keyword is used to define constants. The value for the constant should be assigned when it is declared and it cannot be changed/reassigned later.

Const actually means that once the variable is assigned it cannot be assigned again and an attempt to do so will throw an error.

const defends the variable from being overwritten.

const i = 0;
i = 1; // TypeError: Assignment to constant variable.

 

const, like let, is block scoped.

consider the below code segment which tries to reassign a value for the const variable.

if (true) {
  const i = 0;
}
console.log(i); // ReferenceError: i is not defined

 

const does allow mutability: the value can change if it’s mutable, such as an Object or an Array.

const obj = {
  i: 0
};
obj.i = 1; //here it is legal because we are not going to assign new object to 'obj'
obj.i; // 1  (legal and prints '1')