DEV Community

Cover image for Module Management in Node
Doaa Mahely
Doaa Mahely

Posted on

Module Management in Node

I regularly work with a Node project at work where functionality in a certain file is imported in other files using the require keyword, and exported to be used in other files using the module.exports keyword. More recently, I started working on a side project using create-react-app, where files are imported using the import keyword and exported using the export keyword. Although both projects use the same programming language, I never questioned this difference until now.

What is a module?

To make code more DRY, we're often told to extract code that is used in many places to a separate function that is imported in all the files that need it. For example, a date parsing function that is used application-wide. In JavaScript speak, this function would be called a module. A module, however, isn't always necessarily a function, but can also be a number of related functions, a class or even a single variable.

Node's solution

Node's module management system is called CommonJS, and it uses the aforementioned require keyword. For example, here's a very simple function that checks token validity on a fetch request. The last line allows us to export this module to be used in other places:

// utils/isTokenValid.js
const isTokenValid = (err) => {
    if (err.status === 401) return false;
    return true;
};

module.exports = isTokenValid;
Enter fullscreen mode Exit fullscreen mode

And this is how we'd use it in another file:

// index.js
const isTokenValid = require('../utils/isTokenValid');

const response = await fetch('/');
if (!isTokenValid(response)) 
    throw new Error('Authentication error');
Enter fullscreen mode Exit fullscreen mode

And then came ES6

With this revision of the language, a native module management system was introduced. Now, we can rewrite the above example in this way:

// utils/isTokenValid.js
const isTokenValid = (err) => {
    if (err.status === 401) return false;
    return true;
};

export default isTokenValid;
Enter fullscreen mode Exit fullscreen mode
// index.js
import isTokenValid from '../utils/isTokenValid';

const response = await fetch('/');
if (!isTokenValid(response)) 
    throw new Error('Authentication error');
Enter fullscreen mode Exit fullscreen mode

This example uses a default export for isTokenValid. Alternatively, it can be rewritten as export { isTokenValid } then imported in index.js as import { isTokenValid } from '../utils/isTokenValid'.

Using import/export in Node

Now does that mean we have to remember where to use each of these two syntaxes if we're building a full stack JavaScript application? Thankfully, Node is already on it and has started to offer support to ES6 import/export syntax. At the moment, the support is experimental and unstable and therefore not recommended to be used in production. Using it is not straightforward either, as you have to change each file from a .js to a .mjs along with changes in your package.json.

The other way to get started using import/export in your Node app is to install Babel which can take care of transpiling all your ES6 code to ES5. Personally, I opted to keep using CommonJS syntax in my backend and ES6 syntax in my frontend, now that I understand the difference between them.

Thanks for reading. Until next time 👋
Cover photo by Danny Lines on Unsplash

Top comments (0)