DEV Community

Cover image for Node.js Import Function from Another File
Mateen Kiani
Mateen Kiani

Posted on • Originally published at milddev.com

Node.js Import Function from Another File

Introduction

Writing code in separate files is a great way to keep a Node.js project organized and maintainable. Breaking your logic into modules lets you reuse components, share utilities, and simplify debugging. Yet, many developers stumble when they try to import or export functions across files, especially as Node.js supports both CommonJS and ES modules.

How do you correctly export a function in one file and import it in another? In this guide, we’ll walk through both module systems—showing you step-by-step how to share functions, avoid common pitfalls, and leverage dynamic imports for on-demand loading.

By mastering these patterns, you’ll write cleaner code, speed up development, and ensure your project structure scales smoothly. Ready to dive in?


Exporting Functions

Before we import a function, we need to export it properly. In Node.js there are two main module systems:

  1. CommonJS (the default before ES modules).
  2. ES Modules (modern JavaScript module syntax).

CommonJS Exports

Create a file named mathUtils.js:

// mathUtils.js
function add(a, b) {
  return a + b
}

function multiply(a, b) {
  return a * b
}

module.exports = {
  add,
  multiply,
}
Enter fullscreen mode Exit fullscreen mode

Here we attach add and multiply to module.exports, making them available to other files.

ES Module Exports

If your project uses ES modules (set "type": "module" in package.json), export functions like this:

// stringUtils.js
export function capitalize(str) {
  return str.charAt(0).toUpperCase() + str.slice(1)
}

export function lowerCase(str) {
  return str.toLowerCase()
}
Enter fullscreen mode Exit fullscreen mode

Each function gets its own export keyword, which you can import elsewhere.

Tip: Align your export style across files to avoid confusion. Mixing CommonJS and ES Modules can lead to unexpected errors.


Importing with require

When using CommonJS, you bring in functions with require.

// app.js
const { add, multiply } = require('./mathUtils')

console.log(add(2, 3))       // 5
console.log(multiply(4, 5))  // 20
Enter fullscreen mode Exit fullscreen mode

Notice:

  • We drop the .js extension when requiring local files.
  • The path ./mathUtils looks in the same folder. You can use ../ to go up a level.

Practical Tips

• Always check file paths: typos in require('./utils') will crash your app.

• Avoid circular dependencies: two files requiring each other can lead to incomplete exports.

Pro Tip: If you need to import JSON data, see how to import JSON file in Node.js for best practices.


Using ES Modules

With ES Modules, you switch to import and export syntax.

Setup

  1. In your package.json, add:
   {
     "type": "module"
   }
Enter fullscreen mode Exit fullscreen mode
  1. Use .js extensions in imports.

Import Example

// app.mjs or app.js (with type: module)
import { capitalize, lowerCase } from './stringUtils.js'

console.log(capitalize('hello'))   // Hello
console.log(lowerCase('WORLD'))    // world
Enter fullscreen mode Exit fullscreen mode

You can also import the default export or rename imports:

// defaultExport.js
export default function greet(name) {
  return `Hello, ${name}!`
}

// app.js
import greet from './defaultExport.js'
import { capitalize as cap } from './stringUtils.js'

console.log(greet('Alice'))  // Hello, Alice!
console.log(cap('bob'))      // Bob
Enter fullscreen mode Exit fullscreen mode

Note: ES Modules are fully supported in modern Node.js versions. Use them if you prefer standard JavaScript syntax.


Dynamic Imports

Sometimes you only need a module under certain conditions. Dynamic importing can help:

// lazyLoad.js
async function loadFeature(flag) {
  if (flag) {
    const { specialFeature } = await import('./specialFeature.js')
    specialFeature()
  } else {
    console.log('Feature not loaded')
  }
}

loadFeature(true)
Enter fullscreen mode Exit fullscreen mode

Benefits:

  • Reduces initial load time.
  • Loads heavy code only when needed.

Keep in mind dynamic imports return a promise, so use await or .then().


Troubleshooting Imports

When things go wrong, here’s how to debug:

  1. Syntax Error: Check you’re not mixing require with import without enabling ES modules.
  2. Module Not Found: Verify file names, paths, and extensions. Remember require('./utils') vs import './utils.js'.
  3. Circular Dependencies: Refactor common logic into a third file to break the cycle.
  4. Undefined Exports: Double-check you exported the function (export function foo) or added it to module.exports.

If you still get errors, add console logs at the top of your modules to see if they run at all.

Tip: Use Node’s --trace-warnings flag to get more details on import issues.


Conclusion

Importing functions from other files is a core skill for any Node.js developer. Whether you stick with CommonJS or embrace ES modules, the patterns are simple:

  • Export your functions clearly.
  • Import them with the matching syntax.
  • Handle dynamic cases with import().
  • Debug common errors by checking paths and avoiding circular dependencies.

By modularizing your code, you’ll boost readability, enable better testing, and keep your project maintainable. Start refactoring large files into focused modules today—and enjoy cleaner, more organized code tomorrow!

Top comments (0)