Я использую популярный пакет find-up npm, у которого в качестве зависимости есть locate-path . locate-path
требует fs
в своем коде.
Когда я пытаюсь запустить свое приложение, я получаю следующее сообщение об ошибке:
[ error ] ./node_modules/locate-path/index.js
Module not found: Can't resolve 'fs' in 'C:\...\node_modules\locate-path'
Could not find files for /index in .next/build-manifest.json
Promise { <pending> }
ModuleNotFoundError: Module not found: Error: Can't resolve 'fs' in 'C:\...\node_modules\locate-path'
at factory.create (C:\...\node_modules\webpack\lib\Compilation.js:823:10)
at factory (C:\...\node_modules\webpack\lib\NormalModuleFactory.js:397:22)
at resolver (C:\...\node_modules\webpack\lib\NormalModuleFactory.js:130:21)
at asyncLib.parallel (C:\...\node_modules\webpack\lib\NormalModuleFactory.js:224:22)
at C:\...\node_modules\neo-async\async.js:2830:7
at C:\...\node_modules\neo-async\async.js:6877:13
at normalResolver.resolve (C:\...\node_modules\webpack\lib\NormalModuleFactory.js:214:25)
at doResolve (C:\...\node_modules\enhanced-resolve\lib\Resolver.js:184:12)
at hook.callAsync (C:\...\node_modules\enhanced-resolve\lib\Resolver.js:238:5)
at _fn0 (eval at create (C:\...\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:15:1)
at resolver.doResolve (C:\...\node_modules\enhanced-resolve\lib\UnsafeCachePlugin.js:37:5)
at hook.callAsync (C:\...\node_modules\enhanced-resolve\lib\Resolver.js:238:5)
at _fn0 (eval at create (C:\...\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:15:1)
at hook.callAsync (C:\...\node_modules\enhanced-resolve\lib\Resolver.js:238:5)
at _fn0 (eval at create (C:\...\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:27:1)
at resolver.doResolve (C:\...\node_modules\enhanced-resolve\lib\DescriptionFilePlugin.js:42:38)
Я создал проблему в репозитории
Клонируйте https://github.com/TidyIQ/nextjs-issue и запустите npm run dev
.
Нет проблем
Вы можете безопасно использовать fs
в getStaticProps
или getServerSideProps
, дополнительная настройка не требуется . Убедитесь, что вы ссылаетесь на переменную в жизненном цикле данных, чтобы дерево было правильно удалено.
Вы можете использовать этот инструмент, чтобы наглядно узнать, как он работает!
Если вы все еще используете устаревшую версию Next.js с getInitialProps
, прочтите ниже 👇
Предоставленный код недействителен - этот файл никогда не будет доступен на стороне клиента во время рендеринга:
Помните, что вы можете выполнять операции, связанные с FS, только когда _на сервере_. Это означает, что вы не можете использовать fs
во время рендеринга.
Если вы используете fs
, убедитесь, что это только в пределах getInitialProps
.
Вам также может потребоваться создать файл next.config.js
со следующим содержимым, чтобы получить пакет клиента для сборки:
module.exports = {
webpack: (config, { isServer }) => {
// Fixes npm packages that depend on `fs` module
if (!isServer) {
config.node = {
fs: 'empty'
}
}
return config
}
}
У меня такая же проблема с моей локальной, практически ванильной установкой, однако в примерах из nextjs это не кажется проблемой
https://github.com/zeit/next.js/tree/5787cbd9de33ea9add7cadeb04689b0d4b02976d/examples/blog-starter
что заставляет его работать там без изменения файла конфигурации?
Используйте только fs
в getStaticProps / getServerSideProps, поскольку они исключены из пакета браузера.
Я выяснил, в чем проблема. Если я импортирую функцию, которая использует fs
, но не запускаю / не использую функцию внутри getStaticProps, она в конечном итоге будет включена в пакет браузера. Как только функция будет указана внутри getStaticProps, она перестанет появляться в пакете браузера.
Я предполагаю, что есть некоторая скрытая логика, которая удаляет импорт, используемый в getStaticProps, но не используемый в основном экспорте. Я потратил несколько часов на отладку, пока не смог воспроизвести, возможно, стоит сделать заметку где-нибудь в документации :)
Разве скрытая логика не дрожит только от дерева webpack? Когда вы думаете об этом, имеет смысл, Next не импортирует getStaticProps
в пакет браузера, поэтому он удаляет импортированную функцию, используемую в нем.
Если вы нигде не ссылаетесь на него, я полагаю, что webpack считает, что вы импортировали его из-за побочных эффектов, поэтому он по-прежнему включает его в каждый пакет.
Разве скрытая логика не дрожит только от дерева webpack? Когда вы думаете об этом, имеет смысл, Next не импортирует
getStaticProps
в пакет браузера, поэтому он удаляет импортированную функцию, используемую в нем.Если вы нигде не ссылаетесь на него, я полагаю, что webpack считает, что вы импортировали его из-за побочных эффектов, поэтому он по-прежнему включает его в каждый пакет.
Нет, встряхивание дерева веб-пакетов недостаточно изощренно, чтобы встряхнуть этот экспорт таким образом. Встряхивание дерева getStaticProps / getServerSideProps / getStaticPaths обрабатывается этим настраиваемым плагином Babel, который мы создали: https://github.com/vercel/next.js/blob/canary/packages/next/build/babel/plugins/next-ssg-transform .ts
Ой, спасибо за указатель, похоже, я переоценил webpack :)
По какой причине это могло происходить из _within_ getServerSideProps
?
Всем привет. Как и @aloukissas, у меня такая же проблема при использовании dotenv
в моем index.js
getStaticProps()
. Это решается при добавлении файла next.config.js
как показано в начальном комментарии @Timer .
Есть какие-нибудь подсказки, почему это происходит? Я отменяю Next.js
v.9.4.0
Спасибо!
У меня была эта ошибка при использовании fast-glob
.
Я использовал этот отличный инструмент, чтобы понять код, который собирается на стороне клиента.
Оказалось, что я импортировал переменную из файла, который использует fast-glob
который внутренне использует fs
но я не использовал переменную где-либо внутри getStaticProps
поэтому файлы импортируют fast-glob
не исключались.
Пример:
import glob from 'fast-glob'
import path from 'path'
export const BLOG_PATH = path.join(process.cwd(), 'posts')
export const blogFilePaths = glob.sync(`${BLOG_PATH}/blog/**/*.mdx`)
import { BLOG_PATH, blogFilePaths } from './mdxUtils'
export const getStaticProps = () => {
const posts = blogFilePaths.map((filePath) => {
...
}
return { props: { posts } }
}
Как видите, я нигде не использую BLOG_PATH
в index.js
но все же импортирую его. Я использую только blogFilePaths
поэтому он дал мне эту ошибку.
Для получения дополнительной информации → https://github.com/vercel/next.js/discussions/17138
Спасибо @ deadcoder0904, это мой код:
import Layout from '../components/template'
import Main from '../components/main'
import Menu from '../components/menu'
import 'dotenv/config'
export async function getStaticProps () {
const avatarLocation = process.env.AVATAR_URL
const avatarTitle = process.env.AVATAR_TITLE
return {
props: {
avatarLocation,
avatarTitle
}
}
}
export default function RenderMainPage ({ avatarLocation, avatarTitle }) {
return (
<Layout
avatarURL={avatarLocation}
topLeft={<Menu />}
middle={<Main avatarURL={avatarLocation} avatarTitle={avatarTitle} />}
/>
)
}
Инструмент, который вы упомянули, показывает, что import 'dotenv/config'
включен в код клиента, и, вероятно, это вызывает ошибку. Дело в том, что мне нужно, чтобы он читал из переменных env.
Наверное, есть другой способ получше, я все еще изучаю Next.js :)
@ ig-perez Начиная с версии Next v9.4, у них есть встроенный способ загрузки переменных среды → https://nextjs.org/docs/basic-features/environment-variables
Предлагаю вам прочитать документацию, чтобы найти решение :)
Это здорово, я пропустил эту часть в документации, спасибо! Я обновлю свой код 👍🏽
Самый полезный комментарий
Обновление для современного Next.js (9.4+)
Вы можете безопасно использовать
fs
вgetStaticProps
илиgetServerSideProps
, дополнительная настройка не требуется . Убедитесь, что вы ссылаетесь на переменную в жизненном цикле данных, чтобы дерево было правильно удалено.Вы можете использовать этот инструмент, чтобы наглядно узнать, как он работает!
Если вы все еще используете устаревшую версию Next.js с
getInitialProps
, прочтите ниже 👇Предоставленный код недействителен - этот файл никогда не будет доступен на стороне клиента во время рендеринга:
https://github.com/TidyIQ/nextjs-issue/blob/aef67b12d91d299d0978550005a40cbb34f74b71/pages/index.js#L5
Помните, что вы можете выполнять операции, связанные с FS, только когда _на сервере_. Это означает, что вы не можете использовать
fs
во время рендеринга.Если вы используете
fs
, убедитесь, что это только в пределахgetInitialProps
.Вам также может потребоваться создать файл
next.config.js
со следующим содержимым, чтобы получить пакет клиента для сборки: