Static Analysis


JavaScript, compared to other languages, has a more flexible syntax. Such characteristic sometimes causes unintended problems. For example, the flexible syntax creates accidental errors that are not, from syntactical perspective, bugs, and also leads to codes of which purpose is not transparent. Because JavaScript does not have a compile stage, such errors are undetectable before actually running the program. While adhering to the Coding Convention to increase readability and prevents anti-patterns is a temporary solution, it is still difficult for developers to ensure that they are following the Coding Convention by themselves. In order to compensate for the JavaScript’s shortcoming, Static Analysis is used to automatically validate the Coding Convention and sniff out possible errors.

Table of Contents

Static Analysis Tools

Roles of Static Analysis Tools

  • Detects possible errors including syntax errors and typos by statically analyzing the code.
  • Automates Coding Convention verification.
  • Provides prompt feedbacks, integrated with development environments.

Iconic Static Analysis Tools

  • ESLint: It is the most recently built tool, and is very flexible and extensible.
  • Prettier: It is a tool that only emphasizes code style and automatic formatting
  • JSLint: Built by Douglas Crockford, and cannot be configured or extended.
  • JSHint: JSHint is built by adding configurability and extensibility to JSLint.
  • JSCS: As a coding convention checker, it has been integrated into ESLint.

ESLint

Built by Nicholas C. Zakas, ESLint is currently the most widely used static analysis tool. The tool’s credibility has been verified by the fact that giants like Facebook, PayPal, and Airbnb feel comfortable enough to use it in their development environments. ESLint uses the Espree parser to built Abstract Syntax Tree (AST) to directly evaluate the code, and it not only supports diverse rules, but also supports various environments and formatters. Because it also provides features to add custom rules or formatters, it can be customized flexibly in accordance with the project’s characteristics. To learn more about rules and demos, follow the respective links.

Install

ESlint can be installed using npm.

npm install --save-dev eslint

Usage

It is possible to create a config file for each project, and use it to enforce different rules to carry out static analysis. Also, editors that support ESLint give feedback according to the custom ESLint rule in the project folder, which allows faster debugging and prompt error validation. ESLint can even be integrated into bundlers like Webpack and can be configured to suit the development mode or production mode. Especially in production mode, if more errors are raised than the alert threshold, it can even stop the build process.

Options

Options in ESLint can be categorized into six modes: Possible Errors, Best Practices, Strict Mode, Variables, Stylistic Issues, and ES6, and detailed explanation on each option can be found in the official documentation. Options can be applied on the .eslintrc.js config file, and will be explained briefly in the Applying it to Projects section. More in depth explanation can be found in the official documentation.

Using the CLI

In order to use ESLint, a config file containing the basic rules (.eslintrc.js) is required. Use the --init option provided by the CLI to create the config file as shown below.

npx eslint --init

Now, ESLint can be executed using the CLI.

npx eslint app.js

When the CLI command finishes executing, ESLint statically analyzes the app.js file, and detects and prints the lines that contain errors or do not conform to the Coding Convention as in the following image.

filterimage

--fix is one of the commonly used options in the CLI. --fix automatically corrects the pieces of code marked as error and saves the code. In order to only display the corrections without saving them, use --fix-dry-run.

More options and their detailed explanations can be found on the official website.

Applying it to Projects

1. Creating .eslintrc.js file

Note The previously explained method of using the --init option from the CLI also works.

Below is an example of a config file with some basic rules.

module.exports = {
  parserOptions: {
    sourceType: 'module'
  },
  env: {
    browser: true,
    es6: true,
    jasmine: true
  },
  extends: ['tui'],
  // add your custom rules here
  rules: {
    'indent': [2, 2, {SwitchCase: 1, ignoreComments: false, ImportDeclaration: 1}],
    'semi': 2
  }
};
  • parserOptions ESLint can be configured to support different JavaScript language options. The parseOptions can take values like ecmaVersion, sourceType, ecmaFeatures, and etc., and more examples can be found on the user guide.
  • env The env option allows developers to define the environment on which the code is being executed. The example above has browser, es6, and jasmine as values.
  • extends The extends option allows developers to use predefined custom rule sets. In the example above, the file is configured to use the eslint-config-tui, set of rules used in FE Development Lab. (This property will be explained in greater detail in the 2. Using Predefined ESLint Rules)
  • rules Using the rules, rules in the collection defined in the extends property can be added and redefined.

In the example file, a rule making the semicolon mandatory semi has been defined and enforced. Also, the indent is set to only accept 2 spaces for indentation, and more detailed options like switchCase (applicable in switch statements), ignoreComments (applicable for comments), and ImportDeclaration (applicable in import declarations) have been set to true.

2. Using Predefined ESLint Rules

ESLint contains incredibly large collection of rules, so it could be difficult to go through each one to pick out the rules suitable for each project. Luckily, tech-giants like Google, Microsoft, and Airbnb have released their corresponding Coding Conventions and respective ESLint rules, and such collections can be adopted reliably.

The Coding Convention produced by the FE Development Lab has been reviewed one rule at a time, and can prove to be a useful guide. It contains a set of well-written predefined rules, so it is recommended that readers take advantage of it. The FE Development Lab’s Coding Convention and eslint-config-tui file can be found in the link below.

To use the eslint-config files, simply download the desired config file using npm, and include it in the .eslintrc.js file’s extends property. When writing the value for the extends attribute, the eslint-config- prefix can be omitted.

// Install the config file
npm install --save-dev eslint-config-tui
// Edit the .eslintrc.js
module.exports = {
  extends: ['eslint-config-tui']
}
;

It is important to keep in mind that the predefined should be used cooperatively with default rules, not independently. The default rules have been explained in greater detail in earlier sections. In order to use ECMAScript’s module system in the project, it is necessary to set parserOptions.sourceType to module as shown below.

// Edit the .eslintrc.js 
module.exports = {
  parserOptions: {
    "sourceType": "module"
  },
  extends: ['eslint-config-tui']
};

To use global variables from the browser and ES6, configure the env attribute as shown below.

// Edit the .eslintrc.js.
module.exports = {
  parserOptions: {
    "sourceType": "module"
  },
  env: {
    browser: true,
    es6: true
  },
  extends: ['eslint-config-tui']
};

3. Tips for Using Multiple Recommended Configurations

It is actually common to inherit multiple recommended configurations for projects. The below is an example of using the TOAST UI Rules and Vue framework’s recommended configurations together at FE Development Lab.

module.exports = {
  ..
  extends: ['tui', 'plugin:vue/recommended'],
  ..
};

As such, when using multiple configurations, the set declared last holds highest priority.

4. Editing the npm Script

package.json

{
  "scripts": {
    "lint": "eslint src"
  }
}

5. Running the CLI Command

npm run lint
npm run lint -- --fix // (Fix automatically)

Prettier

Prettier, unlike other static analysis tools that analyze every code for syntax, focuses strictly on the code’s style. The biggest advantage Prettier offers is that it automatically formats the code, eliminating the need for each developer to pay attention to making the codes look “pretty.” It allows developers to forget about styling the code, and only focus on the program’s logic. However, since Prettier does only focus on formatting, it is recommended to use tools like ESLint to guarantee the quality of the code. Prettier supports many different languages (JavaScript, JSX, Flow, TypeScript, CSS, Less, SCSS, JSON, GraphQL) and can be integrated on to most of the editors.

In the image below, the left side is unformatted code, and the codes on the right have been formatted using Prettier.

demo_image

To test Prettier, click here.

Install

npm

npm install --save-dev --save-exact prettier
# or globally
npm install --global prettier

yarn

yarn add prettier --dev --exact
# or globally
yarn global add prettier

Usage

Using Prettier on Editors

Many modern editors like Atom, Emacs, Vim, Visual Studio, Sublime, and JetBrains WebStorm supports integrated application of Prettier. Using the integrated plugin, when the source code is being saved, it automatically goes through the Prettier and is saved in formatted version. Refer to the official documentation for more thorough instructions about using Prettier on editors. The following is an example of Prettier formatting the code before it is saved in JetBrains WebStorm editor.

preview

Applying Prettier to Projects

Prettier is a tool to eliminate any debate over the coding convention, so it does not have complicated options about style. However, Prettier does provide options regarding specific cases like tabs vs. spaces or single quotes vs. double quotes. If ESLint is already installed, Prettier can be adopted just by installing the eslint-plugin-prettier. This section will discuss how to add config files to Prettier and how it can be used with ESLint.

1. Adding the Config File First create a .prettierrc file in the project folder, and edit the file according to the official documentation. An explanation on options have been included in the end of the document. The starter template for .prettierrc file should look like the following code.

Prettier, compared to ESLint, does not have many options. This is because it is built to settle any disagreements on style, and the original creators of Prettier thought that enabling never ending list of options would defeat the purpose.

{
  "trailingComma": "none",
  "printWidth": 120,
  "singleQuote": true,
  "bracketSpacing": false,
  "tabWidth": 2,
  "jsxBracketSameLine": false
}

2. Using Prettier as a Plugin in ESLint

Because Prettier and ESLint can have different opinions on the same piece of code, it is recommended to use them together. The two can be integrated simply by installing eslint-plugin-prettier and adding to the eslintrc.js file’s list of plugins.

1) Include Prettier in ESLint’s list of rules, by using eslint-plugin-prettier.

npm install --save-dev eslint-plugin-prettier

2) Add Prettier plugin to eslintrc.js.

module.exports = {
  ...
  "plugins": ["prettier"],
  "rules": {
    "prettier/prettier": "error"
  }
};

3. Turn off the ESLint’s formatting rule.

It can be confusing for the program if ESLint and Prettier send redundant reports to it, so it is recommended to just turn off the ESLint’s formatting options. If the Prettier is integrated using eslint-config-prettier, it automatically deactivates any redundant rules.

The following example demonstrates how ESLint and Prettier can produce redundant reports regarding the empty space after the function name. As shown below, both ESLint’s space-before-function-paran error and Prettier’s DELETE ‘.’ errors are printed together.

2018-09-14 4 06 25

By following the steps below, the redundant reporting issue can be resolved.

1) Install eslint-config-prettier.

npm install --save-dev eslint-config-prettier

2) Add Prettier setting to .eslintrc.js.

module.exports = {
  ...
  "extends": ["prettier"]
};

ESLint provides plugins so that users can customize and add features of their own. Prettier also provides eslint-plugin-prettier plugin just for ESLint, and allows users to run Prettier rules with ESLint. eslint-config-prettier enables the existing rules in ESLint to cancel out redundant rules so that the program can be ran more efficiently.

4. Using the Recommended Rules to Eliminate the Unnecessary config

By using the recommended rules like the following, users do not have to specify the prettier in .eslintrc.js’s plugin property. However, even in this case, it is required to install both eslint-plugin-prettier and eslint-config-prettier. plugin-prettier/recommended automatically adds the prettier value to plugin property, and deactivates the redundant rules.

module.exports = {
  ..
  "extends": ["plugin:prettier/recommended"]
  ..
};

Options

  1. printWidth - Specifies the line length of the printer wrap
  2. tabWidth - Specifies the number of empty spaces
  3. useTabs - Uses tabs instead of spaces to indent
  4. semi - Enforces semicolons at end of statements
  5. singleQuote - Uses single quotes instead of double quotes
  6. trailingComma - Prints trailing commas for multiline codes
  7. bracketSpacing - Enforces spacing between the object literal parenthesis
  8. jsxBracketSameLine - Ensures that the closing bracket is not left alone its own line when using jsx.
  9. arrowParens - Enforces parenthesis for arrow function parameters
  10. parser - Specifies the parser
  11. filepath - Specifies the filepath for the parser
  12. requirePragma - Enables/disables pragma headers
  13. insertPragma - Enables/disables automatic pragma header insertions
  14. proseWrap - Specifies wrap type

Each option is explained in greater detail on the official documentation.

Using the CLI

Although Prettier is often used integrated with editors, it can also be used in CLI environment. Shown below is an example of using the CLI to run Prettier. (The example is using the --no-config to check the javascriptCode.js with default settings.)

prettier --no-config javascriptCode.js

To add other options, refer to the official documentation and find the desired input to use with the CLI. The example below is using --single-quote and --no-semi to make sure that string is declared with single quotes and semicolons will be placed at the end of each statement. Finally, it uses the --write option to save the changes made.

prettier --single-quote --no-semi --write javascriptCode.js"

To learn more about using the CLI to access Prettier’s functionalities, refer to the official documentation.

Afterword

This document has explored the Static Analysis. Static analysis enables developers to analyze the code before execution to maintain the consistency inside of the code and to prevent bugs. This guide is focused on the importance of static analysis and the tools related to it, especially ESLint and Prettier. The author hopes that this document helps the readers adopt the static analysis methods efficiently.

This document is an official Web Front-End development guide written and maintained by NHN Cloud FE Development Lab. Any errors, questions, and points of improvement pertaining to this document should be addressed to the official support channel (dl_javascript@nhn.com).


Last Modified
2019. 04. 15
FE Development LabBack to list