To make code easy to read and maintain, we should follow some best practices. In this article, we’ll look at some best practices we should follow to make everyone’s lives easier.
No Cyclic Imports
We shouldn’t have cyclic imports. They won’t work with ES modules.
For instance, we shouldn’t have:
dep-c.js
import './dep-a.js'
dep-b.js
import './dep-c.js'
dep-a.js
import { b } from './dep-b.js'
We import a
in c
, c
in b
and b
in a
.
This means that we have a cyclic dependency between the 3 modules.
No Default Export
We shouldn’t have default exports without a name.
For instance, we shouldn’t write:
export default 'bar';
It’s good to have a name to identify it.
Instead, we write:
export default name = 'bar';
No Duplicate Import
We shouldn’t have duplicate imports.
For instance, we shouldn’t write:
import Foo from './mod'
import { Bar } from './mod'
We have 2 lines importing the same module.
Instead, we write:
import Foo, { Bar } from './mod'
No Dynamic Require
We shouldn’t have dynamic require calls. This is because we shouldn’t let people pass anything as the value to improve security.
For instance, instead of writing:
require(name);
or:
require(`../${name}`);
We write:
require('../name');
No Extraneous Packages
If we aren’t using a package, then we shouldn’t import it.
So if we have:
import _ from 'lodash';
Then we should use it.
No Mutable Exports
Mutable exports will change the value of the export when it’s exported to the latest value. So we shouldn’t let them be mutable.
For instance, if we have:
export let count = 2;
or:
export var count = 3;
Then we can change the value of count
.
No Node Modules on Client Side
If we’re building a client-side JavaScript project, then we shouldn’t import Node modules since they can’t be used.
For instance, we shouldn’t have:
import fs from 'fs';
import path from 'path';
or:
const fs = require('fs');
const path = require('path');
in a client-side project.
Don’t Let a Module Importing Itself
A module shouldn’t import itself. It works but it’s pointless.
So we shouldn’t write
import foo from './foo';
or:
const foo = require('./foo');
Instead, we write:
import bar from './bar';
or:
const bar = require('./bar');
No Unassigned Imports
If we have an import that can be used unassigned, then that means the module has side effects or it’s not being used. They’re both bad, so we should consider exporting members and not committing side effects in modules.
So instead of writing:
import 'foo'
or:
require('foo')
We write:
import _ from 'foo'
or:
import {foo as bar} from 'foo'
No Useless Path Segments
We shouldn’t have useless path segments in our imports.
For instance, We shouldn’t have:
import "./../pages/about.js"
since .
and ..
cancel each other out.
So we write:
import "./pages/about.js"
We should also remove extra slashes.
So instead of:
import "./pages/";
We write:
import "./pages";
Use Default Export for Single Modules
We should use default export for single modules if there’s only one. Then we can name that export whatever we want.
For instance, instead of writing:
export const foo = 'foo';
We write:
const foo = 'foo';
export default foo;
Consistent Indentation
2 spaces are good for indentation. It minimizes typing and space but still keeps everything clear. So we can use that for indentation.
Initialization in Variable Declarations
We can make sure that we declare variables and assign a value to them so we can use them.
So we can write:
var foo = 1;
or:
let foo = 1;
instead of:
var foo;
or:
let foo;
const
always have to have a value assigned to them.
Multiline Comments Style
Multiline comments are easy to write and read. We can use them to write longer explanations.
For instance, we can write:
/*
* this line
* calls foo() _*/_
We write them with an asterisk on the left separated by a space from the rest of the text.
Conclusion
We should write imports properly. Also, we should consider default exports for exporting one member of a module only. Cyclic and self imports don’t work well, so we should avoid them. Multiline comments are useful for writing longer explanations.