Import functions from another file in Node.js
Export and load functions with CommonJS or ES modules, choose explicit file types, and understand paths, caching, and circular dependencies.
Use module.exports and require() in CommonJS, or export and import in ES modules. The examples below use explicit extensions so their behavior does not depend on a surrounding project's package settings.
Share functions with CommonJS
Save the functions in math.cjs:
function add(a, b) { return a + b; }
function subtract(a, b) { return a - b; }
module.exports = { add, subtract };
Load them from app.cjs in the same directory:
const math = require('./math.cjs');
console.log(math.add(5, 3)); // 8
console.log(math.subtract(8, 3)); // 5
const { add } = require('./math.cjs');
console.log(add(2, 3)); // 5
For a module that exposes a single function, assign the function directly to module.exports; the caller then receives that function. Objects and constants can be exported in the same way.
Share functions with ES modules
Save this as math.mjs:
export function add(a, b) { return a + b; }
export function subtract(a, b) { return a - b; }
Then use it from app.mjs:
import { add, subtract } from './math.mjs';
console.log(add(5, 3));
console.log(subtract(8, 3));
Alternatively, use .js files with "type": "module" in the nearest parent package.json. A .cjs extension explicitly selects CommonJS; .mjs selects ESM.
Resolve paths deliberately
./math.cjs identifies a neighboring file. A bare name such as lodash invokes package resolution; built-in modules such as node:fs are another distinct case. Relative imports are resolved from the importing module, not the terminal's current directory.
CommonJS can infer certain extensions, including .js; it does not infer every extension. Native ESM requires the extension for relative and absolute file imports. Package names follow the package's exports and resolution rules.
Interoperability is supported, but syntax and loader rules still matter. CommonJS can call dynamic import() inside an async function. ESM can import CommonJS, and createRequire() provides an explicit bridge when needed. Recent Node releases also support require() for eligible synchronous ES modules; do not assume that behavior on older runtimes or modules using top-level await.
Caching and cycles
The first successful require() normally executes the module and caches its exports by resolved filename. Later calls resolving to that same file reuse the cached result. Different resolved copies, explicit cache removal, and some filesystem casing situations can change that behavior.
Circular CommonJS dependencies may expose partially initialized exports. Move shared functionality into a third module when possible. If loading fails, check the exact path, filename case, extension, package exports, and whether the file was included in the deployment.
References
Contact us
Join the community
to join the community
Try Guance
Start online and pay only for what you use.
Get startedChoose a Guance plan