Начало
» Основни познания
»
Как да поправите грешката „Module Not Found: Can’t Resolve fs“ в Webpack
Как да поправите грешката „Module Not Found: Can’t Resolve fs“ в Webpack
Последна проверка: 11 септември 2026 г. Грешката „Module not found: Error: Can’t resolve 'fs'“ обикновено означава, че Webpack изгражда код за браузър, но вашият изходен код — или една от неговите зависимости — импортира модула за файловата система на Node.js. Node документира node:fs като API за взаимодействие с файловата система, докато текущата документация на Webpack посочва, че Webpack 5 вече не автоматично полифилва основните модули на Node.js за браузърни сборки.
Важната част е да изберете поправката, която съответства на това, което кодът всъщност се опитва да направи. Няма единна настройка, която да е правилна за всеки проект. Ако вашето приложение наистина има нужда да чете файлове от диска на сървъра, преместете тази работа в Node/сървърен код. Ако зависимостта импортира fs само за опционална функция, предназначена само за Node, която вашата браузърна сборка никога не използва, resolve.fallback: { fs: false } може да е подходящо. Ако пакетът има съвместима с браузър версия, използвайте нея. А ако сборката е предназначена да работи в Node, задайте целта за Node, вместо да се правите, че е уеб сборка.
Бърза таблица за вземане на решение
Ситуация
Най-добра първа поправка
Основно предимство
Основно компромисно решение
Вашият собствен браузърен код импортира fs
Премахнете го от браузърния път или преместете операцията в сървър/API
Съответства на реалната среда на изпълнение
Изисква архитектурна граница между клиент и сървър
Зависимост импортира fs, но тази функция никога не се използва в браузъра
Помислете за resolve.fallback: { fs: false }
Малка, проста поправка на сборката
Ще се провали логически, ако пакетът по-късно изпълни код, зависещ от файловата система
Зависимост предлага браузърни и Node сборки
Използвайте или надградете до браузър-съвместимия вход
Запазва желаното поведение в браузъра
Може да изисква промени в пакета/версията
Изходът работи в Node, а не в браузър
Използвайте target: "node"
Запазва вградените модули на Node достъпни по време на изпълнение
Изходът вече не е браузърна сборка
Опитвате се да „полифилвате fs“ в браузъра
Преосмислете изискването
Избягва подвеждащ слой за съвместимост
Може да ви трябва различен браузърен работен процес за съхранение/файлове
Официалната документация на Webpack за resolve.fallback посочва, че Webpack 5 вече не полифилва автоматично основните модули на Node. Неговите бележки за изданието на Webpack 5 обясняват причината: автоматичните полифилве можеха да добавят голям, ненужен код за съвместимост към фронтенд сборките, затова Webpack прехвърли отговорността към приложението или автора на пакета.
Стъпка 1: Разберете кой импортира fs
Започнете с първата полезна линия в изхода на грешката на Webpack. Тя обикновено сочи към файла, където разрешаването е неуспешно, например:
ERROR in ./src/utils/fileHelper.js 1:0-20
Module not found: Error: Can't resolve 'fs'
Илюстрация, генерирана от AI, на сборка на Webpack, която се проваля при импорт на fs. Това не е изход от реален проект; имената на файловете и номерата на редовете са илюстративни.
Ако провалящият файл е ваш, потърсете в него един от следните форми:
const fs = require('fs')
// или
import fs from 'node:fs'
// или
import { readFile } from 'node:fs/promises'
Официалната документация на Node за файловата система потвърждава, че node:fs и node:fs/promises са Node API за операции с файловата система. Нормална браузърна сборка не получава достъп до диска на сървъра само защото Webpack може да анализира импорта.
Ако провалящият файл е под node_modules, не редактирайте веднага този пакет на място. Първо идентифицирайте коя зависимость от най-високо ниво го е довела във вашата браузърна сборка. Полезният въпрос не е само „Кой пакет импортира fs?“, а „Защо този код, ориентиран към Node, е достъпен от моя клиентски вход?“
Използвайте тази диагностика, когато: грешката се появява след надграждане на Webpack, добавяне на зависимост, импортиране на предишен сървърен инструмент във фронтенд код или преместване на споделен код в клиентска сборка.
Практическа проверка: временно премахнете импорта, който води до провалящия модул, и преизградете. Ако грешката с fs изчезне, сте потвърдили пътя на зависимостта преди да промените конфигурацията на Webpack.
Стъпка 2: Ако кодът наистина има нужда от достъп до файловата система, преместете го в Node/сървърен код
Това е най-добрата поправка, когато кодът трябва да чете конфигурационни файлове, шаблони, локални документи, частни ключове, генерирани ресурси, сървърни логове или каквото и да е друго от файловата система на машината.
Например, това е подходящо в Node:
import { readFile } from 'node:fs/promises'
export async function loadTemplate() {
return readFile('./templates/email.html', 'utf8')
}
Но не трябва да се включва в браузърен вход. Вместо това, изложете резултата чрез сървърния слой на вашето приложение. Опростено разделение може да бъде:
// сървърен код
import { readFile } from 'node:fs/promises'
app.get('/api/template', async (req, res) => {
const text = await readFile('./templates/email.html', 'utf8')
res.type('text/plain').send(text)
})
// браузърен код
export async function loadTemplate() {
const response = await fetch('/api/template')
if (!response.ok) throw new Error('Failed to load template')
return response.text()
}
Илюстрация, генерирана от AI, за разделяне на работата с файловата система на Node от браузърния код. Това е концептуален пример за архитектура, а не екранна снимка на конкретна рамка.
Компромисът е архитектурен: добавяте сървърен крайна точка или друга сървърна граница, но запазвате семантиката на fs. Браузърът заявява данни; сървърът чете файловата система.
Това решение е подходящо, когато: операцията с файловата система е реална и необходима.
Това решение не е необходимо, когато: импортът съществува само вътре в опционален Node код, който браузърът никога не изпълнява. В такъв случай браузър-специфичен вход на пакета или игнориран резервен вариант може да е по-чисто решение.
Стъпка 3: Използвайте resolve.fallback: { fs: false } само когато поведението на файловата система е опционално
Официалното ръководство за миграция от Webpack 4 към 5 на Webpack конкретно посочва, че конфигурациите, използващи стария модел node.fs: 'empty', трябва да преминат към:
Илюстрация, генерирана от AI, на resolve.fallback: { fs: false }. Използвайте това само когато браузърът няма нужда от поведението на файловата система на зависимостта.
Задаването на резервен вариант на false казва на Webpack да не включва имплементация за този неразрешен модул. Това може да е точно правилно за пакет, който съдържа защитен клон, предназначен само за Node, като код, който използва fs само по време на сървърно рендиране или изпълнение на CLI.
То също така може да скрие грешката при сборка, като ви остави с бъг в дизайна по време на изпълнение. Помислете за тази зависимост:
Ако вашият браузър наистина извиква loadUserConfig(), заместването на fs с „нищо“ не създава функционираща браузърна файлова система. Сборката може да продължи, но функцията все пак не може да изпълни желаната Node операция.
Използвайте fs: false, когато: сте потвърдили, че клонът, специфичен за файловата система, не се използва в уеб целта.
Не го използвайте, когато: вашата браузърна функция зависи от readFileSync, обхождане на директории, сървърни пътища или друго реално поведение на файловата система на Node.
Защо „просто инсталирайте полифил за fs“ обикновено е грешният първи отговор
Текущата документация на Webpack за resolve.fallback дава примери за ръчни полифилве за няколко основни модула на Node, като path, buffer, stream и crypto. Забележително е, че нейният списък за съвместимост не предоставя обща замяна на fs, еквивалентна на файловата система на Node.
Тази разлика е важна. JavaScript инструментите често могат да бъдат възпроизведени в браузър. Произволният достъп до файловата система на хоста/сървъра е възможност на средата за изпълнение, а не просто липсваща помощна функция.
Ако това, от което наистина имате нужда, е браузърен работен процес, изберете браузър-нативен дизайн за конкретната задача — например, изтеглете ресурс от URL, позволете на потребителя да избере файл или съхранете данни на приложението, използвайки подходящ механизъм за съхранение в браузъра. Не преценявайте успеха само по това дали Webpack спира да показва грешката.
Вариант 4: Предпочетете зависимост или експорт на пакет, съвместим с браузър
Ако грешката идва от пакет на трета страна, проверете дали този пакет официално поддържа браузъри. Текущото ръководство на Webpack за exports на пакети обяснява, че пакетите могат да предоставят условни експорти за среди като browser и node. Ръководството за изданието на Webpack също препоръчва на авторите на пакети да предоставят алтернативи, съвместими с фронтенда, когато имплементациите, предназначени само за Node, не са подходящи за браузъри.
Ако надградена версия на пакета предоставя правилен браузърен вход, докато вашата по-стара версия не го прави, надграждането може да е по-безопасно от конфигурирането на fs: false. По същия начин, заместването на пакет, ориентиран към Node, с такъв, проектиран изрично за използване в браузър, може да намали хаквете за съвместимост и сложността на сборката.
Изберете този път, когато: зависимостта трябва да работи в браузъри, но инсталираната версия избира или излага имплементация, предназначена само за Node.
Компромис: надграждането или заместването на пакет може да въведе промени в API, затова изпълнете нормалните си тестове за приложението, вместо да третирате успешната компилация като достатъчна.
Вариант 5: Ако изходът е Node сборка, задайте целта на Node
Понякога Webpack изобщо не произвежда браузърен код. Може да сглобявате CLI, фонов работник, инструмент за изграждане, SSR сървър или Node услуга. В такъв случай опитът да потиснете fs е назад: средата за изпълнение всъщност го предоставя.
Използвайте target: 'node', когато: полученият JavaScript ще се изпълнява под Node.
Не го използвайте, за да „поправите“ нормална браузърна SPA: промяната на целта не кара браузърът внезапно да предостави API-тата на файловата система на Node. Тя променя средата, за която Webpack предполага, че ще изпълни сборката.
Разширени Node сборки: externals могат да запазят вградените модули по време на изпълнение
За сървърни сборки, Webpack също предоставя поведение на externals, ориентирано към Node. Неговата официална документация за Externals посочва, че externalsPresets.node може да третира вградените модули на Node, като fs, path и vm, като външни и да ги зарежда с require() на Node по време на изпълнение.
Типична конфигурация, ориентирана към Node, следователно може да изглежда така:
Това е разширен въпрос за сървърни сборки, а не браузърен заобикалящ път.
Стъпка 4: Преизградете, след което тествайте функцията, която предизвика импорта
След като направите архитектурната или конфигурационна промяна, преизградете:
npm run build
Илюстрация, генерирана от AI, на успешна преизградба на Webpack. Номерата на версиите, размерите на ресурсите и времената за изграждане са измислени примери.
Чистата компилация доказва само, че разрешаването на модули е успяло. Тя не доказва, че засегнатата функция се държи правилно. Тествайте според поправката, която сте избрали:
Ако сте преместили достъпа до файлове в сървъра, извикайте браузърната функция и проверете дали сървърният крайна точка връща очакваните данни.
Ако сте задали fs: false, използвайте зависимостта в браузъра и потвърдете, че тя никога не влиза в клона, зависещ от файловата система.
Ако сте превключили към браузърна версия на пакет, изпълнете реалния работен процес на пакета, предназначен за потребителя.
Ако сте променили целта на Node, изпълнете изградения изход под версията на Node, която поддържате.
Сравнение на често срещаните поправки
Поправка
Безопасна за браузър?
Запазва ли реален достъп до файловата система на Node?
Кога да я предпочетете
Преместване на работата с fs в сървър/API
Да
Да, на сървъра
Вашето приложение наистина има нужда от данни от файловата система на сървъра
resolve.fallback.fs = false
Само ако клонът fs не се използва
Не
Опционален път на зависимост, предназначен само за Node
Пакет/експорт, специфичен за браузър
Да, ако пакетът го поддържа
Не; предоставя вместо това браузър-специфично поведение
Зависимостта е предназначена да поддържа двете среди за изпълнение
target: 'node'
Не
Да
Сборката всъщност работи в Node
Общ „fs полифил“
Зависи от библиотеката и семантиката
Не е еквивалентен на произволен достъп до файловата система на Node
Само след потвърждаване на точното браузърно поведение, от което имате нужда
Специален случай: споделен код, импортиран от браузърни и сървърни сборки
Чест източник на тази грешка е модул с помощни функции, който съдържа както чисти функции, така и помощни функции, предназначени само за Node:
// shared-utils.js
import fs from 'node:fs'
export function formatDate(date) {
return new Intl.DateTimeFormat('en-US').format(date)
}
export function readConfig(path) {
return fs.readFileSync(path, 'utf8')
}
Дори ако вашият браузър импортира само formatDate, импорта на fs на най-високо ниво може да принуди Webpack да разреши fs. По-чист дизайн е да разделите модулите:
// shared/formatDate.js
export function formatDate(date) {
return new Intl.DateTimeFormat('en-US').format(date)
}
// server/readConfig.js
import fs from 'node:fs'
export function readConfig(path) {
return fs.readFileSync(path, 'utf8')
}
Това прави границата на средата за изпълнение видима в графа на модулите, вместо да разчита на tree-shaking или резервен вариант, за да премахне несъвместим импорт.
Специален случай: грешката се появи след надграждане от Webpack 4
Това е един от класическите симптоми на миграция към Webpack 5. Webpack 4 автоматично предоставяше съвместими подложки за много основни модули на Node. Webpack 5 намерено спря да го прави. Ако вашият код „работеше преди надграждането“, попитайте дали той наистина е имал нужда от функцията на Node в браузъра, или дали старият бандлер мълчаливо е инжектирал код за съвместимост.
Официалното ръководство за миграция на Webpack препоръчва да прочетете указанията за прекъсващи промени в грешката при сборката и да замените старата конфигурация за съвместимост node.* с по-новия подход за резолвер, където е подходящо.
Не предполагайте, че пресъздаването на всеки полифил на Webpack 4 е най-добрата миграция. Собствените бележки за изданието на Webpack препоръчват модули, съвместими с фронтенда, където е възможно.
Финална самопроверка
Преди да затворите проблема, проверете следните точки:
Намерете точния изходен файл или зависимост, която импортира fs.
Потвърдете дали засегнатата сборка работи в браузър или в Node.
Ако е браузърна сборка, проверете дали функцията наистина има нужда от поведение на файловата система.
Ако има нужда, преместете операцията с файловата система зад сървърна граница.
Ако използването на fs от зависимостта е опционално и никога не се изпълнява в браузъра, помислете за resolve.fallback: { fs: false }.
Ако пакетът официално предоставя браузърен експорт, предпочетете го пред потискането на необходимо поведение.
Ако сборката се изпълнява в Node, използвайте Node цел вместо уеб цел.
Преизградете и потвърдете, че грешката при разрешаване на модули е изчезнала.
Изпълнете действителната функция, която преди това извличаше fs; не спирайте на „компилирано успешно“.
Трайната поправка е да приведете кода в съответствие с неговата среда за изпълнение. fs принадлежи на средата за файлова система на Node. Webpack 5 прави тази граница по-видима, като вече не инжектира автоматично полифилве на основните модули на Node. След като решите дали работата с файловата система принадлежи на сървъра, е опционална в браузъра или е част от сборка с Node цел, правилната конфигурация става много по-лесна за избор.