Migrering fra CommonJS til native ES-moduler
Konverter require/module.exports til import/export, og håndter fallgruver med dual-package og interoperabilitet.
Migrering fra CommonJS til native ES-moduler er en gratis leksjon i Bootcamp i backendutvikling med Node.js på CoddyKit. Dette er leksjon 1 av 4. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i Bootcamp i backendutvikling med Node.js, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Bootcamp i backendutvikling med Node.js inneholder totalt 4 leksjoner.
To modulsystemer, én kjøretidsplattform
Node.js brukte historisk CommonJS (CJS): Du laster inn kode med require() og eksponerer den med module.exports. Moderne JavaScript har en innebygd standard, ES Modules (ESM), som bruker import og export.
- CommonJS laster inn moduler synkront under kjøring.
- ESM analyseres statisk, lastes inn asynkront og er den offisielle ECMAScript-standarden.
Node støtter nå begge, men det finnes regler for å blande dem. I denne leksjonen lærer du hvordan du rydder opp i migreringen av et backend-prosjekt fra CJS til innebygd ESM.
// CommonJS (old)
const fs = require('fs');
module.exports = { readConfig };
// ES Modules (new)
import fs from 'fs';
export { readConfig };Slik forteller du Node at du mener ESM
Node avgjør hvordan en fil skal behandles, basert på filendelsen og den nærmeste package.json-filen:
"type": "module"ipackage.json→.js-filer behandles som ESM.- Ingen
type-felt (eller"commonjs") →.js-filer er CommonJS. .mjser alltid ESM, og.cjser alltid CommonJS, uavhengig avtype.
Det ryddigste migreringstrinnet er å legge til "type": "module" én gang og deretter rette filene som får feil.
{
"name": "my-api",
"version": "1.0.0",
"type": "module",
"main": "src/server.js",
"scripts": {
"start": "node src/server.js"
}
}Konvertering av eksporter
Erstatt module.exports og exports.foo med export-setninger.
module.exports = X(én verdi) →export default X.exports.foo = ...(flere navngitte eksporter) →export const foo = ...eller en samletexport { foo, bar }.
Foretrekk navngitte eksporter for hjelpefunksjoner, slik at forbrukere får autofullføring og tydeligere importer.
// 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.14159Konvertering av importer
Erstatt require() med import. La importen samsvare med eksporttypen:
- Navngitt:
const { add } = require('./math')→import { add } from './math.js'. - Standardeksport:
const express = require('express')→import express from 'express'.
Viktig regel: I ESM må relative importer av egne filer inneholde filendelsen (.js). Node gjetter den ikke for deg slik 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)); // 15Slutt på __dirname og __filename
ESM tilbyr ikke CommonJS-globale variabler som __dirname og __filename. Hvis backend-koden bygger filbaner (for konfigurasjon, opplastinger eller maler), må du opprette dem på nytt fra import.meta.url.
Moderne Node (20.11+) eksponerer også import.meta.dirname og import.meta.filename direkte, noe som er det enkleste alternativet 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;Import av JSON og innebygde moduler
To andre endringer som ofte skaper problemer i backend-prosjekter:
- JSON:
require('./data.json')fungerer ikke lenger direkte. Bruk et importattributt:import data from './data.json' with { type: 'json' }. - Kjernemoduler: Foretrekk prefikset
node:(for eksempelimport { readFile } from 'node:fs/promises'). Det er entydig og fremtidssikkert.
Hvis du støtter eldre Node-versjoner, unngår du alle kompatibilitetsproblemer med attributtsyntaks ved å lese JSON via fs.
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);Top-level await er en superkraft
En reell oppgradering ESM gir backend-kode, er top-level await. I CommonJS måtte du pakke asynkron oppstart inn i en IIFE. I en ESM-modul kan du bruke await direkte på toppnivå.
Dette gjør databaseforbindelser, henting av konfigurasjon og oppvarmingslogikk mye ryddigere 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);Interop: ESM importerer CommonJS
Du vil fortsatt være avhengig av npm-pakker som bare støtter CJS. Den gode nyheten er at ESM kan importere CommonJS. Node pakker inn pakkens module.exports som standardeksporten.
- Bruk
import pkg from 'cjs-lib'for å hentemodule.exports. - Node prøver også å oppdage navngitte eksporter, men dette 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]]Interop: CommonJS laster inn ESM
Det motsatte er vanskeligere. En CommonJS-fil kan ikke laste inn en ESM-modul synkront med require() (eldre Node-versjoner kaster ERR_REQUIRE_ESM). Alternativer:
- Bruk en dynamisk
import(), som returnerer et Promise – dette fungerer inne i asynkrone funksjoner i CJS. - Node 22+ har lagt til eksperimentell synkron
require()av ESM, men du bør ikke basere portabel kode på dette.
Denne asymmetrien er hovedgrunnen til at team migrerer hele kodebasen til ESM i stedet for å blande systemene.
// 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();Publisering av doble pakker
Hvis du publiserer et bibliotek, bruker noen av brukerne ESM og andre CJS. Den moderne løsningen er feltet exports med betingede eksporter, slik at begge byggene leveres.
import-betingelsen → ESM-inngangen.require-betingelsen → CJS-inngangen.
Vær oppmerksom på faren ved doble pakker: Hvis begge byggene lastes inn, får du to kopier av modulens tilstand (for eksempel to separate singletons). Plasser tilstandsavhengig logikk i én intern modul som begge byggene 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 migreringssjekkliste
En pålitelig rekkefølge for et eksisterende backend-prosjekt:
- Legg til
"type": "module"ipackage.json. - Gi alle filer som må forbli CJS, nytt navn med endelsen
.cjs. - Konverter
require/module.exportstilimport/export. - Legg til
.js-endelser i alle relative importer. - Erstatt
__dirname/__filenamemedimport.meta-hjelpere. - Rett JSON-importer og interoperabilitet med CJS-standardeksporter.
- Kjør testpakken; la feilene peke ut gjenværende
require-kall.
Verktøy som cjstoesm og codemods kan automatisere de fleste endringene, men gjennomgå alltid diff-en.
Rask kontroll
Du konverterer en backend-fil til ESM og legger til "type": "module". Plutselig kaster en import av din egen hjelpefil ERR_MODULE_NOT_FOUND. Hva er den mest sannsynlige løsningen?
Oppsummering
Du har migrert en Node.js-backend fra CommonJS til innebygde ES Modules. Dette er de viktigste punktene:
- Aktiver ESM med
"type": "module"; bruk.cjs/.mjsfor å overstyre dette per fil. - Bytt ut
require/module.exportsmedimport/export, og inkluder alltid.js-endelsen i relative importer. - Opprett
__dirnamepå nytt viaimport.meta.url(eller brukimport.meta.dirname). - ESM kan importere CJS (som standardeksport); CJS må bruke dynamisk
import()for ESM. - Top-level
awaitforenkler asynkron oppstart. - For biblioteker bør du bruke betingede
exportsog være oppmerksom på faren ved doble pakker.
Med disse reglene kan du trygt modernisere enhver Node-tjeneste til standardiserte ES Modules.
Lær deg JavaScript med en AI-veileder – gratis
Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.
- Kurs
- 22
- Leksjoner
- 92
Ofte stilte spørsmål
Er leksjonen «Migrering fra CommonJS til native ES-moduler» gratis?
Ja – hele teksten i «Migrering fra CommonJS til native ES-moduler» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av Bootcamp i backendutvikling med Node.js-kurset, kan du oppgradere til CoddyKit PRO. Kurset i Bootcamp i backendutvikling med Node.js inneholder totalt 4 leksjoner.
Hva lærer jeg i «Migrering fra CommonJS til native ES-moduler»?
Konverter require/module.exports til import/export, og håndter fallgruver med dual-package og interoperabilitet. Du øver på Bootcamp i backendutvikling med Node.js med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.
Trenger jeg erfaring for å begynne med Bootcamp i backendutvikling med Node.js?
Ingen tidligere erfaring er nødvendig. Bootcamp i backendutvikling med Node.js på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 1 av 4.
Hvor lang tid tar leksjonen «Migrering fra CommonJS til native ES-moduler»?
De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.
Kan jeg skrive og kjøre kode i denne Bootcamp i backendutvikling med Node.js-leksjonen?
Ja. Alle Bootcamp i backendutvikling med Node.js-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.
Alle leksjonene i dette kurset
- Migrering fra CommonJS til native ES-moduler
- Konfigurering av tsconfig for Node-backendprosjekter
- Typesikker miljøkonfigurasjon og validering ved kjøring
- Rask iterasjon med tsx, hot reload og source maps