Book Image

Modern JavaScript Web Development Cookbook

By : Federico Kereki
Book Image

Modern JavaScript Web Development Cookbook

By: Federico Kereki

Overview of this book

JavaScript has evolved into a language that you can use on any platform. Modern JavaScript Web Development Cookbook is a perfect blend of solutions for traditional JavaScript development and modern areas that developers have lately been exploring with JavaScript. This comprehensive guide teaches you how to work with JavaScript on servers, browsers, mobile phones and desktops. You will start by exploring the new features of ES8. You will then move on to learning the use of ES8 on servers (with Node.js), with the objective of producing services and microservices and dealing with authentication and CORS. Once you get accustomed to ES8, you will learn to apply it to browsers using frameworks, such as React and Redux, which interact through Ajax with services. You will then understand the use of a modern framework to develop the UI. In addition to this, development for mobile devices with React Native will walk you through the benefits of creating native apps, both for Android and iOS. Finally, you’ll be able to apply your new-found knowledge of server-side and client-side tools to develop applications with Electron.
Table of Contents (15 chapters)

Adding code quality checks with ESLint

JS is a very potent language, but there's also great potential for misuse. For example, most people would agree that if a==b is true, and b==c is also true, then a==c should be true too, but because of the data type conversion rules that JS applies for the == operator, you have the following:

""==0   // true
0=="0" // true
""=="0" // false!?

Another example follows; what does this very simple function return?

function mystery() {
return
{
something: true
}
}

If you answered an object, you would have been bitten by a missing semicolon. This code is actually interpreted by JS as follows:

function mystery() {
return ;
{
something: true;
}
}

Note the semicolon after return. This function returns undefined, and something is interpreted as a label for an expression that happens to be true; bad! These kinds of situations are common enough, and even if you know what you are doing, getting at least a warning about possible problems with your code could help root out a bug, and that's the kind of warning that ESLint produces.

The gotcha shown previously is only one of many that JS has for unaware developers. Google for JavaScript gotchas and you'll get several lists of possible errors.

How to do it...

Linters are a class of programming tools that analyze your source code, and raise warnings and errors about poor-quality uses or constructs that could even imply bugs. We are going to use ESLint, created by Nicholas Zakas in 2013; the tool's current version is 5.10.0, as of December, 2018.

The first lint program was written in 1978 by Stephen Johnson, at Bell Labs, where he also worked on Unix, yet another compiler compiler (yacc), and the portable C compiler, which made it easier to output code for different computer architectures.

ESLint is based upon pluggable rules, which may be enabled or disabled at will, or configured according to your specific preferences. (You could even develop your own rules, but that's beyond the scope of this book.) There are also bundles of rules that let you avoid having to individually configure dozens of distinct rules.

Installing ESLint is quite simple, and just requires doing the following:

 npm install eslint eslint-config-recommended --save-dev

Then, you will have to add ESLint options to the package.json configuration file; let's get into this. First, we'll add a script to apply ESLint to our complete source directory (which has only a single file at this time!) with npm run eslint:

"scripts": {
"build": "babel src -d out",
"eslint": "eslint src",
"test": "echo \"Error: no test specified\" && exit 1"
}

We must also specify some configuration for ESLint itself. We'll add a completely new section for this:

"eslintConfig": {
"parserOptions": {
"ecmaVersion": 2017,
"sourceType": "module"
},
"env": {
"browser": true,
"node": true
},
"extends": "eslint:recommended",
"rules": {}
}

Let's go item by item:

  • parserOptions lets you specify what JS version you want to process (I'm going with 2017, for ES8), and whether you are going to use modules (I'm indicating this, in advance of what we'll see in the Organizing code in modules section of Chapter 2, Using Modern JavaScript Features).
  • env lets you specify the environment(s) you are going to work with, and that really means that some global variables will be assumed to exist. In this case, I'm saying I will be working both with code for browsers and for Node, but there are plenty more possible environments; checkout the Specifying Environments section at https://eslint.org/docs/user-guide/configuring. Later on, we will be adding some more environments, for example, for unit testing.
  • extends lets you select a predefined set of rules, which you will later be able to modify to suit your tastes. I'm going with the recommended set; you can read more about it at https://github.com/kunalgolani/eslint-config. The available sets of rules change only whenever the ESlint major version changes, so they are reasonably stable. Furthermore, the recommended set represents a usually agreed upon list of rules, so before you start tinkering with specific changes, give it a try as is. The complete set of rules is available at https://eslint.org/docs/rules/, and the recommended rules can be found at https://github.com/eslint/eslint/blob/master/conf/eslint-recommended.js.
  • rules lets you change some of the rules to better suit your style. We'll see good reasons for this soon.
If (and only if) you are planning to use some Babel feature that is not yet supported by ESLint, you should install and use the babel-eslint package from https://www.npmjs.com/package/babel-eslint. This will also require adding a line to the .eslintrc.json file to change the parser that ESLint uses. However, keep in mind that it's highly unlikely you will require this change!

How it works...

If we use npm run eslint as is, we will get the following result:

> npm run eslint
> [email protected] eslint /home/fkereki/sample
> eslint src

/home/fkereki/sample/src/eight_queens.js
32:1 error Unexpected console statement no-console
> X 1 problem (1 error, 0 warnings)

The standard rules do not allow using console.log(...), since you don't probably want to include them in your shipped application; this is the no-console rule at https://eslint.org/docs/rules/no-console. We can enable or disable rules on a global or local basis. If we approve of this console.log(...), we must then disable the no-console rule locally. We'll do this by adding a comment to the source code, just before the problem line:

// eslint-disable-next-line no-console
console.log(`Solutions found: ${solutions}`);

If you had used // eslint-disable no-console, you would have disabled the no-console rule for the whole source file; // eslint-disable with no further specification would have disabled all rules for the file. After this, if you use npm run eslint, you'll get no errors.

Now, let's set a global rule. Some people don't like the solutions++ line because not everybody feels comfortable with the ++ operator; there's a no-plusplus rule for this, at https://eslint.org/docs/rules/no-plusplus, but by default it's not enabled in the recommended set, so we will enable it globally by adding to the rules section in package.json:

"rules": {
"no-plusplus": "error"
}

After this, if you run ESLint, you'll get a new error, and the developer that supposedly did it should fix the code:

/home/fkereki/sample/src/eight_queens.js 
13:9 error Unary operator '++' used no-plusplus

The possible configurations for a rule are "off" (if you want to disable it), "warn" (if you want to get a warning, but accept it), and "error" (rejecting the file). Some rules accept extra configurations, but those are specific; you'll have to read the rule documentation in order to learn about the possible changes. See https://eslint.org/docs/rules/no-empty for a specific example with the no-empty rule, which disallows empty blocks of code but has an extra option to allow them in catch statements.

Deciding what rules to enable or disable is something that usually happens at the beginning of a project, and it can be expected that some new rule changes will happen over time. In any case, no matter what you pick, ideally you should work only with "off" and "error"; if developers get used to warnings, they finally end up not paying attention to them, and that can be bad! Get used to the whole list of rules at https://eslint.org/docs/rules/.

Finally, all projects will be using an out/ directory for the output file, which you would then distribute. If you care to look at some files within it, you don't need ESLint protesting about possible errors in generated code. To avoid this, you can add a small section to the package.json file:

 "eslintIgnore": ["**/out/*.js"],

There's more...

Of course, all these checks are very good, but if you had to stop working, save everything, and run a separate tool each time you wanted to check for problems in your code, it would soon become unbearable. However, with VSC you can add a plugin to interact with ESLint in real time. Go to the extensions view and search for ESLint; you should find and install an extension, currently at version 1.7.2 (March 2018), written by Dirk Baeumer.

Once you install this extension, errors will be shown on screen with a wavy red underline, and if you mouse over them, you'll get an explanation about the failed rule. Take a look at the for an example:

The ESLint plugin in action, showing problems with the code in real time

There are very few configuration items for ESLint; the only one I use is "eslint.alwaysShowStatus": true, so the status bar will show whether ESLint is enabled or not.

An interesting package that you could consider is the web DeepScan tool at https://deepscan.io/home/. DeepScan is advertised as beyond Lint, insofar as it can also detect runtime problems having to do with implicit type conversions, null checks, unreachable code, and more. For the time being, DeepScan is considered to be in beta stage and there are no paid plans yet. You can use it free for open source projects; for example, you can use it automatically with a GitHub project.