Прямо сейчас у меня есть набор файлов JSON, к которым я предоставляю глобальный доступ, помещая их в конечную точку API своего веб-приложения. Благодаря этому несколько частей приложения могут использовать данные, просто отправляя запрос на выборку самому себе...
Однако, поскольку эти данные не обязательно должны быть общедоступными, я считаю, что, вероятно, есть лучший способ сделать это, поскольку веб-сайт в любом случае является единственным объектом, который должен использовать данные.
Я пытался использовать модуль fs, чтобы сделать это напрямую, но, если я не ошибаюсь, его нужно использовать на страницах, используя getStaticProps/getServerSideProps, что заставило бы меня переписать этот фрагмент кода на каждой странице, которой нужны данные, а не просто вызов подготовленной функции get-request.
Так каков правильный способ сделать это?
Я давно не использовал next, но хотел бы знать, не могли бы вы просто импортировать или потребовать json вместо использования fs
@Max, когда я попробовал это, я получаю сообщение «не могу устранить ошибку модуля». Причина, по-видимому, в том, что мое приложение пыталось использовать fs на стороне клиента, но fs можно использовать только на стороне сервера. Как мне написать функцию с использованием fs, чтобы страница, использующая информацию, отображалась на стороне сервера?
да, если вы хотите использовать fs, он должен быть на сервере, вы можете следить за nextjs.org/docs/app/building-your-application/rendering/… о том, как создать серверный компонент
но опять же, в зависимости от вашей среды, характера данных и приложения, может быть полезно импортировать файл JSON и повторно развернуть его. А поскольку вы используете next, вы можете использовать nextjs.org/docs/pages/building-your-application/data-fetching/…, чтобы регенерировать только определенные страницы в соответствии с тем, как вы их настроили. Затем вы можете просто импортировать json и передать его статическим реквизитам.






Вам следует добавить этот параметр компилятора в tsconfig.json вашего проекта.
"compilerOptions: {
"resolveJsonModule": true,
}
Затем вы можете получить строго типизированную структуру данных из файлов, которые хранятся на вашем сервере в частном порядке, но становятся частью пакета javascript...
import stuff from "./stuff.json";
Конечно, но мне нужно, чтобы он был более динамичным, новые файлы могут добавляться во время выполнения, и он должен работать для папки с файлами json, а не только для одного.
в основном, что касается разницы между использованием 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>
);
}
Затем, в конечном итоге, вы можете добавить любую логику, какую захотите, если вы хотите проверить проанализированные входные данные с помощью библиотек, вы можете это сделать.
вы все равно можете создать функцию, которая импортирует с помощью fs, и просто вызвать эту функцию, можете сделать путь или подпуть к некоторому каталогу аргументом