Как правильно использовать файлы JSON, хранящиеся на стороне сервера в Next.js?

Прямо сейчас у меня есть набор файлов JSON, к которым я предоставляю глобальный доступ, помещая их в конечную точку API своего веб-приложения. Благодаря этому несколько частей приложения могут использовать данные, просто отправляя запрос на выборку самому себе...

Однако, поскольку эти данные не обязательно должны быть общедоступными, я считаю, что, вероятно, есть лучший способ сделать это, поскольку веб-сайт в любом случае является единственным объектом, который должен использовать данные.

Я пытался использовать модуль fs, чтобы сделать это напрямую, но, если я не ошибаюсь, его нужно использовать на страницах, используя getStaticProps/getServerSideProps, что заставило бы меня переписать этот фрагмент кода на каждой странице, которой нужны данные, а не просто вызов подготовленной функции get-request.

Так каков правильный способ сделать это?

вы все равно можете создать функцию, которая импортирует с помощью fs, и просто вызвать эту функцию, можете сделать путь или подпуть к некоторому каталогу аргументом

Max 10.05.2024 18:54

Я давно не использовал next, но хотел бы знать, не могли бы вы просто импортировать или потребовать json вместо использования fs

Max 10.05.2024 18:56

@Max, когда я попробовал это, я получаю сообщение «не могу устранить ошибку модуля». Причина, по-видимому, в том, что мое приложение пыталось использовать fs на стороне клиента, но fs можно использовать только на стороне сервера. Как мне написать функцию с использованием fs, чтобы страница, использующая информацию, отображалась на стороне сервера?

willaayy 12.05.2024 15:02

да, если вы хотите использовать fs, он должен быть на сервере, вы можете следить за nextjs.org/docs/app/building-your-application/rendering/… о том, как создать серверный компонент

Max 12.05.2024 16:44

но опять же, в зависимости от вашей среды, характера данных и приложения, может быть полезно импортировать файл JSON и повторно развернуть его. А поскольку вы используете next, вы можете использовать nextjs.org/docs/pages/building-your-application/data-fetchin‌​g/…, чтобы регенерировать только определенные страницы в соответствии с тем, как вы их настроили. Затем вы можете просто импортировать json и передать его статическим реквизитам.

Max 12.05.2024 16:54
Зод: сила проверки и преобразования данных
Зод: сила проверки и преобразования данных
Сегодня я хочу познакомить вас с библиотекой Zod и раскрыть некоторые ее особенности, например, возможности валидации и трансформации данных, а также...
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Мне нравится библиотека Mantine Component , но заставить ее работать без проблем с Remix бывает непросто.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
TypeScript против JavaScript
TypeScript против JavaScript
TypeScript vs JavaScript - в чем различия и какой из них выбрать?
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Не все нужно хранить на стороне сервера. Иногда все, что вам нужно, это постоянное хранилище на стороне клиента для хранения уникальных для клиента...
Что такое ленивая загрузка в Angular и как ее применять
Что такое ленивая загрузка в Angular и как ее применять
Ленивая загрузка - это техника, используемая в Angular для повышения производительности приложения путем загрузки модулей только тогда, когда они...
0
5
242
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вам следует добавить этот параметр компилятора в tsconfig.json вашего проекта.

    "compilerOptions: {
       "resolveJsonModule": true,
    }

Затем вы можете получить строго типизированную структуру данных из файлов, которые хранятся на вашем сервере в частном порядке, но становятся частью пакета javascript...

    import stuff from "./stuff.json";

Конечно, но мне нужно, чтобы он был более динамичным, новые файлы могут добавляться во время выполнения, и он должен работать для папки с файлами json, а не только для одного.

willaayy 12.05.2024 14:58
Ответ принят как подходящий

в основном, что касается разницы между использованием fs и import/require, я думаю, если вы не хотите перестраивать каждый раз при изменении файла, вам следует использовать fs.

Что касается абстрагирования поведения, я думаю, вы могли бы создать функцию так, как вам нужно, начиная с примера на https://vercel.com/guides/loading-static-file-nextjs-api-route.

import { promises as fs } from 'fs';

export default async function Page() {
  const file = await fs.readFile(process.cwd() + '/app/data.json', 'utf8');
  const data = JSON.parse(file);

  return (
    <div>
      <h1>{data.title}</h1>
      <p>{data.content}</p>
    </div>
  );
}

В любом месте вы можете определить

const myReadFile = async (path: string) => {
  const file = await fs.readFile(process.cwd() + path, "utf8");
  const data = JSON.parse(file);
  return data;
};

И может вызвать его в любом компоненте

export default async function Page() {
  const data = myReadFile("/app/data.json");

  return (
    <div>
      <h1>{data.title}</h1>
      <p>{data.content}</p>
    </div>
  );
}

От символа к символу вы, возможно, не сильно сэкономите, но все равно полезно избегать переписывания одного и того же, и в этом случае, вероятно, нет недостатков.

И вы можете расширить функцию тем, что хотите. Если вы хотите добавить типы для того, что должно быть проанализировано, вы можете добавить общий тип, который вы укажете вручную.

const myReadFileTyped = async <T,>(path: string): Promise<T> => {
  const file = await fs.readFile(process.cwd() + path, "utf8");
  const data: T = JSON.parse(file);
  return data;
};

затем

type Data = {title:string, content:string};
const data = await myReadFileTyped<Data>("/app/data.json")

и используйте данные в своем компоненте.

Если вы хотите перехватывать ошибки и возвращать null или что-то еще в исключениях, вы можете сделать

const myReadFileSafe = async <T,>(path: string): Promise<T | null> => {
  try {
    const file = await fs.readFile(process.cwd() + path, "utf8");
    const data: T = JSON.parse(file);
    return data;
  } catch (e) {
    console.info(e);
    return null;
  }
};

а потом

export default async function Page() {
  const data = await myReadFileSafe("/app/data.json");

  if (data === null) {
    return null;
  }

  return (
    <div>
      <h1>{data.title}</h1>
      <p>{data.content}</p>
    </div>
  );
}

Затем, в конечном итоге, вы можете добавить любую логику, какую захотите, если вы хотите проверить проанализированные входные данные с помощью библиотек, вы можете это сделать.

Другие вопросы по теме