Размещение статического сайта на FTP-сервере на примере Next.js

При создании статически генерируемого сайта (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 соберет ваш проект в статические файлы и автоматически загрузит эти статические файлы.

Потенциальные проблемы

Клиент хочет обновлять сайт самостоятельно

Клиент может обновить часть контента, используемого на сайте, который используется на этапе сборки. В этом случае на сайте будут отображаться старые данные, и его необходимо будет развернуть заново. Один из довольно ручных способов решения этой проблемы — дать клиенту возможность самостоятельно обновлять сайт, используя тот же скрипт обновления. Это займет некоторое время для правильной настройки, но может сэкономить много времени в дальнейшем.

  1. Установите git, node и npm на компьютер клиента.
  2. Добавьте их в репозиторий GitHub проекта в качестве соавтора (в настройках, затем соавторы).
  3. Обновите сценарий развертывания, включив git pull и npm i в начало, чтобы он выглядел как "deploy": "git pull && npm i && next build && next export && node ./scripts/deploy.js". Это позволит клиенту всегда иметь последнюю версию проекта и правильные зависимости, установленные перед развертыванием.
  4. Клонируйте репозиторий на машину клиента с помощью git clone https://github.com/username/reponame.git.
  5. Добавьте правильные учетные данные в файл .env в проекте.
  6. Перепишите любой файл сценария на компьютере клиента в доступное место, назовите его как-нибудь понятно, например Update Project.bat. Файл сценария должен делать две вещи: 1. перейти в корень проекта и 2. запустить npm run deploy.

После этой установки ваш клиент может свободно обновлять любые данные, связанные с сайтом, например, на безголовой CMS, а после обновления он может нажать Update Project.bat, что приведет (с его точки зрения) к запуску магического кода, и сайт будет обновлен. Теперь все, что вам нужно сделать, это убедиться, что клиент не изменяет ни один из файлов в каталоге проекта, чтобы облегчить вам жизнь, и взаимодействовать с проектом только путем запуска скрипта обновления.

В качестве альтернативы вы можете предоставить облачный компьютер, который будет делать то же самое при вызове через webhook (который запускается при любом обновлении источников данных клиента) для автоматического обновления сайта без какого-либо взаимодействия с клиентом. Однако это обойдется вам дороже, чем предыдущий вариант за $0.

Старые неиспользуемые файлы остаются на FTP-сервере

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

Оцените статью
devanswers.ru
Добавить комментарий