Next.js: Модуль не найден: не удается разрешить "fs"

Созданный на 5 июл. 2019  ·  13Комментарии  ·  Источник: vercel/next.js

Сообщение об ошибке

Опишите ошибку

Я использую популярный пакет 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 .

Ожидаемое поведение

Нет проблем

Системная информация

  • ОС: Windows 10
  • Версия Next.js: 8.1.1-canary.67

Самый полезный комментарий

Обновление для современного 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 со следующим содержимым, чтобы получить пакет клиента для сборки:

module.exports = {
  webpack: (config, { isServer }) => {
    // Fixes npm packages that depend on `fs` module
    if (!isServer) {
      config.node = {
        fs: 'empty'
      }
    }

    return config
  }
}

Все 13 Комментарий

Обновление для современного 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 со следующим содержимым, чтобы получить пакет клиента для сборки:

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 не исключались.

Пример:

mdxUtils.js

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`)

index.js

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

Предлагаю вам прочитать документацию, чтобы найти решение :)

Это здорово, я пропустил эту часть в документации, спасибо! Я обновлю свой код 👍🏽

Была ли эта страница полезной?
0 / 5 - 0 рейтинги