Slik fikser du «ERR_MODULE_NOT_FOUND» i Node.js ESM-importer
ERR_MODULE_NOT_FOUNDbetyr at Node.js nådde ECMAScript-modullasteren og kunne ikke løse modulen som ble forespurt av en import, import()eller programstartpunkt. I den nåværende Node.js-dokumentasjonen er denne feilen spesifikt definert som en ESM-lasterløsningsfeil; den analoge CommonJS-feilen er MODULE_NOT_FOUND. Se den offisielle Node.js-feilreferansen .
Den raskeste løsningen er å identifisere hva slags spesifikator som feilet før du endrer noe. En relativ import som ./utils/logger.jsfølger andre regler enn en pakkeimport som lodash. Node.js ESM løses også annerledes enn CommonJS: relative importer krever eksplisitte filtyper, og katalogindekser gjettes ikke automatisk. Disse forskjellene forklarer mange feil etter at man har flyttet fra require()til import.
Hva er det egentlig Node.js ikke klarer å finne?
Start med den første linjen i feilen, ikke hele stakksporingen. Den forteller deg vanligvis både det uløste målet og filen som prøvde å importere det. Klassifiser den mislykkede spesifikatoren i en av disse gruppene:
Relativ fil:./utils/logger.js eller ../config.js.
Absolutt fil eller fil-URL: en absolutt sti eller file:URL.
Bar pakke:lodash , express, eller @scope/pkg.
Pakkeundersti:some-package/feature.js .
Pakkeimportalias: en intern spesifikator som begynner med #, definert gjennom package.json"imports".
Les den første feillinjen først: dette eksemplet identifiserer et bart pakkenavn, så de neste kontrollene bør fokusere på avhengighetsinstallasjon og pakkeløsning.
Den offisielle dokumentasjonen for Node.js ECMAScript-moduler skiller relative, bare og absolutte spesifikatorer fordi de ikke løses på samme måte. Når du vet hvilken kategori som feilet, bør du unngå tilfeldige rettelser som sletting node_moduleseller endring package.jsoninntil bevisene peker dit.
Inkluderer en lokal ESM-import den virkelige filtypen?
For relative og absolutte ESM-spesifikatorer krever Node.js filtypen. Den søker ikke etter .js, .mjseller .jsonetter en mislykket relativ import. Den nåværende Node.js-dokumentasjonen kaller denne regelen obligatoriske filtyper og sier også at katalogindekser må være fullstendig spesifisert.
Hvis filen på disken er src/utils/logger.js, er dette det sikre ESM-skjemaet:
import { logger } from './utils/logger.js';
Ikke:
import { logger } from './utils/logger';
Node.js ESM søker ikke etter filtypending for relative importer. Skriv den faktiske filtypendingen i modulspesifikasjonen.
Dette er en av de viktigste forskjellene fra CommonJS-oppløsningen. Den offisielle dokumentasjonen for Node.js-pakker forklarer at require()man kan prøve utvidelser og mapper, mens ESM-lasteren ikke utfører søk etter utvidelser.
Importerer du en katalog i stedet for en faktisk fil?
Et CommonJS-prosjekt kan ha vært avhengig av en katalogimport som til slutt lastet inn en index.js. Ikke anta at ESM-lasteren vil gjøre det samme. Hvis strukturen din er:
src/
config/
index.js
app.js
foretrekker:
import config from './config/index.js';
heller enn:
import config from './config';
En lokal løsningsfeil peker vanligvis mot den nøyaktige uløste banen. Sjekk banen, filtypen og om importen er rettet mot en katalog i stedet for en fil.
Den offisielle ESM-dokumentasjonen sier at katalogindekser som ./startup/index.jsmå spesifiseres fullstendig. Hvis det fortsatt mislykkes å legge til utvidelsen, sammenlign hvert stisegment med det faktiske katalogtreet.
Kjører prosjektet virkelig som ESM?
Node.js støtter både CommonJS- og ECMAScript-moduler. For .jsfiler er den tydeligste pakkenivåmarkøren:
{
"type": "module"
}
Filer som slutter på .mjsbehandles alltid som ES-moduler, mens filer som slutter på .cjsalltid behandles som CommonJS. Nåværende Node.js-versjoner kan også oppdage ESM-syntaks i noen tvetydige filer, men Node.js-dokumentasjonen anbefaler eksplisitte pakkemarkører fordi de er tydeligere for Node.js, verktøy og fremtidig vedlikehold.
Sjekk den nærmeste kontrollerende package.json. En toppnivåtypeverdi for modulen gjør at .js-filer i den pakken bruker ESM-semantikk.
Les de offisielle reglene for pakker og modultyper før du endrer "type". Endring av en pakke fra CommonJS til ESM kan påvirke mange filer samtidig. Husk også at det å legge til "type": "module"ikke installerer en manglende avhengighet eller korrigerer en feil sti; det bestemmer bare hvordan relevante .jsfiler tolkes.
Er den manglende pakken faktisk installert i dette prosjektet?
Hvis feilen navngir en bare pakke, for eksempel lodash, sjekk avhengighetstreet i stedet for å anta at en globalt installert pakke eller et annet arbeidsområde gjør den tilgjengelig.
npm ls lodash
Den nåværende npm-dokumentasjonen for npm ls sier at kommandoen viser installerte pakkeversjoner og kan rapportere manglende eller ugyldige avhengigheter. Hvis pakken er en direkte runtime-avhengighet og ikke er installert, installer den i riktig prosjekt:
npm install lodash
For import av bare pakker, må du bekrefte at pakken er i gjeldende avhengighetstre før du endrer ESM-syntaksen.
Den offisielle npm-installasjonsdokumentasjonen forklarer at en vanlig prosjektinstallasjon plasserer avhengigheter i det lokale node_modulestreet og som standard lagrer eksplisitt installerte pakker til dependencies.
I et monorepo kjører du sjekken i arbeidsområdet som eier importfilen. En pakke som installeres et annet sted i repositoriet betyr ikke automatisk at den gjeldende pakken har en gyldig deklarert avhengighet.
Er pakkenavnet riktig, men understien feil?
En pakke kan eksistere og fortsatt avvise en dyp import. Moderne pakker kan definere et "exports"kart i sin package.json. Når det feltet finnes, tillater Node.js bare de offentlige inngangspunktene som er deklarert der. Den offisielle Node.js-pakkeinngangspunktdokumentasjonen sier "exports"at prioriteres over "main"i støttede Node.js-versjoner og innkapsler ikke-listede underbaner.
Anta at en avhengighet dokumenterer denne offentlige importen:
import { parse } from 'example-package/parser';
Ikke erstatt den med en gjettet intern sti, for eksempel:
import { parse } from 'example-package/dist/internal/parser.js';
Inspiser metadataene for den installerte pakken når en bare pakke løses, men en underbane ikke gjør det. Offentlige underbaner kontrolleres av pakkens eksportkart når et slikt finnes.
En blokkert "exports"understi produserer ofte ERR_PACKAGE_PATH_NOT_EXPORTEDheller enn ERR_MODULE_NOT_FOUND. Den endringen i feilkoden er nyttig bevis: det betyr at Node.js fant pakken, men den forespurte banen er ikke en del av det offentlige grensesnittet. Bruk pakkens dokumenterte importsti i stedet for å omgå innkapsling.
Kan stien bare avvike etter stavemåte eller store bokstaver?
Sjekk det faktiske filtreet for tegn. Importer som ser ut til å fungere på et utviklingsfilsystem som ikke skiller mellom store og små bokstaver, kan mislykkes etter distribusjon til et filsystem som skiller mellom store og små bokstaver.
For eksempel, hvis den virkelige filen er:
src/utils/Logger.js
deretter en import av:
import logger from './utils/logger.js';
er ikke portabel, fordi Logger.jsog logger.jskan ha forskjellige filnavn.
Sammenlign importen med det virkelige katalogtreet. Bekreft alle mappenavn, filnavn, utvidelser og store og små bokstaver.
Bekreft også at importen er relativ til importmodulen , ikke til skallets gjeldende katalog. Relative ESM-spesifikatorer løses relativt til modul-URL-en til importfilen.
Hvordan kan du se hva Node.js ville løse?
I en ES-modul import.meta.resolve()kan følgende hjelpe til med å inspisere oppløsningen:
Den offisielle Node.js ESM-referansen beskriver den import.meta.resolve(specifier)som en modul-relativ oppløsningsfunksjon som returnerer en absolutt URL-streng og respekterer pakkeoppløsning og tillatte eksporter.
Det finnes et viktig forbehold angående gjeldende versjon: for et relativt file:mål import.meta.resolve()kan URL-en returneres selv om den tilsvarende lokale filen ikke finnes. Bruk den til å svare på «Hvilket mål løser noden denne spesifikatoren til?», og bekreft deretter at den resulterende filen faktisk finnes. For manglende pakker uten kode eller ugyldige pakketilordninger kan selve løsningen fortsatt avsløre feilen tidligere.
Bør du slette node_modules og lockfilen?
Ikke som det første svaret. En manglende utvidelse, feil lokal sti eller en ustøttet pakkeundersti vil ikke bli reparert ved å installere avhengigheter på nytt.
Hvis npm lsdet rapporteres et inkonsekvent tre, prosjektet har en committed package-lock.json, og du ønsker en reproduserbar ren installasjon, bruk:
npm ci
Den nåværende npm ci-dokumentasjonen sier at den npm cikrever en eksisterende låsefil, fjerner den eksisterende node_moduleskatalogen automatisk, installerer det låste treet og ikke skriver package.jsonom låsefilen. Hvis package.jsonog låsefilen ikke stemmer overens, avsluttes den i stedet for å oppdatere låsen i stillhet.
Unngå å slette package-lock.jsonbare for å få feilen til å forsvinne. Det kan føre til at en ny avhengighetsgraf løses og gjøre en modulløsningsfeil om til en endring i avhengighetsversjonen.
Ikke legg til "type": "module"bare fordi en import mislyktes; bekreft prosjektets tiltenkte modulsystem først.
Ikke fjern filtyper for å imitere CommonJS-eksempler. Node.js ESM krever eksplisitte typer typer for relative og absolutte filspesifikasjoner.
Ikke dypimporter private filer fra en avhengighet når tilordningen "exports"gir et støttet offentlig inngangspunkt.
Ikke anta at en vellykket global npm-installasjon gjør en avhengighet tilgjengelig for et lokalt program.
Ikke slett en låsefil som et rutinemessig trinn for hurtigbufferrensing.
Ikke anta at arbeidskatalogen kontrollerer relative ESM-importer; importmodulen er basen.
Hvordan vet du at reparasjonen er fullført?
Kjør det samme inngangspunktet som opprinnelig mislyktes på nytt, og bekreft at modulen løser seg uten å erstatte feilen med et annet løsningsproblem. Kjør deretter prosjektets vanlige tester eller oppstartskommando, slik at du vet at løsningen fungerer utover en enkelt import-setning.
Etter at du har rettet opp det underliggende løsningsproblemet, kjør den opprinnelige kommandoen på nytt og deretter prosjektets normale test- eller oppstartsarbeidsflyt.
Hvis applikasjonen nå får en annen feil, for eksempel ERR_PACKAGE_PATH_NOT_EXPORTED, ERR_UNKNOWN_FILE_EXTENSION, eller en eksportnavn-feil, må du ikke behandle det som det samme problemet. Det betyr at modulløsningen har kommet lenger, og Node.js rapporterer nå en mer spesifikk inkompatibilitet.
Konklusjon
For Node.js ESM ERR_MODULE_NOT_FOUNDløses det vanligvis ved å spore den nøyaktige spesifikatoren i stedet for å installere alt på nytt. Lokale filer trenger eksplisitte utvidelser og eksplisitte katalogindekser. Bare pakker må installeres i riktig avhengighetstre. Pakkeunderbaner må respektere "exports". Kontrolleren package.jsonmå samsvare med det tiltenkte modulsystemet, og filnavnene må samsvare nøyaktig med filsystemet.
Når du har behandlet feilen i den rekkefølgen – spesifikatortype, reell sti, ESM-regler, avhengighetstre, pakkeeksport og deretter ren installasjon – kan du vanligvis identifisere årsaken raskt uten å introdusere urelaterte endringer.