Вам когда-нибудь требовалось получить с сервера некоторый контент для наполнения глобального компонента, но при этом вы понимали, что NextJS не позволяет сделать это из коробки? В проекте, над которым я работал, была глобальная навигационная панель, которая импортировалась на 202 различные страницы, но для нее требовалось предварительно сгенерированное статическое содержимое, которое поступало из CMS. Вместо того чтобы использовать getStaticProps
на каждой отдельной странице, я решил попробовать сгенерировать весь этот контент за один раз и импортировать его непосредственно в компонент.
Команда решила обойти ограничение на страницу getStaticProps
, используя процесс сборки NodeJS для получения контента из любого места, которое нам нужно, и поместить его в проект для импорта нашими компонентами в виде стандартных файлов json
. Мы даже можем сделать разные версии для dev и production окружения.
Установка
Найдите подходящее место в каталоге проекта, чтобы добавить папку preBuildScripts
(вы можете назвать ее как угодно). В моем каталоге проекта у меня есть:
src -> functions -> preBuildScripts
Если у вас одна среда, в которую вы развертываете, вам понадобится только два файла. Для каждого дополнительного окружения вам понадобится дополнительный файл для запуска. В этом примере мы создадим файлы для среды разработки и производственной среды.
Новые файлы:
preBuildUtilities.js
preBuildDev.js
preBuildProd.js
Настройка теста
Внутри вашего preBuildUtilities.js
, добавьте в этот модуль экспорт кода, который выглядит следующим образом:
module.exports.preBuildDevelopment = async() => {
console.log("Loading the development content!")
}
module.exports.preBuildProduction = async() => {
console.log("Loading the production content!")
}
Теперь внутри каждого из ваших других файлов мы можем вызвать соответствующие функции
preBuildDev.js
const {preBuildDevelopment} = require("./preBuildUtilities.js")
preBuildDevelopment();
preBuildProd.js
const {preBuildProduction} = require("./preBuildUtilities.js")
preBuildProduction();
И теперь наша настройка практически завершена! То, как мы вызываем эти функции, очень просто. NPM автоматически запускает скрипты в файле package.json
, которые имеют префикс pre
. Подробнее об этом вы можете прочитать здесь: https://docs.npmjs.com/cli/v8/using-npm/scripts#life-cycle-scripts.
Обновление файла Package.json
Откройте файл package.json
и найдите раздел scripts
, который показывает:
"scripts": {
"dev": "next dev",
"build": "next build"
}
и добавьте новый скрипт над ним, как показано ниже:
Пример множественного окружения
"scripts": {
"predev": "node src/functions/preBuildScripts/preBuildDev.js",
"dev": "next dev",
"prebuild:dev": "node src/functions/preBuildScripts/preBuildDev.js",
"build:dev": "next build",
"prebuild:prod": "node src/functions/preBuildScripts/preBuildProd.js",
"build:prod": "next build"
}
Пример одного окружения
Вот пример настройки одного окружения:
"scripts": {
"predev": "node src/functions/preBuildScripts/preBuildDev.js",
"dev": "next dev",
"prebuild": "node src/functions/preBuildScripts/preBuildDev.js",
"build": "next build"
}
Путь к папке необходимо изменить в соответствии с вашим конкретным проектом. Теперь убедитесь, что ваш сервер выключен, откройте терминал и выполните обычную команду npm run dev
. В консоли должно появиться сообщение Loading the development content!
!
Теперь, когда все готово, мы можем добавить любые функции в наш preBuildUtilities.js
.
Создание новых файлов
Внутри preBuildUtilities.js
создадим пример запроса API, который сгенерирует для нас некоторые данные в формате JSON. Представьте, что мы получаем контент из CMS и хотим заполнить компонент этими данными.
Мы можем использовать для этого API Star Wars и просто заменить эту функциональность на свою собственную. Мы просто сосредоточимся на функции preBuildDevelopment()
, но она будет следовать той же схеме для preBuildProduction()
.
Вот наши шаги по созданию скрипта предварительной сборки:
- Импортируйте пакет NodeJS File System
- Настройте наш API, используя async/await
- Создайте новый файл в проекте, используя данные JSON.
В этом примере мы будем использовать Axios, так как Fetch пока не очень широко поддерживается в NodeJS. Не стесняйтесь использовать любую систему HTTP-запросов, которая нужна вашему проекту. Это будет работать одинаково.
Примечание: Мы будем использовать синхронный метод, чтобы предотвратить любые условия гонки. Также убедитесь, что папка существует перед запуском, иначе Node может выдать ошибку, пытаясь найти нужную директорию.
const fs = require('fs');
const axios = require('axios').default;
module.exports.preBuildDevelopment = async() => {
const API = `https://swapi.dev/api/people`;
const response = await axios.get(API);
const data = response.data.results;
fs.writeFileSync("./src/data/preBuild/starWarsData.json", JSON.stringify(data))
}
Убедитесь, что ваш сервер выключен, а затем запустите его с помощью npm run dev
. После того, как сервер будет запущен, проверьте каталог файлов и посмотрите, находится ли там ваш новый JSON-файл. Надеюсь, он там есть!
Теперь в любом из ваших компонентов вы можете ссылаться на эти данные следующим образом:
StarWarsList.js
import starWarsData from "src/data/preBuild/starWarsData.json";
export const StarWarsList = () => {
return (
<ul>
{starWarsData.map((item, index) => (
<li key={`star-wars-item-${index}`}>{item.name}</li>
))}
</ul>
)
}
Теперь ваш компонент использует серверные/статические данные! 🎉