Domů
» Základní znalosti
»
Jak opravit chybu „ERR_MODULE_NOT_FOUND“ v importech Node.js ESM
Jak opravit chybu „ERR_MODULE_NOT_FOUND“ v importech Node.js ESM
ERR_MODULE_NOT_FOUNDznamená, že Node.js dosáhl zavaděče modulů ECMAScript a nemohl vyřešit modul požadovaný prvkem import, import()nebo vstupním bodem programu. V aktuální dokumentaci Node.js je tato chyba konkrétně definována jako selhání vyřešení zavaděče ESM; analogická chyba CommonJS je MODULE_NOT_FOUND. Viz oficiální reference chyb Node.js .
Nejrychlejší opravou je zjistit, jaký typ specifikátoru selhal, než cokoli změnit. Relativní import, například ., ./utils/logger.jsse řídí jinými pravidly než import balíčku, například lodash. Node.js ESM se také řeší odlišně od CommonJS: relativní importy vyžadují explicitní přípony souborů a indexy adresářů se nehádají automaticky. Tyto rozdíly vysvětlují mnoho selhání po přechodu z . require()na import.
Co přesně Node.js nedokáže najít?
Začněte prvním řádkem chyby, ne celým trasováním zásobníku. Obvykle vám ukáže jak nevyřešený cíl, tak i soubor, který se pokusil o jeho import. Zařaďte chybný specifikátor do jedné z těchto skupin:
Relativní soubor:./utils/logger.js nebo ../config.js.
Absolutní soubor nebo URL souboru: absolutní cesta nebo file:URL.
Holý balíček:lodash , express, nebo @scope/pkg.
Podcesta balíčku:some-package/feature.js .
Alias importu balíčku: interní specifikátor začínající na #, definovaný pomocí package.json"imports".
Nejprve si přečtěte první chybový řádek: tento příklad identifikuje holý název balíčku, takže další kontroly by se měly zaměřit na instalaci závislostí a rozlišení balíčků.
Oficiální dokumentace modulů Node.js ECMAScript odděluje relativní, holé a absolutní specifikátory, protože se neřeší stejným způsobem. Jakmile zjistíte, která kategorie selhala, vyhněte se náhodným opravám, jako je mazání node_modulesnebo změna, package.jsondokud na to neukážou důkazy.
Obsahuje lokální import ESM skutečnou příponu souboru?
Pro relativní a absolutní specifikátory ESM vyžaduje Node.js příponu souboru. Nehledá .js, .mjsani .jsonpo neúspěšném relativním importu. Aktuální dokumentace Node.js označuje toto pravidlo jako povinné přípony souborů a také uvádí, že indexy adresářů musí být plně specifikovány.
Pokud je soubor na disku src/utils/logger.js, jedná se o bezpečný formulář ESM:
import { logger } from './utils/logger.js';
Ne:
import { logger } from './utils/logger';
Node.js ESM neprovádí vyhledávání přípon pro relativní importy. Skutečnou příponu souboru napište do specifikátoru modulu.
Toto je jeden z nejdůležitějších rozdílů oproti rozlišení CommonJS. Oficiální dokumentace balíčků Node.js vysvětluje, že require()lze vyzkoušet rozšíření a složky, zatímco zavaděč ESM neprovádí vyhledávání rozšíření.
Importujete adresář místo skutečného souboru?
Projekt CommonJS mohl spoléhat na import adresáře, který nakonec načetl soubor index.js. Nepředpokládejte, že zavaděč ESM udělá totéž. Pokud je vaše struktura:
src/
config/
index.js
app.js
preferuji:
import config from './config/index.js';
spíše než:
import config from './config';
Lokální chyba rozlišení obvykle ukazuje na přesnou nerozluštěnou cestu. Zkontrolujte cestu, příponu a zda import cílí na adresář, nikoli na soubor.
Oficiální dokumentace ESM uvádí, že indexy adresářů, jako například , ./startup/index.jsmusí být plně specifikovány. Pokud přidání rozšíření stále selže, porovnejte každý segment cesty se skutečným stromem adresářů.
Opravdu projekt běží jako ESM?
Node.js podporuje moduly CommonJS i ECMAScript. Pro .jssoubory je nejjasnějším ukazatelem na úrovni balíčku:
{
"type": "module"
}
Soubory končící na .mjsjsou vždy považovány za moduly ES, zatímco soubory končící na .cjsjsou vždy považovány za moduly CommonJS. Aktuální verze Node.js dokáží také detekovat syntaxi ESM v některých nejednoznačných souborech, ale dokumentace Node.js doporučuje explicitní značky balíčků, protože jsou pro Node.js, nástroje a budoucí údržbu srozumitelnější.
Zkontrolujte nejbližší řídící soubor package.json. Hodnota typu nejvyšší úrovně module způsobí, že soubory .js v tomto balíčku budou používat sémantiku ESM.
Před změnou si přečtěte oficiální pravidla pro balíčky a typy modulů"type" . Změna balíčku z CommonJS na ESM může ovlivnit mnoho souborů najednou. Nezapomeňte také, že přidání "type": "module"neinstaluje chybějící závislost ani neopravuje nesprávnou cestu; pouze určuje, jak .jsjsou relevantní soubory interpretovány.
Je chybějící balíček v tomto projektu skutečně nainstalován?
Pokud chyba pojmenovává holý balíček, například lodash, zkontrolujte strom závislostí namísto předpokladu, že jej zpřístupňuje globálně nainstalovaný balíček nebo jiný pracovní prostor.
npm ls lodash
Aktuální dokumentace npm pro npm ls uvádí, že příkaz vypíše nainstalované verze balíčků a může hlásit chybějící nebo neplatné závislosti. Pokud je balíček přímou běhovou závislostí a není nainstalován, nainstalujte jej do správného projektu:
npm install lodash
V případě importu holého balíčku ověřte, zda se balíček nachází v aktuálním stromu závislostí, než změníte syntaxi ESM.
Oficiální dokumentace k instalaci npm vysvětluje, že normální instalace projektu umisťuje závislosti do lokálního node_modulesstromu a ve výchozím nastavení ukládá explicitně nainstalované balíčky do dependencies.
V monorepozitáři spusťte kontrolu v pracovním prostoru, který vlastní importovaný soubor. Instalace balíčku jinde v repozitáři automaticky neznamená, že aktuální balíček má platnou deklarovanou závislost.
Je název balíčku správný, ale podcesta špatná?
Balíček může existovat a přesto odmítat hluboký import. Moderní balíčky mohou definovat "exports"mapu ve svém souboru package.json. Pokud toto pole existuje, Node.js povoluje pouze veřejné vstupní body deklarované v něm. Oficiální dokumentace k vstupním bodům balíčků Node.js uvádí, že "exports"má přednost před "main"v podporovaných verzích Node.js a zapouzdřuje neuvedené podcesty.
Předpokládejme, že závislost dokumentuje tento veřejný import:
import { parse } from 'example-package/parser';
Nenahrazujte ji uhodnutou vnitřní cestou, například:
import { parse } from 'example-package/dist/internal/parser.js';
Zkontrolujte metadata nainstalovaného balíčku, když se holý balíček nalezne, ale podcesta ne. Veřejné podcesty jsou řízeny mapou exportů balíčku, pokud je k dispozici.
Zablokovaná "exports"podcesta často vytváří ERR_PACKAGE_PATH_NOT_EXPORTEDspíše než ERR_MODULE_NOT_FOUND. Tato změna v chybovém kódu je užitečným důkazem: znamená to, že Node.js našel balíček, ale požadovaná cesta není součástí jeho veřejného rozhraní. Použijte zdokumentovanou cestu importu balíčku, místo abyste obešli zapouzdření.
Mohla by se cesta lišit pouze pravopisem nebo velikostí písmen?
Zkontrolujte skutečný souborový strom, zda neobsahuje znaky. Importy, které zdánlivě fungují na vývojovém souborovém systému bez rozlišení velkých a malých písmen, mohou po nasazení do souborového systému rozlišujícího velká a malá písmena selhat.
Například pokud je skutečný soubor:
src/utils/Logger.js
pak import:
import logger from './utils/logger.js';
není přenositelný, protože Logger.jsa logger.jsmohou mít různé názvy souborů.
Porovnejte import se skutečným adresářovým stromem. Ověřte každý název složky, název souboru, příponu a velká a malá písmena.
Také ověřte, že import je relativní vzhledem k importujícímu modulu , nikoli k aktuálnímu adresáři shellu. Relativní specifikátory ESM jsou rozpoznávány relativně k URL modulu importujícího souboru.
Jak můžete vidět, co by Node.js vyřešil?
V modulu ES import.meta.resolve()může pomoci kontrolovat rozlišení:
Oficiální reference Node.js ESM popisuje import.meta.resolve(specifier)funkci relativního rozlišení modulu, která vrací absolutní řetězec URL a respektuje rozlišení balíčků a povolené exporty.
Existuje důležité upozornění pro aktuální verzi: v případě relativního file:cíle import.meta.resolve()může vrátit URL, i když odpovídající lokální soubor neexistuje. Použijte ho k zodpovězení otázky „Na jaký cíl uzel překládá tento specifikátor?“ a poté ověřte, zda výsledný soubor skutečně existuje. V případě chybějících holých balíčků nebo neplatných mapování balíčků může samotné překlad odhalit chybu dříve.
Měli byste smazat node_modules a lockfile?
Ne jako první odpověď. Chybějící rozšíření, nesprávná lokální cesta nebo nepodporovaná podcesta balíčku nebudou opraveny přeinstalací závislostí.
Pokud npm lshlásí nekonzistentní strom, projekt má commit package-lock.jsona chcete reprodukovatelnou čistou instalaci, použijte:
npm ci
Aktuální dokumentace k npm ci uvádí, že npm civyžaduje existující lockfile, automaticky odstraní existující node_modulesadresář, nainstaluje uzamčený strom a nepřepisuje package.jsonlockfile. Pokud se package.jsonhodnoty `a `lockfile` neshodují, program se místo tiché aktualizace zámku ukončí.
Vyhněte se mazání package-lock.jsonpouze proto, aby chyba zmizela. To může způsobit vyřešení nového grafu závislostí a změnit chybu v rozlišení modulů na změnu verze závislostí.
Jaké je nejrychlejší pořadí řešení problémů?
Jak se chyby nazývají
Nejprve zkontrolujte
Typická oprava
./local/path
Přesná cesta a rozšíření
Přidejte .js/ .mjsa opravte relativní cestu
Adresář
Ať už jste očekávaliindex.js
./directory/index.jsExplicitní import
package-name
npm ls package-name
Nainstalujte nebo správně deklarujte závislost
package-name/subpath
Balíček "exports"a oficiální dokumentace k balíčku
Použít exportovanou veřejnou podcestu
Cesta, která vypadá správně
Velká a malá část názvu souboru a skutečný strom projektu
Přesně shodný souborový systém
Selže pouze jedno prostředí
Lockfile, pracovní prostor, verze uzlu, případ souborového systému
Reprodukovat se stejným deklarovaným stromem závislostí
Čeho byste se měli vyvarovat při ukvapených změnách?
Nepřidávejte moduly "type": "module"jen proto, že import selhal; nejprve ověřte zamýšlený systém modulů projektu.
Neodstraňujte přípony souborů, abyste napodobili příklady CommonJS. Node.js ESM vyžaduje explicitní přípony pro relativní a absolutní specifikátory souborů.
Neprovádějte hluboký import soukromých souborů ze závislosti, pokud její "exports"mapa poskytuje podporovaný veřejný vstupní bod.
Nepředpokládejte, že úspěšná globální instalace npm zpřístupní závislost lokální aplikaci.
Neodstraňujte soubor lockfile jako rutinní krok čištění mezipaměti.
Nepředpokládejte, že pracovní adresář řídí relativní importy ESM; základ tvoří importní modul.
Jak poznáte, že oprava je hotová?
Znovu spusťte stejný vstupní bod, který původně selhal, a ověřte, že se modul vyřeší bez nahrazení chyby jiným problémem s řešením. Poté spusťte běžné testy projektu nebo příkaz spouštění, abyste věděli, že oprava funguje i po jediném příkazu importu.
Po opravě základního problému s rozlišením znovu spusťte původní příkaz a poté běžný testovací nebo spouštěcí pracovní postup projektu.
Pokud aplikace nyní narazí na jinou chybu, například ERR_PACKAGE_PATH_NOT_EXPORTED, ERR_UNKNOWN_FILE_EXTENSIONnebo chybu názvu exportu, nepovažujte to za stejný problém. Znamená to, že řešení modulů pokročilo dále a Node.js nyní hlásí konkrétnější nekompatibilitu.
Sečteno a podtrženo
U Node.js ESM ERR_MODULE_NOT_FOUNDse problém obvykle řeší trasováním přesného specifikátoru, nikoli přeinstalováním všeho. Lokální soubory potřebují explicitní přípony a explicitní indexy adresářů. Holé balíčky musí být nainstalovány ve správném stromu závislostí. Podcesty balíčků musí respektovat "exports". Řídicí systém package.jsonmusí odpovídat zamýšlenému systému modulů a názvy souborů musí přesně odpovídat souborovému systému.
Jakmile k chybě přistoupíte v tomto pořadí – typ specifikátoru, skutečná cesta, pravidla ESM, strom závislostí, export balíčků a poté čistá instalace – obvykle můžete rychle identifikovat příčinu, aniž byste museli provádět nesouvisející změny.