При создании статически генерируемого сайта (SSG-сайта) с помощью Next.js или любого другого SSG-фреймворка, такого как Hugo, Gatsby, Jekyll или Nuxt, вы можете столкнуться с необходимостью размещения сгенерированных статических файлов на FTP-сервере. Будь то ваше собственное решение или требование клиента, эта статья покажет вам, как это сделать. Наша цель — создать сценарий, который позволит вам просто запустить один-единственный npm-скрипт для сборки и развертывания проекта на FTP-сервере.
$ npm run deploy
Какой контент вы можете разместить?
Используя этот метод, вы можете размещать любые статические сайты, которые состоят из статического HTML, JavaScript и CSS файлов, или других статических активов. Статические страницы могут быть написаны вручную с нуля или сгенерированы с помощью любого фреймворка SSG. Любой динамический контент должен быть либо получен на стороне клиента, либо сайт должен быть регенерирован и развернут при изменении контента.
В этой статье я буду использовать Next.js в качестве примера. Если вы не используете Next.js, в статье будут указаны те шаги, которые необходимо адаптировать к вашему собственному фреймворку.
Что такое FTP?
Вам понадобится FTP-сервер. FTP расшифровывается как File Transfer Protocol, что по сути похоже на HTTP, но для передачи файлов между компьютерами. Подробнее о FTP вы можете прочитать здесь. Вы можете подключиться к удаленному FTP-серверу напрямую с помощью FTP-клиента, такого как FileZilla или Commander One. Они предоставляют графический интерфейс пользователя для ручной загрузки и выгрузки файлов. Хотя вы, конечно, можете использовать FTP-клиент, наша цель — написать скрипт, который позволит загрузить весь ваш проект на FTP-сервер с помощью одной единственной команды: npm run deploy
.
Шаг 1: Создайте свой проект
Давайте начнем с инициализации пустого скрипта deploy
в нашем package.json
.
{
...
"scripts": {
...
"deploy": ""
},
...
}
Первым шагом для нашего скрипта развертывания является сборка проекта в статические файлы. Используя Next.js, мы должны выполнить две команды: next build
и next export
. В случае с Next.js он по умолчанию сгенерирует наши экспортированные статические файлы в каталог /out
.
Давайте запишем их в качестве первых инструкций для нашего сценария развертывания.
"scripts": {
"deploy": "next build && next export"
}
Для других фреймворков: Замените next build && next export
на любую команду, которая собирает ваш проект в статические файлы в некоторую выходную директорию, например npm run build
. Для проектов, где этап сборки не требуется (ручная запись статических файлов), этот шаг можно пропустить.
Шаг 2: Настройка пользовательского сценария JavaScript для развертывания
Создайте директорию /scripts
, где мы создадим файл: deploy.js
для развертывания. (Примечание: если у вас возникнут проблемы с запуском скрипта, попробуйте изменить тип файла на deploy.mjs
).
Давайте пока инициализируем его пустой асинхронной главной функцией.
async function main() {
return 0;
}
main().then(code => process.exit(code));
Этот сценарий развертывания будет обрабатывать все остальные процедуры развертывания после того, как мы соберем проект, поэтому мы можем подключить его к сценарию npm, чтобы завершить его следующим образом.
"scripts": {
"deploy": "next build && next export && node ./scripts/deploy.js"
}
Шаг 3: Создайте файл .env с учетными данными FTP
Вам понадобятся учетные данные для подключения к FTP-серверу. Давайте сохраним хост FTP, порт, имя пользователя и пароль в файле .env
для дальнейшего использования. Порт 21 обычно используется для FTP.
FTP_USER=your-username-here
FTP_PASS=your-password-here
FTP_HOST=your.hostname.here
FTP_PORT=21
Шаг 4: Разработка сценария развертывания
Давайте начнем с установки зависимостей, необходимых для сценария, выполнив команду
$ npm i -D dotenv ftp-deploy
И импортируйте их в верхнюю часть сценария
import dotenv from "dotenv";
import FtpDeploy from "ftp-deploy";
dotenv.config({ path: "./.env" });
И давайте заполним скрипт развертывания. Большую часть тяжелой работы выполнит ftp-deploy
. Не стесняйтесь изменять любые настройки для развертывания, чтобы лучше соответствовать вашим потребностям. Эту конфигурацию я использовал для загрузки всех файлов сборки Next.js в корень FTP-сервера.
import dotenv from "dotenv";
import FtpDeploy from "ftp-deploy";
dotenv.config({ path: "./.env" });
async function main() {
try {
// Replace "/out" with your build directory which contains all generated static files
const outDir = path.join(process.cwd(), "/out");
await new FtpDeploy().deploy({
user: process.env.FTP_USER, // Your credentials
password: process.env.FTP_PASS, // Your credentials
host: process.env.FTP_HOST, // Your credentials
port: process.env.FTP_PORT, // Your credentials
localRoot: outDir, // Location of build files in project
remoteRoot: "/", // Upload location on remote, replace with subfolder on FTP-server if required
include: ["*", "**/*"], // Upload all files from build folder
exclude: [], // Exclude no files
deleteRemote: false, // Set to true if you want to delete ALL FILES in the remote root before uploading
forcePasv: true // Use passive mode
})
console.log("Succesfully deployed site")
return 0;
} catch (e) {
console.error("An error occured during deployment:", e);
return 1;
}
}
main().then((code) => process.exit(code));
Вы закончили.
Теперь запуск npm run deploy
соберет ваш проект в статические файлы и автоматически загрузит эти статические файлы.
Потенциальные проблемы
Клиент хочет обновлять сайт самостоятельно
Клиент может обновить часть контента, используемого на сайте, который используется на этапе сборки. В этом случае на сайте будут отображаться старые данные, и его необходимо будет развернуть заново. Один из довольно ручных способов решения этой проблемы — дать клиенту возможность самостоятельно обновлять сайт, используя тот же скрипт обновления. Это займет некоторое время для правильной настройки, но может сэкономить много времени в дальнейшем.
- Установите
git
,node
иnpm
на компьютер клиента. - Добавьте их в репозиторий GitHub проекта в качестве соавтора (в настройках, затем соавторы).
- Обновите сценарий развертывания, включив
git pull
иnpm i
в начало, чтобы он выглядел как"deploy": "git pull && npm i && next build && next export && node ./scripts/deploy.js"
. Это позволит клиенту всегда иметь последнюю версию проекта и правильные зависимости, установленные перед развертыванием. - Клонируйте репозиторий на машину клиента с помощью
git clone https://github.com/username/reponame.git
. - Добавьте правильные учетные данные в файл
.env
в проекте. - Перепишите любой файл сценария на компьютере клиента в доступное место, назовите его как-нибудь понятно, например
Update Project.bat
. Файл сценария должен делать две вещи: 1. перейти в корень проекта и 2. запуститьnpm run deploy
.
После этой установки ваш клиент может свободно обновлять любые данные, связанные с сайтом, например, на безголовой CMS, а после обновления он может нажать Update Project.bat
, что приведет (с его точки зрения) к запуску магического кода, и сайт будет обновлен. Теперь все, что вам нужно сделать, это убедиться, что клиент не изменяет ни один из файлов в каталоге проекта, чтобы облегчить вам жизнь, и взаимодействовать с проектом только путем запуска скрипта обновления.
В качестве альтернативы вы можете предоставить облачный компьютер, который будет делать то же самое при вызове через webhook (который запускается при любом обновлении источников данных клиента) для автоматического обновления сайта без какого-либо взаимодействия с клиентом. Однако это обойдется вам дороже, чем предыдущий вариант за $0.
Старые неиспользуемые файлы остаются на FTP-сервере
Если на FTP-сервере в вашем remoteRoot
нет других файлов, вы можете использовать опцию deleteRemote: true
, чтобы стереть все предыдущие файлы при развертывании новых файлов. Если вы не можете этого сделать, вам нужно либо написать пользовательскую логику в скрипте для удаления предыдущих файлов, либо вручную периодически удалять неиспользуемые файлы, либо оставить их как есть.