Kā novērst kļūdu "ERR_MODULE_NOT_FOUND" Node.js ESM importā
ERR_MODULE_NOT_FOUNDnozīmē, ka Node.js sasniedza ECMAScript moduļa ielādētāju un nevarēja atrisināt moduli, ko pieprasīja import, import()vai programmas ieejas punkts. Pašreizējā Node.js dokumentācijā šī kļūda ir īpaši definēta kā ESM ielādētāja atrisināšanas kļūme; analoga CommonJS kļūda ir MODULE_NOT_FOUND. Skatiet oficiālo Node.js kļūdu atsauci .
Ātrākais risinājums ir noteikt, kāda veida specifikators neizdevās, pirms jebkādu izmaiņu veikšanas. Relatīvais imports, piemēram, , ./utils/logger.jsievēro citus noteikumus nekā pakotņu imports, piemēram lodash, . Node.js ESM arī atrisina to atšķirīgi no CommonJS: relatīvajam importam ir nepieciešami skaidri failu paplašinājumi, un direktoriju indeksi netiek automātiski uzminēti. Šīs atšķirības izskaidro daudzas kļūmes pēc pārejas no require()uz import.
Ko tieši Node.js neatrod?
Sāciet ar kļūdas pirmo rindiņu, nevis visu steka izsekošanas informāciju. Parasti tajā ir norādīts gan neatrisinātais mērķis, gan fails, no kura tika mēģināts to importēt. Klasificējiet kļūdaino specifikatoru vienā no šīm grupām:
Relatīvs fails:./utils/logger.js vai ../config.js.
Absolūts fails vai faila URL: absolūts ceļš vai file:URL.
Tukšs iepakojums:lodash , express, vai @scope/pkg.
Pakotnes apakšceļš:some-package/feature.js .
Pakotnes importēšanas aizstājvārds: iekšējs specifikators, kas sākas ar #, definēts caur package.json"imports".
Vispirms izlasiet pirmo kļūdas rindiņu: šajā piemērā ir norādīts tukšs pakotnes nosaukums, tāpēc nākamajām pārbaudēm jākoncentrējas uz atkarību instalēšanu un pakotnes atrisināšanu.
Oficiālajā Node.js ECMAScript moduļu dokumentācijā ir nošķirti relatīvie, pilnīgie un absolūtie specifikatori, jo tie neatrisina problēmas vienādi. Kad esat noskaidrojis, kura kategorija neizdevās, izvairieties no nejaušiem labojumiem, piemēram, dzēšanas node_modulesvai mainīšanas, package.jsonlīdz pierādījumi norāda uz to.
Vai lokālajā ESM importā ir iekļauts faktiskais faila paplašinājums?
Relatīvajiem un absolūtajiem ESM specifikatoriem Node.js pieprasa faila paplašinājumu. Pēc neveiksmīgas relatīvās importēšanas tas nemeklē .js, .mjs, vai .json. Pašreizējā Node.js dokumentācijā šis noteikums tiek saukts par obligātiem faila paplašinājumiem un norādīts arī, ka direktoriju indeksi ir jānorāda pilnībā.
Ja diskā esošais fails ir src/utils/logger.js, šī ir drošā ESM forma:
Šī ir viena no svarīgākajām atšķirībām no CommonJS risinājuma. Oficiālajā Node.js pakotņu dokumentācijā ir paskaidrots, ka require()var izmēģināt paplašinājumus un mapes, savukārt ESM ielādētājs neveic paplašinājumu meklēšanu.
Vai importējat direktoriju, nevis faktisku failu?
CommonJS projekts, iespējams, paļāvās uz direktoriju importēšanu, kas galu galā ielādēja index.js. Nepieņemiet, ka ESM ielādētājs darīs to pašu. Ja jūsu struktūra ir:
src/
config/
index.js
app.js
dod priekšroku:
import config from './config/index.js';
nevis:
import config from './config';
Lokālas atrisināšanas kļūme parasti norāda uz precīzu neatrisināto ceļu. Pārbaudiet ceļu, paplašinājumu un to, vai importēšanas mērķis ir direktorijs, nevis fails.
Oficiālajā ESM dokumentācijā ir norādīts, ka direktoriju indeksi, piemēram, ./startup/index.jsir pilnībā jānorāda. Ja paplašinājuma pievienošana joprojām neizdodas, salīdziniet katru ceļa segmentu ar faktisko direktoriju koku.
Vai projekts tiešām darbojas kā ESM?
Node.js atbalsta gan CommonJS, gan ECMAScript moduļus. .jsFailiem skaidrākais pakotnes līmeņa marķieris ir:
{
"type": "module"
}
Faili, kas beidzas ar , .mjsvienmēr tiek uzskatīti par ES moduļiem, savukārt faili, kas beidzas ar , .cjsvienmēr tiek uzskatīti par CommonJS. Pašreizējās Node.js versijas var noteikt arī ESM sintaksi dažos neskaidros failos, taču Node.js dokumentācija iesaka skaidrus pakotņu marķierus, jo tie ir skaidrāki Node.js, rīkiem un turpmākai apkopei.
Pārbaudiet tuvāko kontrolējošo pakotni (package.json). Augstākā līmeņa tipa vērtība module liek šīs pakotnes .js failiem izmantot ESM semantiku.
Pirms izmaiņu veikšanas izlasiet oficiālos pakotnes un moduļu tipa noteikumus"type" . Pakotnes maiņa no CommonJS uz ESM var ietekmēt daudzus failus vienlaikus. Atcerieties arī, ka pievienošana "type": "module"neinstalē trūkstošu atkarību vai neizlabo nepareizu ceļu; tā tikai nosaka, kā .jstiek interpretēti atbilstošie faili.
Vai trūkstošā pakotne šajā projektā patiešām ir instalēta?
Ja kļūdas ziņojumā ir nosaukta tukša pakotne, piemēram lodash, , pārbaudiet atkarību koku, nevis pieņemot, ka to padara pieejamu globāli instalēta pakotne vai cita darbvieta.
npm ls lodash
Pašreizējā npm dokumentācija npm ls komandai norāda, ka tā uzskaita instalētās pakotnes versijas un var ziņot par trūkstošām vai nederīgām atkarībām. Ja pakotne ir tieša izpildlaika atkarība un nav instalēta, instalējiet to pareizajā projektā:
npm install lodash
Lai importētu tukšu pakotni, pirms ESM sintakses maiņas pārliecinieties, vai pakotne atrodas pašreizējā atkarību kokā.
Oficiālajā npm instalēšanas dokumentācijā ir paskaidrots, ka parasta projekta instalēšana novieto atkarības lokālajā node_moduleskokā un pēc noklusējuma saglabā skaidri instalētās pakotnes mapē dependencies.
Monorepo veiciet pārbaudi darbvietā, kurai pieder importējamais fails. Pakotnes instalēšana citur repozitorijā automātiski nenozīmē, ka pašreizējai pakotnei ir derīga deklarēta atkarība.
Vai pakotnes nosaukums ir pareizs, bet apakšceļš ir nepareizs?
Pakotne var pastāvēt un joprojām noraidīt dziļo importu. Mūsdienu pakotnes var definēt "exports"karti savos package.json. Ja šis lauks pastāv, Node.js atļauj tikai tur deklarētos publiskos ieejas punktus. Oficiālā Node.js pakotnes ieejas punktu dokumentācija norāda, ka atbalstītajās Node.js versijās "exports"ir prioritāte un ka tajā ir iekapsulēti neuzskaitīti apakšceļi."main"
Pieņemsim, ka atkarība dokumentē šo publisko importu:
import { parse } from 'example-package/parser';
Neaizstājiet to ar uzminētu iekšējo ceļu, piemēram:
import { parse } from 'example-package/dist/internal/parser.js';
Pārbaudiet instalētās pakotnes metadatus, ja tiek atrisināta tukša pakotne, bet apakšceļš netiek atrisināts. Publiskos apakšceļus kontrolē pakotnes eksporta karte, ja tāda ir.
Bloķēts "exports"apakšceļš bieži vien ģenerē, ERR_PACKAGE_PATH_NOT_EXPORTEDnevis ERR_MODULE_NOT_FOUND. Šīs kļūdas koda izmaiņas ir noderīgs pierādījums: tas nozīmē, ka Node.js atrada pakotni, bet pieprasītais ceļš nav daļa no tās publiskās saskarnes. Izmantojiet pakotnes dokumentēto importēšanas ceļu, nevis apejot iekapsulēšanu.
Vai ceļš varētu atšķirties tikai pēc pareizrakstības vai burtu reģistriem?
Pārbaudiet faktisko failu koku pēc rakstzīmes. Importēšana, kas šķietami darbojas reģistrjutīgā izstrādes failu sistēmā, var neizdoties pēc izvietošanas reģistrjutīgā failu sistēmā.
Piemēram, ja īstais fails ir:
src/utils/Logger.js
tad imports no:
import logger from './utils/logger.js';
nav pārnēsājams, jo Logger.jsun logger.jsvar būt dažādi failu nosaukumi.
Salīdziniet importēto failu ar reālo direktoriju koku. Pārbaudiet katras mapes nosaukumu, faila nosaukumu, paplašinājumu un lielo burtu lietojumu.
Tāpat pārliecinieties, vai importēšana notiek relatīvi attiecībā pret importēšanas moduli , nevis pret čaulas pašreizējo direktoriju. ESM relatīvie specifikatori tiek atrisināti attiecībā pret importējamā faila moduļa URL.
Kā var redzēt, ko Node.js atrisinātu?
ES modulī import.meta.resolve()var palīdzēt pārbaudīt izšķirtspēju:
Oficiālajā Node.js ESM atsaucē tā ir aprakstīta import.meta.resolve(specifier)kā moduļa relatīva izšķirtspējas funkcija, kas atgriež absolūtu URL virkni un ievēro pakotnes atšifrēšanu un atļautos eksportus.
Pastāv svarīgs pašreizējās versijas brīdinājums: relatīva file:mērķa gadījumā import.meta.resolve()URL var atgriezt pat tad, ja atbilstošais lokālais fails nepastāv. Izmantojiet to, lai atbildētu uz jautājumu "Uz kādu mērķi mezgls atrisina šo specifikatoru?", pēc tam pārbaudiet, vai iegūtais fails patiešām pastāv. Trūkstošu tukšu pakotņu vai nederīgu pakotņu kartējumu gadījumā pati atrisināšana joprojām var atklāt kļūmi agrāk.
Vai jums vajadzētu dzēst node_modules un bloķēšanas failu?
Ne kā pirmā atbilde. Trūkstošs paplašinājums, nepareizs lokālais ceļš vai neatbalstīts pakotnes apakšceļš netiks labots, atkārtoti instalējot atkarības.
Ja npm lsziņo par nekonsekventu koku, projektam ir pievienota commit atzīme package-lock.jsonun vēlaties reproducējamu tīru instalāciju, izmantojiet:
npm ci
Pašreizējā npm ci dokumentācija norāda, ka npm ciir nepieciešams esošs bloķēšanas fails, esošais direktorijs tiek automātiski noņemts , tiek instalēts bloķētais koks un bloķēšanas fails node_modulesnetiek pārrakstīts . Ja un bloķēšanas fails nesakrīt, programma iziet, nevis klusībā atjaunina bloķēšanu.package.jsonpackage.json
Izvairieties no dzēšanas package-lock.jsontikai tāpēc, lai kļūda pazustu. Tas var izraisīt jauna atkarību grafika novēršanu un pārvērst moduļa risināšanas kļūdu par atkarības versijas maiņu.
Kāds ir ātrākais problēmu novēršanas secības veids?
Kā sauc kļūdas
Vispirms pārbaudiet
Tipisks risinājums
./local/path
Precīzs ceļš un paplašinājums
Pievienojiet .js/ .mjsun izlabojiet relatīvo ceļu
Katalogs
Vai jūs gaidījātindex.js
Importēt ./directory/index.jstieši
package-name
npm ls package-name
Instalējiet vai pareizi deklarējiet atkarību
package-name/subpath
Pakotne "exports"un oficiālā pakotnes dokumentācija
Izmantojiet eksportētu publisku apakšceļu
Ceļš, kas izskatās pareizs
Faila nosaukuma reģistrs un faktiskais projekta koks
Precīzi atbilst failu sistēmai
Tikai viena vide neizdodas
Bloķēšanas fails, darbvieta, mezgla versija, failu sistēmas gadījums
Reproducēt ar to pašu deklarēto atkarību koku
Ko vajadzētu izvairīties mainīt akli?
Nepievienojiet "type": "module"tikai tāpēc, ka importēšana neizdevās; vispirms apstipriniet projekta paredzēto moduļu sistēmu.
Nenoņemiet failu paplašinājumus, lai atdarinātu CommonJS piemērus. Node.js ESM prasa skaidrus paplašinājumus relatīvajiem un absolūtajiem failu specifikatoriem.
Neveiciet dziļu privātu failu importu no atkarības, ja tās "exports"karte nodrošina atbalstītu publisku ieejas punktu.
Nepieņemiet, ka veiksmīga globāla npm instalēšana padara atkarību pieejamu lokālai lietojumprogrammai.
Neizdzēsiet bloķēšanas failu kā ikdienas kešatmiņas tīrīšanas darbību.
Nepieņemiet, ka darba direktorijs kontrolē relatīvo ESM importu; importēšanas modulis ir pamats.
Kā jūs zināt, ka labojums ir pabeigts?
Vēlreiz palaidiet to pašu ievades punktu, kas sākotnēji neizdevās, un pārliecinieties, vai modulis novērš kļūdu, neaizstājot to ar citu risinājuma problēmu. Pēc tam palaidiet projekta parastos testus vai startēšanas komandu, lai pārliecinātos, ka labojums darbojas arī pēc viena importēšanas priekšraksta.
Pēc pamatā esošās risinājuma problēmas novēršanas atkārtoti palaidiet sākotnējo komandu un pēc tam projekta parasto testa vai startēšanas darbplūsmu.
Ja lietojumprogramma tagad sasniedz citu kļūdu, piemēram ERR_PACKAGE_PATH_NOT_EXPORTED, ERR_UNKNOWN_FILE_EXTENSION, vai eksporta nosaukuma kļūdu, neuztveriet to kā vienu un to pašu problēmu. Tas nozīmē, ka moduļa risināšana ir turpinājusies un Node.js tagad ziņo par konkrētāku nesaderību.
Apakšējā līnija
Node.js ESM gadījumā ERR_MODULE_NOT_FOUNDtas parasti tiek atrisināts, izsekojot precīzu specifikatoru, nevis visu atkārtoti instalējot. Lokālajiem failiem ir nepieciešami skaidri paplašinājumi un skaidri direktoriju indeksi. Tukšās pakotnes ir jāinstalē pareizajā atkarību kokā. Pakotņu apakšceļiem ir jāievēro "exports". Vadībai package.jsonir jāatbilst paredzētajai moduļu sistēmai, un failu nosaukumiem ir precīzi jāatbilst failu sistēmai.
Kad pie kļūdas pierejas ķeraties šādā secībā — specifikatora tips, reālais ceļš, ESM noteikumi, atkarību koks, pakotņu eksports un pēc tam tīrā instalēšana —, parasti varat ātri noteikt cēloni, neieviešot nesaistītas izmaiņas.