Module ES (import) și CommonJS (require) în Node.js

Module și package.json Node.js 12.17 (module ES fără opțiune), require(esm) stabil din 25.4

Cele două sisteme de module din Node.js: import/export (ES) și require/module.exports (CommonJS), și cum le combini.

Sintaxă
// modul ES (.mjs sau "type": "module")
import fs from "node:fs";
export function f() {}

// CommonJS (.cjs sau "type": "commonjs")
const fs = require("node:fs");
module.exports = { f };

Ce face Module ES (import) și CommonJS (require)

Node.js are două feluri de module. CommonJS este sistemul vechi: încarci cu require() și exporți prin module.exports. Modulele ES sunt standardul JavaScript: import și export, la fel ca în browser. Proiectele noi folosesc module ES.

Node.js decide tipul fișierului după extensie: .mjs = modul ES, .cjs = CommonJS. Pentru .js contează câmpul "type" din package.json ("module" sau "commonjs"); fără el, Node.js detectează singur după sintaxă. Modulele de bază se scriu cu prefixul node: (node:fs), ca să nu fie confundate cu pachete din npm.

Diferențe practice: în modulele ES căile relative au nevoie de extensie (./utile.mjs), await merge la nivelul de sus, iar __dirname și require nu există (folosești import.meta.dirname și createRequire). Un modul ES poate importa CommonJS (primește module.exports ca export implicit), iar require() poate încărca un modul ES fără await la nivelul de sus.

Exemple

Exemplul 1: Import dintr-un modul CommonJS

Scriem un modul .cjs și îl importăm dintr-un modul ES. Obiectul module.exports devine exportul implicit; Node.js încearcă să ofere și exporturi cu nume.

import { writeFileSync } from "node:fs";

writeFileSync("preturi.cjs", `
  const TVA = 0.21;
  function cuTva(pret) { return Math.round(pret * (1 + TVA) * 100) / 100; }
  module.exports = { TVA, cuTva };
`);

const preturi = await import("./preturi.cjs");
console.log(preturi.default.cuTva(100));

const { cuTva, TVA } = await import("./preturi.cjs");
console.log(cuTva(49.99), TVA);

Rezultat

121
60.49 0.21

Exemplul 2: require într-un modul ES, cu createRequire

Uneori ai nevoie de require și într-un modul ES (de exemplu pentru un fișier JSON citit sincron). createRequire îl creează.

import { createRequire } from "node:module";
import { writeFileSync } from "node:fs";

writeFileSync("orase.json", JSON.stringify(["Iași", "Cluj", "Timișoara"]));

const require = createRequire(import.meta.url);
const orase = require("./orase.json");
console.log(orase.length, orase[0]);
console.log(typeof globalThis.require);

Rezultat

3 Iași
undefined

Exemplul 3: require încarcă un modul ES

Un fișier CommonJS poate folosi require() pentru un modul ES (fără await la nivelul de sus). Primește obiectul cu toate exporturile.

import { writeFileSync } from "node:fs";
import { createRequire } from "node:module";

writeFileSync("formatare.mjs", `
  export const moneda = "lei";
  export default function pret(suma) { return suma.toFixed(2) + " " + moneda; }
`);
writeFileSync("app.cjs", `
  const formatare = require("./formatare.mjs");
  console.log(formatare.default(12.5), formatare.moneda);
`);

createRequire(import.meta.url)("./app.cjs");

Rezultat

12.50 lei lei

Greșeli frecvente

  • Scrii import { f } from "./utile" fără extensie: în modulele ES primești ERR_MODULE_NOT_FOUND. Scrie calea completă, ./utile.mjs sau ./utile.js.
  • Folosești __dirname într-un modul ES și primești ReferenceError: __dirname is not defined. Înlocuiește-l cu import.meta.dirname.
  • Amesteci module.exports și export în același fișier: un fișier este fie CommonJS, fie modul ES. Alege una dintre variante.
  • Încarci cu require() un modul ES care are await la nivelul de sus: primești ERR_REQUIRE_ASYNC_MODULE. Folosește await import().

Comenzi înrudite

  • import.meta.dirname / filename: Calea directorului și a fișierului modulului curent: înlocuitorii pentru __dirname și __filename în module ES.
  • package.json: Fișierul de configurare al unui proiect Node.js: nume, versiune, tipul modulelor, scripturi, dependențe și versiunea Node cerută.
  • package.json "exports" și "imports": Alege ce fișiere ale unui pachet pot fi importate din afară (exports) și definește alias-uri interne cu # (imports).
  • node script.js: Rulează un fișier JavaScript în terminal sau o bucată de cod dată direct în comandă (-e, -p).