Published on April 11, 2025
2 min read
476 words

Node.js Import Style Guide

Node.js Import Style Guide

When working with built-in Node.js modules, how you import them matters more than you might think. The syntax you choose can affect clarity, performance, compatibility—and even how easily your codebase scales.

This guide walks through the different import styles and offers a practical rule-of-thumb approach to picking the best one.

For the record, these are not hard rules—but they are sensible defaults that align with modern Node.js practices (especially from v16 onward).

TL;DR

  • Use import { method } from 'node:module'
  • Why? It's explicit, tree-shakable, IDE-friendly, and future-ready.

import in Node.js: The Big Picture

Node.js has come a long way from require(). With ES modules (ESM) support stabilized in modern versions, it's time to level up how we import built-in modules.

But here's the catch, you've got options. Let's break them down.

🔹 Default Import

import fs from 'fs';

Rule of Thumb: Are you importing the entire module for convenience—even if you don't need everything?

  • Brings in the whole module as a default export.
  • Less efficient for bundlers and tree-shaking.
  • Fine for quick scripts, but suboptimal for larger apps.

🔹 Named Import

import { readFile } from 'fs';

Rule of Thumb: Do you only need a specific function or method?

  • Imports only what you need.
  • More readable and efficient.
  • Plays nicely with tree-shaking and autocomplete.

🔹 Node Protocol Import

import fs from 'node:fs';

Rule of Thumb: Want to make it crystal clear you're using a Node built-in?

  • The node: prefix tells both humans and tools it's a built-in module.
  • Reduces ambiguity, especially in monorepos or when mixing npm packages with similar names.

✅ The Sweet Spot: Named + node: Prefix

import { readFile } from 'node:fs/promises';
import { join } from 'node:path';

Rule of Thumb: Do you want clarity, efficiency, and future-proofing all at once?

  • Best of both worlds.
  • Clear, focused, and modern.
  • Supported in Node.js 16+.

📚 Common Module Examples

Here's how to apply these patterns across popular built-in modules:

File System

import { readFileSync, writeFileSync } from 'node:fs';
import { readFile, writeFile } from 'node:fs/promises';

Path

import { dirname, join, resolve } from 'node:path';

URL

import { fileURLToPath } from 'node:url';

Utils

import { promisify } from 'node:util';

✅ Best Practices Checklist

Use this:

import { method } from 'node:module';

Because:

  • node: prefix is explicit and modern
  • Named imports help reduce bundle size
  • Improves readability and IDE support
  • Easier to audit and refactor
  • Plays well with ESM and future tooling

🧠 Final Thoughts

Think of your imports as the opening sentence of your code's story. The clearer and more intentional they are, the easier it is for others (and future-you) to follow along. By using the node: protocol and named imports, you're writing Node.js the way it's meant to be written in 2025.

Small choices add up—so import smart, stay sharp, and keep your codebase clean.

Happy coding 🚀