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:
- CommonJS (the default before ES modules).
- 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,
}
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()
}
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
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
- In your
package.json
, add:{ "type": "module" }
- 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
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
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)
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:
- Syntax Error: Check you’re not mixing
require
withimport
without enabling ES modules. - Module Not Found: Verify file names, paths, and extensions. Remember
require('./utils')
vsimport './utils.js'
. - Circular Dependencies: Refactor common logic into a third file to break the cycle.
- Undefined Exports: Double-check you exported the function (
export function foo
) or added it tomodule.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!
Subscribe to my newsletter
Read articles from Mateen Kiani directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
