Nodejs - Quick Tips #2

04/17/2016, Sun
Categories: #JavaScript
Tags: #NodeJs

Process Exit and Time Elapse

When performing a long-running operation in the terminal, such as file generation, a user would like to know how long the task has run.

A simple way to determine how much time has elapsed in general will be to listen to 'exit' event on the process object. This can be combined with the 'hrtime' method on the process object to provide a detailed time interval.

// Using Built-In Nodejs Functions for Timing

let time = process.hrtime();

process.on("exit", () => {
  let timeDiff = process.hrtime(time);
  console.log(
    "Time elapsed for file(s) and folder(s) generation: %d nanoseconds",
    timeDiff[0] * 1e9 + timeDiff[1]
  );
});

Babel Webpack Eslint Boilerplate

The JavaScript community has embraced ES2015 as the go-to JavaScript version to do modern web development. There are many Gulp and Babel boilerplates out there, but I found out that it is not as reliable as the Webpack and Babel combination because the Gulp watch tasks did not always pick up file changes for me.

Here is a simple config for creating a starter ES2015 JavaScript project.

{
  "name": "my-great-module",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "node_modules/webpack/bin/webpack.js --watch"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "babel": "^6.5.2",
    "babel-core": "^6.7.2",
    "babel-eslint": "^6.0.2",
    "babel-loader": "^6.2.4",
    "babel-plugin-syntax-async-functions": "^6.5.0",
    "babel-plugin-transform-runtime": "^6.6.0",
    "babel-preset-es2015": "^6.6.0",
    "babel-preset-stage-3": "^6.5.0",
    "eslint": "^2.8.0",
    "eslint-config-standard": "^5.1.0",
    "eslint-loader": "^1.3.0",
    "eslint-plugin-babel": "^3.2.0",
    "eslint-plugin-promise": "^1.1.0",
    "eslint-plugin-standard": "^1.3.2",
    "webpack": "^1.12.14"
  }
}

Async functions are actually a ES2016 feature, but they are a really useful functionality, so useful that I included it into the boilerplate.

Webpack is a module bundler and loader, but it can also perform file transformations for us. Webpack in our case, will be used to transpile ES2015 and for linting.

Webpack is configured with a webpack.config.js file:

// webpack.config.js

var path = require("path");

module.exports = {
  entry: "./the-main-input-file.js",
  output: {
    path: path.join(__dirname, "/dist/"),
    filename: "my-output-file.js",
  },
  module: {
    preLoaders: [
      { test: /\.js$/, loader: "eslint-loader", exclude: /node_modules/ },
    ],
    loaders: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: "babel-loader",
      },
    ],
  },
  resolve: {
    extensions: ["", ".config.js", ".js"],
  },
  eslint: {
    configFile: "./.eslintrc.json",
  },
  babel: {
    presets: ["es2015", "stage-3"],
  },
};

By default, Webpack intends to have an entry point file which serves as a manifest file for all your JavaScript files to be transformed to a single output file.

Now a .babelrc is required to configure how Babel is to transpile ES2015 JavaScript:

{
  "presets": ["stage-3", "es2015"],
  "plugins": ["transform-runtime", "syntax-async-functions"]
}

A stage-3 preset is needed for the async function feature in ES2016.

Lastly, for the eslintrc.json file, this will provide the rules for linting JavaScript:

{
  "parser": "babel-eslint",
  "parserOptions": {
    "ecmaVersion": 7,
    "sourceType": "module"
  },
  "plugins": ["babel"],
  "root": true,
  "ecmaFeatures": {
    "arrowFunctions": true,
    "binaryLiterals": true,
    "blockBindings": true,
    "classes": true,
    "defaultParams": true,
    "destructuring": true,
    "forOf": true,
    "generators": true,
    "modules": true,
    "objectLiteralComputedProperties": true,
    "objectLiteralDuplicateProperties": true,
    "objectLiteralShorthandMethods": true,
    "objectLiteralShorthandProperties": true,
    "octalLiterals": true,
    "regexUFlag": true,
    "regexYFlag": true,
    "spread": true,
    "superInFunctions": true,
    "templateStrings": true,
    "unicodeCodePointEscapes": true,
    "globalReturn": true
  },
  "rules": {
    "strict": 0,
    "no-var": 2,
    "comma-dangle": [2, "never"],
    "no-cond-assign": [2, "always"],
    "no-console": 0,
    "no-debugger": 1,
    "no-alert": 0,
    "no-constant-condition": 1,
    "no-dupe-keys": 2,
    "no-duplicate-case": 2,
    "no-empty": 0,
    "no-ex-assign": 2,
    "no-extra-boolean-cast": 1,
    "no-extra-semi": 2,
    "no-func-assign": 2,
    "no-inner-declarations": 2,
    "no-invalid-regexp": 2,
    "no-irregular-whitespace": 2,
    "no-obj-calls": 2,
    "quote-props": 0,
    "no-sparse-arrays": 2,
    "no-unreachable": 2,
    "use-isnan": 2,
    "block-scoped-var": 2,
    "quotes": [1, "single"],
    "no-shadow": 0,
    "no-shadow-restricted-names": 2,
    "no-unused-vars": [
      0,
      {
        "vars": "local",
        "args": "after-used"
      }
    ],
    "no-use-before-define": 2,
    "consistent-return": 2,
    "complexity": [2, 7],
    "curly": [2, "multi-line"],
    "default-case": 2,
    "dot-notation": [
      2,
      {
        "allowKeywords": true
      }
    ],
    "eqeqeq": 2,
    "guard-for-in": 0,
    "no-caller": 2,
    "no-else-return": 1,
    "no-eq-null": 2,
    "no-eval": 2,
    "no-extend-native": 2,
    "no-extra-bind": 2,
    "no-fallthrough": 2,
    "no-floating-decimal": 2,
    "no-implied-eval": 2,
    "no-lone-blocks": 2,
    "no-loop-func": 1,
    "no-multi-str": 2,
    "no-native-reassign": 2,
    "no-new": 2,
    "no-new-func": 2,
    "no-new-wrappers": 2,
    "no-octal": 2,
    "no-octal-escape": 2,
    "no-param-reassign": 0,
    "no-proto": 2,
    "no-redeclare": 2,
    "no-return-assign": 2,
    "no-script-url": 2,
    "no-self-compare": 2,
    "no-sequences": 2,
    "no-throw-literal": 2,
    "no-with": 2,
    "radix": 2,
    "vars-on-top": 0,
    "wrap-iife": [2, "any"],
    "yoda": 2,
    "indent": 0,
    "brace-style": [
      2,
      "1tbs",
      {
        "allowSingleLine": true
      }
    ],
    "quotes": [0, "single", "avoid-escape"],
    "camelcase": [
      2,
      {
        "properties": "never"
      }
    ],
    "comma-spacing": [
      2,
      {
        "before": false,
        "after": true
      }
    ],
    "comma-style": [2, "last"],
    "eol-last": 0,
    "key-spacing": [
      2,
      {
        "beforeColon": false,
        "afterColon": true
      }
    ],
    "new-cap": [
      2,
      {
        "newIsCap": true
      }
    ],
    "no-multiple-empty-lines": [
      0,
      {
        "max": 2
      }
    ],
    "no-nested-ternary": 2,
    "no-new-object": 2,
    "no-spaced-func": 2,
    "no-trailing-spaces": 2,
    "no-extra-parens": 0,
    "no-underscore-dangle": 0,
    "one-var": [0, "never"],
    "padded-blocks": 0,
    "semi": [2, "always"],
    "semi-spacing": [
      2,
      {
        "before": false,
        "after": true
      }
    ],
    "keyword-spacing": 2,
    "space-before-blocks": 2,
    "space-before-function-paren": [2, "never"],
    "space-infix-ops": 2,
    "keyword-spacing": 2,
    "spaced-comment": 0
  }
}