Node.js-taustakehityksen bootcamp · Oppitunti

Siirtyminen CommonJS:stä natiiveihin ES-moduuleihin

Muunna require/module.exports import/export-muotoon ja käsittele dual package- ja yhteentoimivuusongelmat.

Oppitunti 1/413 vaihetta

Siirtyminen CommonJS:stä natiiveihin ES-moduuleihin on ilmainen Node.js-taustakehityksen bootcamp-oppitunti CoddyKitissä. Tämä on oppitunti 1/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu Node.js-taustakehityksen bootcamp-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Node.js-taustakehityksen bootcamp-kurssilla on yhteensä 4 oppituntia.

Kaksi moduulijärjestelmää, yksi suoritusympäristö

Node.js käytti perinteisesti CommonJS:ää (CJS): koodi ladataan komennolla require() ja asetetaan muiden käytettäväksi komennolla module.exports. Nykyaikaisessa JavaScriptissä on sisäänrakennettu standardi, ES Modules (ESM), jossa käytetään komentoja import ja export.

  • CommonJS lataa moduulit ajonaikaisesti synkronisesti.
  • ESM analysoidaan staattisesti, ladataan asynkronisesti ja se on virallinen ECMAScript-standardi.

Node tukee nykyään molempia, mutta niiden yhdistämiseen liittyy sääntöjä. Tässä oppitunnissa siirrätte taustapalveluprojektin CJS:stä siististi natiiviin ESM:ään.

// CommonJS (old)
const fs = require('fs');
module.exports = { readConfig };

// ES Modules (new)
import fs from 'fs';
export { readConfig };

Kertokaa Nodelle, että tarkoitatte ESM:ää

Node päättää tiedostotunnisteen ja lähimmän package.json-tiedoston perusteella, miten tiedostoa käsitellään:

  • "type": "module" tiedostossa package.json → .js-tiedostoja käsitellään ESM-tiedostoina.
  • Ei type-kenttää (tai arvo "commonjs") → .js-tiedostot ovat CommonJS-tiedostoja.
  • .mjs on aina ESM ja .cjs aina CommonJS type-kentän arvosta riippumatta.

Siistein siirtovaihe on lisätä "type": "module" kerran ja korjata sitten tiedostot, joissa se aiheuttaa virheitä.

{
  "name": "my-api",
  "version": "1.0.0",
  "type": "module",
  "main": "src/server.js",
  "scripts": {
    "start": "node src/server.js"
  }
}

Vientien muuntaminen

Korvatkaa module.exports ja exports.foo export-lauseilla.

  • module.exports = X (yksi arvo) → export default X.
  • exports.foo = ... (useita nimettyjä vientiarvoja) → export const foo = ... tai ryhmitelty export { foo, bar }.

Suosikaa apuohjelmissa nimettyjä vientiarvoja, jotta käyttäjät saavat automaattisen täydennyksen ja selkeämmät tuonnit.

// 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.14159

Tuontien muuntaminen

Korvatkaa require() komennolla import. Vastatkaa vientityyliä:

  • Nimetty: const { add } = require('./math') → import { add } from './math.js'.
  • Oletusvienti: const express = require('express') → import express from 'express'.

Tärkeä sääntö: ESM:ssä omien tiedostojen suhteellisiin tuonteihin on sisällytettävä tiedostotunniste (.js). Node ei päättele sitä puolestanne kuten CommonJS teki.

// Before (CJS)
// const { add } = require('./math');

// After (ESM) — note the explicit .js extension
import { add } from './math.js';

console.log(add(10, 5)); // 15

Ei enää tunnisteita __dirname tai __filename

ESM ei tarjoa CommonJS:n yleisiä tunnisteita __dirname ja __filename. Jos taustapalvelunne muodostaa tiedostopolkuja (määritykset, lataukset, mallineet), ne on luotava uudelleen import.meta.url-arvon avulla.

Nykyaikainen Node (20.11+) tarjoaa myös tunnisteet import.meta.dirname ja import.meta.filename suoraan, mikä on jatkossa yksinkertaisin vaihtoehto.

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;

JSON-tiedostojen ja sisäänrakennettujen moduulien tuonti

Taustapalveluprojekteihin vaikuttaa vielä kaksi muutosta:

  • JSON: require('./data.json') ei enää toimi suoraan. Käyttäkää tuontiattribuuttia: import data from './data.json' with { type: 'json' }.
  • Ydinmoduulit: suosikaa node:-etuliitettä (esimerkiksi import { readFile } from 'node:fs/promises'). Se poistaa tulkinnanvaraisuuden ja kestää tulevat muutokset.

Jos kohdistatte koodin vanhempaan Node-versioon, JSON-tiedoston lukeminen fs-moduulin avulla välttää attribuuttisyntaksin yhteensopivuusongelmat kokonaan.

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);

Tason ylimmän tason await on supervoima

Yksi aito ESM:n taustakoodille tuoma parannus on ylimmän tason await. CommonJS:ssä asynkroninen käynnistys piti kääriä IIFE-funktioon. ESM-moduulissa voitte käyttää await-komentoa suoraan ylimmällä tasolla.

Tämä tekee tietokantayhteyksistä, määritysten hakemisesta ja alustustoiminnoista huomattavasti selkeämpiä palvelimen käynnistystiedostoissa.

// 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);

Yhteentoimivuus: ESM tuo CommonJS:n

Tulette edelleen riippumaan vain CJS:ää tukevista npm-paketeista. Hyvä uutinen on, että ESM voi tuoda CommonJS:n. Node käärii paketin module.exports-arvon oletusvientiarvoksi.

  • Käyttäkää import pkg from 'cjs-lib' saadaksenne module.exports-arvon.
  • Node yrittää tunnistaa myös nimetyt viennit, mutta monimutkainen CJS voi aiheuttaa tässä virheen — purkakaa arvot sen sijaan oletusviennistä.
// '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]]

Yhteentoimivuus: CommonJS lataa ESM:n

Toinen suunta on vaikeampi. CommonJS-tiedosto ei voi ladata ESM-moduulia synkronisesti komennolla require() (vanhemmat Node-versiot aiheuttavat virheen ERR_REQUIRE_ESM). Vaihtoehdot:

  • Käyttäkää dynaamista import()-tuontia, joka palauttaa Promisen — se toimii CJS:n asynkronisten funktioiden sisällä.
  • Node 22+ lisäsi kokeellisen mahdollisuuden ladata ESM synkronisesti komennolla require(), mutta älkää luottako siihen siirrettävässä koodissa.

Tämä epäsymmetria on tärkein syy siihen, että tiimit siirtävät koko koodikannan ESM:ään sen sijaan, että yhdistäisivät molempia.

// 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();

Kaksoispakettien julkaiseminen

Jos julkaisette kirjaston, osa käyttäjistä käyttää ESM:ää ja osa CJS:ää. Nykyaikainen ratkaisu on exports-kenttä ja ehdolliset viennit, joiden avulla toimitetaan molemmat koontiversiot.

  • import-ehto → ESM-aloituskohta.
  • require-ehto → CJS-aloituskohta.

Varokaa kaksoispakettivaaraa: jos molemmat koontiversiot ladataan, moduulin tilasta syntyy kaksi kopiota (esimerkiksi kaksi erillistä singleton-oliota). Pitäkää tilallinen logiikka yhdessä sisäisessä moduulissa, jonka molemmat koontiversiot tuovat.

{
  "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"
    }
  }
}

Käytännöllinen siirtotarkistuslista

Luotettava toimintajärjestys olemassa olevalle taustapalvelulle:

  • Lisätkää "type": "module" tiedostoon package.json.
  • Nimetkää kaikki CommonJS:ksi jäävät tiedostot uudelleen muotoon .cjs.
  • Muuntaa require/module.exports muotoon import/export.
  • Lisätkää .js-tunnisteet kaikkiin suhteellisiin tuonteihin.
  • Korvatkaa __dirname/__filename import.meta-apuominaisuuksilla.
  • Korjatkaa JSON-tuonnit ja CJS-oletusviennin yhteentoimivuus.
  • Suorittakaa testit; antakaa virheiden osoittaa jäljellä olevat require-kutsut.

Työkalut, kuten cjstoesm tai codemodit, voivat automatisoida suurimman osan muokkauksista, mutta tarkistakaa muutokset aina.

Pikatarkistus

Muunneratte taustapalvelutiedoston ESM:ään ja lisäätte "type": "module"-asetuksen. Yhtäkkiä oman apuohjelman tuonti aiheuttaa virheen ERR_MODULE_NOT_FOUND. Mikä on todennäköisin korjaus?

Kertaus

Siirsitte Node.js-taustapalvelun CommonJS:stä natiiveihin ES-moduuleihin. Tärkeimmät asiat:

  • Ottakaa ESM käyttöön asetuksella "type": "module"; käyttäkää .cjs/.mjs-tunnisteita tiedostokohtaiseen ohitukseen.
  • Vaihtakaa require/module.exports muotoon import/export ja sisällyttäkää aina .js-tunniste suhteellisiin tuonteihin.
  • Luokaa __dirname uudelleen import.meta.url-arvon avulla (tai käyttäkää import.meta.dirname-tunnistetta).
  • ESM voi tuoda CJS:n oletusvientinä; CJS:n on käytettävä dynaamista import()-tuontia ESM:ää varten.
  • Ylimmän tason await yksinkertaistaa asynkronista käynnistystä.
  • Käyttäkää kirjastoissa ehdollista exports-määritystä ja varokaa kaksoispakettivaaraa.

Näiden sääntöjen avulla voitte nykyaikaistaa minkä tahansa Node-palvelun luottavaisesti standardin mukaisiksi ES-moduuleiksi.

Aloita maksutta

Opi JavaScript tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
22
Oppitunnit
92

Usein kysytyt kysymykset

Onko oppitunti ”Siirtyminen CommonJS:stä natiiveihin ES-moduuleihin” ilmainen?

Kyllä – oppitunnin ”Siirtyminen CommonJS:stä natiiveihin ES-moduuleihin” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko Node.js-taustakehityksen bootcamp-kurssin, päivitä CoddyKit PROhon. Node.js-taustakehityksen bootcamp-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”Siirtyminen CommonJS:stä natiiveihin ES-moduuleihin”?

Muunna require/module.exports import/export-muotoon ja käsittele dual package- ja yhteentoimivuusongelmat. Harjoittelet Node.js-taustakehityksen bootcamp-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni Node.js-taustakehityksen bootcamp-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin Node.js-taustakehityksen bootcamp-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 1/4.

Kuinka kauan ”Siirtyminen CommonJS:stä natiiveihin ES-moduuleihin”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä Node.js-taustakehityksen bootcamp-oppitunnilla?

Kyllä. Jokainen Node.js-taustakehityksen bootcamp-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. Siirtyminen CommonJS:stä natiiveihin ES-moduuleihin
  2. tsconfigin määrittäminen Node-taustaprojekteille
  3. Tyyppiturvallinen ympäristökonfiguraatio ja ajonaikainen validointi
  4. Nopea iterointi tsx:llä, hot reloadilla ja source map -tiedostoilla
← Takaisin: Node.js-taustakehityksen bootcamp