Migrering fra CommonJS til native ES-moduler
Konvertér require/module.exports til import/export, og håndtér faldgruber ved dual packages og interoperabilitet.
Migrering fra CommonJS til native ES-moduler er en gratis Bootcamp i backendudvikling med Node.js-lektion på CoddyKit. Dette er lektion 1 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i Bootcamp i backendudvikling med Node.js, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Bootcamp i backendudvikling med Node.js-kurset indeholder 4 lektioner i alt.
To modulsystemer, én kørselstid
Node.js brugte historisk CommonJS (CJS): du indlæser kode med require() og eksponerer den med module.exports. Moderne JavaScript har en indbygget standard, ES Modules (ESM), der bruger import og export.
- CommonJS indlæser moduler synkront under kørsel.
- ESM analyseres statisk, indlæses asynkront og er den officielle ECMAScript-standard.
Node understøtter nu begge dele, men der gælder regler for at blande dem. I denne lektion lærer du trin for trin at migrere et backend-projekt fra CJS til naturlig ESM på en ren måde.
// CommonJS (old)
const fs = require('fs');
module.exports = { readConfig };
// ES Modules (new)
import fs from 'fs';
export { readConfig };Fortæl Node, at du mener ESM
Node afgør, hvordan en fil skal behandles, ud fra filendelsen og den nærmeste package.json:
"type": "module"ipackage.json→.js-filer behandles som ESM.- Intet
type-felt (eller"commonjs") →.js-filer er CommonJS. .mjser altid ESM, og.cjser altid CommonJS, uansettype.
Det reneste migreringstrin er at tilføje "type": "module" én gang og derefter rette de filer, som det skaber problemer for.
{
"name": "my-api",
"version": "1.0.0",
"type": "module",
"main": "src/server.js",
"scripts": {
"start": "node src/server.js"
}
}Konverter eksporteringer
Erstat module.exports og exports.foo med export-sætninger.
module.exports = X(enkelt værdi) →export default X.exports.foo = ...(flere navngivne værdier) →export const foo = ...eller en samletexport { foo, bar }.
Foretræk navngivne eksporteringer til hjælpefunktioner, så brugere får autoudfyldning og tydeligere importeringer.
// Before (CJS)
// module.exports.add = (a, b) => a + b;
// module.exports.PI = 3.14159;
// After (ESM)
export const add = (a, b) => a + b;
export const PI = 3.14159;
console.log(add(2, 3)); // 5
console.log(PI); // 3.14159Konverter importeringer
Erstat require() med import. Tilpas til eksportstilen:
- Navngivet:
const { add } = require('./math')→import { add } from './math.js'. - Standard:
const express = require('express')→import express from 'express'.
Vigtig regel: I ESM skal relative importeringer af dine egne filer indeholde filendelsen (.js). Node gætter ikke endelsen for dig, som CommonJS gjorde.
// Before (CJS)
// const { add } = require('./math');
// After (ESM) — note the explicit .js extension
import { add } from './math.js';
console.log(add(10, 5)); // 15Ikke flere __dirname eller __filename
ESM stiller ikke CommonJS-globale variablerne __dirname og __filename til rådighed. Hvis din backend opbygger filstier (konfiguration, uploads, skabeloner), skal du genskabe dem ud fra import.meta.url.
Moderne Node (20.11+) stiller også import.meta.dirname og import.meta.filename direkte til rådighed, hvilket er den enkleste løsning fremover.
import { fileURLToPath } from 'node:url';
import { dirname, join } from 'node:path';
// Classic portable approach
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const configPath = join(__dirname, 'config.json');
console.log(configPath);
// Node 20.11+ shortcut:
// const dir = import.meta.dirname;Importering af JSON og indbyggede moduler
Her er yderligere to ændringer, der ofte giver backend-projekter problemer:
- JSON:
require('./data.json')fungerer ikke længere direkte. Brug en importattribut:import data from './data.json' with { type: 'json' }. - Kernemoduler: Foretræk præfikset
node:(f.eks.import { readFile } from 'node:fs/promises'). Det er entydigt og fremtidssikret.
Hvis du sigter mod en ældre Node-version, undgår læsning af JSON via fs helt problemer med kompatibilitet for attributsyntaks.
import { readFile } from 'node:fs/promises';
// Robust, version-agnostic way to load JSON in ESM
const raw = await readFile(new URL('./pkg.json', import.meta.url));
const pkg = JSON.parse(raw);
console.log(pkg.name);await på øverste niveau er en superkraft
En reel forbedring, som ESM giver backend-kode, er await på øverste niveau. I CommonJS skulle du pakke asynkron opstart ind i en IIFE. I et ESM-modul kan du bruge await direkte på øverste niveau.
Det gør databaseforbindelser, hentning af konfiguration og opvarmningslogik meget renere i serverens startfiler.
// ESM entry file
async function connectDb() {
await new Promise((r) => setTimeout(r, 50));
return { status: 'connected' };
}
const db = await connectDb(); // top-level await — no IIFE needed
console.log('DB:', db.status);Interoperabilitet: ESM importerer CommonJS
Du vil stadig være afhængig af npm-pakker, der kun understøtter CJS. Den gode nyhed er, at ESM kan importere CommonJS. Node pakker pakkens module.exports ind som standardeksporten.
- Brug
import pkg from 'cjs-lib'for at hentemodule.exports. - Node forsøger også at finde navngivne eksporteringer, men det kan mislykkes for kompleks CJS — destrukturer i stedet standardeksporten.
// 'lodash' is CommonJS; the whole export object is the default
import _ from 'lodash';
const { chunk } = _; // safe: destructure from default
console.log(chunk([1, 2, 3, 4], 2)); // [[1,2],[3,4]]Interoperabilitet: CommonJS indlæser ESM
Den omvendte retning er vanskeligere. En CommonJS-fil kan ikke synkront bruge require() til at indlæse et ESM-modul (ældre Node-versioner udløser ERR_REQUIRE_ESM). Muligheder:
- Brug en dynamisk
import(), som returnerer et Promise — det fungerer inde i asynkrone funktioner i CJS. - Node 22+ tilføjede eksperimentel synkron
require()af ESM, men stol ikke på det i kode, der skal være portabel.
Denne asymmetri er hovedårsagen til, at teams migrerer hele kodebasen til ESM i stedet for at blande systemerne.
// Inside a CommonJS file:
async function run() {
// dynamic import works even from CJS
const { add } = await import('./math.mjs');
console.log(add(4, 6)); // 10
}
run();Udgivelse af dobbelte pakker
Hvis du udgiver et bibliotek, bruger nogle brugere ESM, mens andre bruger CJS. Den moderne løsning er feltet exports med betingede eksporteringer, så begge builds leveres.
import-betingelse → ESM-startpunktet.require-betingelse → CJS-startpunktet.
Pas på risikoen ved dobbelte pakker: Hvis begge builds indlæses, får du to kopier af modulets tilstand (f.eks. to separate singletoner). Placér tilstandsafhængig logik i ét internt modul, som begge builds importerer.
{
"name": "my-lib",
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"exports": {
".": {
"import": "./dist/index.js",
"require": "./dist/index.cjs",
"types": "./dist/index.d.ts"
}
}
}En pragmatisk migreringstjekliste
En pålidelig rækkefølge for et eksisterende backend-projekt:
- Tilføj
"type": "module"tilpackage.json. - Omdøb alle filer, der skal forblive CJS, til
.cjs. - Konvertér
require/module.exportstilimport/export. - Tilføj
.js-endelser til alle relative importeringer. - Erstat
__dirname/__filenamemedimport.meta-hjælpere. - Ret JSON-importeringer og interoperabilitet med CJS-standardeksportering.
- Kør testpakken, og lad fejlene pege på resterende
require-kald.
Værktøjer som cjstoesm eller codemods kan automatisere de fleste redigeringer, men gennemgå altid diffen.
Hurtigt tjek
Du konverterer en backend-fil til ESM og tilføjer "type": "module". Pludselig udløser en importering af din egen hjælpefunktion ERR_MODULE_NOT_FOUND. Hvad er den mest sandsynlige løsning?
Opsummering
Du har migreret en Node.js-backend fra CommonJS til naturlige ES-moduler. Vigtigste pointer:
- Tilvælg systemet med
"type": "module", og brug.cjs/.mjstil at tilsidesætte det pr. fil. - Erstat
require/module.exportsmedimport/export, og medtag altid.js-endelsen i relative importeringer. - Genskab
__dirnameviaimport.meta.url(eller brugimport.meta.dirname). - ESM kan importere CJS (som standardeksportering); CJS skal bruge dynamisk
import()til ESM. awaitpå øverste niveau forenkler asynkron opstart.- Brug betingede
exportstil biblioteker, og pas på risikoen ved dobbelte pakker.
Med disse regler kan du trygt modernisere enhver Node-tjeneste til standardiserede ES-moduler.
Lær JavaScript med en AI-underviser — gratis
Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.
- Kurser
- 22
- Lektioner
- 92
Ofte stillede spørgsmål
Er lektionen “Migrering fra CommonJS til native ES-moduler” gratis?
Ja — hele teksten til “Migrering fra CommonJS til native ES-moduler” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af Bootcamp i backendudvikling med Node.js-kurset, skal du opgradere til CoddyKit PRO. Bootcamp i backendudvikling med Node.js-kurset indeholder 4 lektioner i alt.
Hvad lærer jeg i “Migrering fra CommonJS til native ES-moduler”?
Konvertér require/module.exports til import/export, og håndtér faldgruber ved dual packages og interoperabilitet. Du øver dig i Bootcamp i backendudvikling med Node.js med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.
Skal jeg have erfaring for at begynde på Bootcamp i backendudvikling med Node.js?
Der kræves ingen tidligere erfaring. Bootcamp i backendudvikling med Node.js på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 1 af 4.
Hvor lang tid tager lektionen “Migrering fra CommonJS til native ES-moduler”?
De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.
Kan jeg skrive og køre kode i denne Bootcamp i backendudvikling med Node.js-lektion?
Ja. Alle Bootcamp i backendudvikling med Node.js-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.
Alle lektioner i dette kursus
- Migrering fra CommonJS til native ES-moduler
- Konfiguration af tsconfig til Node-backendprojekter
- Typesikker miljøkonfiguration og runtime-validering
- Hurtig iteration med tsx, hot reload og source maps