Nodejs - Quick Tips #5

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 ran.

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
1
2
3
4
5
6
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.

package.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
{
"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 is our case, will be use to transpile ES2015 and for linting.

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

webpack.config.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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 transform to a single output file.

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

.babelrc
1
2
3
4
5
6
7
8
9
10
{
"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:

eslintrc.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
{
"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
}
}