pimenov.ai

Cloudflare на практике: небольшой сайт, файлы и автоматизация с Workers и R2

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

Для первого запуска достаточно готового примера и умения выполнять команды в терминале. Писать приложение с нуля не потребуется, но для изменения серверной логики пригодятся основы JavaScript. Если вы пока разбираетесь, чем Cloudflare отличается от хостинга и регистратора доменов, сначала откройте базовое руководство для новичков.

Документация и тарифы проверены 16 сентября 2026 года. Учебный пример проверен локально; размещение в аккаунте Cloudflare и доступность из сетей российских операторов в эту проверку не входили.

Содержание

  1. Что получится и за что отвечают сервисы.
  2. Что проверить пользователю из России.
  3. Полезные сценарии: сайт, библиотека файлов и обновление каталога.
  4. Подготовка и запуск на компьютере.
  5. Как связаны страница, Worker и R2.
  6. Размещение проекта в Cloudflare.
  7. Обновление файлов и страницы.
  8. Расходы, доступ и типичные ошибки.
  9. Проверка результата и дальнейшие шаги.

Что получится и за что отвечают сервисы

Соберём страницу «Материалы проекта». Посетитель открывает её, видит список документов и скачивает нужный файл. Вы добавляете материал в хранилище, и после обновления страницы он появляется в каталоге.

КомпонентЕго задачаЧто хранится или выполняется
Workers Static AssetsОтдаёт готовую страницуHTML, CSS и браузерный JavaScript
WorkerОбрабатывает запросы страницыПолучает список файлов и отдаёт выбранный документ
R2Хранит файлы отдельно от кодаДокументы, архивы, изображения и другие объекты
WranglerУправляет проектом из терминалаЛокальный запуск, загрузка объектов и размещение приложения

Workers запускает серверный код без настройки собственной виртуальной машины. Для готовой страницы используется встроенная возможность Static Assets. R2 — объектное хранилище: у каждого файла есть уникальное имя, которое называют ключом. Контейнер для объектов называется bucket; дальше будем использовать слово «бакет». Workers Static Assets, R2: начало работы.

Схема проекта:

Браузер → HTML-страница из Static Assets
        → /api/files → Worker → список объектов R2
        → /files/имя → Worker → содержимое объекта R2

Вся работа посетителя идёт через один адрес сайта. Доступ к R2 получает серверная часть через привязку ресурса — binding. Ключи доступа к хранилищу не нужно помещать в HTML или браузерный JavaScript. Привязка R2 к Worker.

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

Что проверить пользователю из России

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

До выбора Cloudflare для рабочего проекта проверьте три вещи:

  • Вы можете пользоваться аккаунтом, управлять Workers и подключить R2 на доступных вам условиях.
  • Страница, запрос списка и скачивание файла работают у предполагаемых пользователей, включая домашний и мобильный интернет.
  • У вас остаются исходники и копии файлов, чтобы перенести проект при изменении условий.

Проверяйте скачивание целиком: открывшаяся небольшая страница или ответ HTTP 200 ещё не означают, что большой документ дошёл без обрыва. Запишите дату, сеть и результат проверки. Единичный успешный тест не гарантирует дальнейшую доступность.

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

Полезные сценарии

Страница проекта с материалами для скачивания

Задача: дать участникам мероприятия или читателям одну ссылку на программу, презентацию и дополнительные документы.

Разместите страницу через Static Assets, а открытые материалы положите в R2. Worker формирует каталог и отдаёт файлы. Результат проверяется просто: другой человек открывает страницу и скачивает выбранный документ полностью.

Такой пример подходит для открытых материалов. Доступ по оплате и личные кабинеты потребуют отдельной системы авторизации.

Библиотека шаблонов, которую можно обновлять отдельно от сайта

Задача: добавлять новые таблицы, инструкции или образцы документов без изменения HTML.

Страница запрашивает список объектов у Worker. После загрузки нового файла в разрешённый раздел R2 он появляется при следующем запросе каталога. Повторно размещать код сайта для этого не нужно.

Проверка: загрузите второй тестовый файл и обновите страницу. В списке должны быть оба документа. Это автоматическое обновление списка при запросе, а не фоновая синхронизация открытого окна.

Небольшой API для другого приложения

Задача: получить тот же каталог программно, например для собственного скрипта.

Адрес /api/files возвращает JSON — структурированный текст с именем, размером и ссылкой для каждого объекта. Его можно проверить в браузере или командой curl. Учебная версия API публичная; секретных документов и персональных данных в ней быть не должно.

Подключать API из браузера другого сайта — отдельная задача: для неё потребуется продумать доступ и CORS, правила межсайтовых запросов. В нашем примере страница и API находятся на одном адресе.

Подготовка и запуск на компьютере

Шаг 1. Подготовьте папку проекта

Установите поддерживаемую LTS-версию Node.js с официального сайта. Вместе с ней устанавливается npm, менеджер пакетов. Требования к окружению сверяйте с руководством Cloudflare по запуску через CLI.

Скачайте приложенный архив cloudflare-materials-demo.zip, распакуйте его и откройте терминал в папке проекта. Внутри находятся:

cloudflare-materials-demo.zip
Учебный каталог: исходники, настройки и тестовый файл. Локально проверен с Wrangler 4.132.0.
cloudflare-materials-demo/
  public/index.html    — страница и код отображения списка
  src/index.js         — серверная логика
  wrangler.jsonc       — настройки Workers и привязки R2
  package.json         — зависимости и команды
  package-lock.json    — зафиксированные версии зависимостей
  checklist.txt        — безобидный файл для первого теста

Установите зависимости из архива:

npm ci

В архиве зафиксирована версия Wrangler, использованная при проверке примера. Для собственного проекта после обновления зависимостей повторите проверки из руководства.

Шаг 2. Добавьте файл в локальное хранилище

Из папки проекта выполните:

npx wrangler r2 object put materials-demo-files/public/checklist.txt --file=checklist.txt --local

Здесь materials-demo-files — имя бакета, а public/checklist.txt — ключ объекта. Часть public/ обозначает выбранный нами раздел для открытых материалов. В R2 это префикс имени, а не отдельная настройка прав доступа.

Флаг --local направляет команду в хранилище на вашем компьютере. Такой файл не появится в панели Cloudflare. Для облачного экземпляра ниже используется отдельная команда с --remote. Команды Wrangler для R2.

Шаг 3. Запустите проект

npm run dev

Откройте локальный адрес, который напечатает Wrangler. Обычно это http://localhost:8787. Если порт занят, ориентируйтесь на адрес в терминале.

На странице должен появиться checklist.txt. Скачайте его и сравните содержимое с исходным файлом. Затем откройте /api/files на том же адресе: вы увидите JSON со списком.

По умолчанию локальный режим Wrangler использует локальное R2. В учебной конфигурации нет remote: true, поэтому чтение файлов во время этой проверки не обращается к облачному бакету. Локальная работа R2 в Workers.

Как связаны страница, Worker и R2

Конфигурация проекта

Файл wrangler.jsonc содержит настройки целиком:

{
  "$schema": "node_modules/wrangler/config-schema.json",
  "name": "materials-demo",
  "main": "src/index.js",
  "compatibility_date": "2026-09-16",
  "workers_dev": true,
  "assets": {
    "directory": "./public",
    "binding": "ASSETS",
    // Серверный код обслуживает API и скачивание файлов.
    "run_worker_first": ["/api/*", "/files/*"]
  },
  "r2_buckets": [{
    "binding": "FILES",
    // В облаке сначала создайте bucket с этим именем.
    "bucket_name": "materials-demo-files"
  }]
}

assets.directory указывает папку страницы. Маршруты /api/* и /files/* сначала обрабатывает Worker. Через env.FILES код обращается к R2, а через env.ASSETS может получить статические файлы. Эти имена должны совпадать с binding в конфигурации. Настройка Static Assets и маршрутизации.

compatibility_date фиксирует дату совместимости среды выполнения. Это не дата публикации и не срок действия проекта.

Как получается список документов

Основная операция в обработчике /api/files:

const page = await env.FILES.list({
  prefix: 'public/',
  limit: 100,
  cursor: url.searchParams.get('cursor') || undefined,
});

Worker берёт объекты только с префиксом public/. Один ответ ограничен страницей результатов. Если R2 сообщает truncated: true, следующий запрос использует cursor; в готовом примере посетитель нажимает «Показать ещё». Проверять наличие продолжения нужно по truncated, а не по числу полученных файлов. R2 Workers API.

Страница запрашивает этот адрес обычным fetch('/api/files') и создаёт ссылки. Имена вставляются как текст, а не как HTML. Ошибка запроса выводится отдельно, чтобы недоступность API не выглядела пустым каталогом.

Как скачивается файл

Для /files/checklist.txt Worker получает объект с ключом public/checklist.txt и передаёт его содержимое посетителю. Если объекта нет, возвращается HTTP 404.

В готовом коде разрешены только чтение и проверка заголовков: методы GET и HEAD. Загрузки и удаления через публичный API нет. Ответы с файлами оформлены как вложения для скачивания; загруженный HTML не предназначен для исполнения на сайте.

⚠️
Закрытый бакет и публичная выдача файлов могут существовать одновременно. В этом примере любой посетитель сайта получает файлы из public/ через Worker. Отсутствие прямой публичной ссылки R2 не превращает каталог в защищённый архив.

Для наглядности каталог и скачивание используют Cache-Control: no-store. Пример не настраивает кэш Cloudflare и не реализует частичное скачивание по Range. Для видеоплеера, перемотки аудио или раздачи больших архивов потребуется отдельная доработка.

Размещение проекта в Cloudflare

Следующие шаги создают ресурсы в вашем аккаунте и могут приводить к расходам. Проходите их после локальной проверки и оценки доступности для своей аудитории.

Шаг 1. Подключите R2 и проверьте аккаунт

В панели Cloudflare откройте раздел R2 и пройдите подключение подписки. Бесплатный объём использования не отменяет подключения биллинга и условий оплаты. Если доступный способ оплаты не принимается, остановитесь на локальном примере; работоспособность оплаты для российских пользователей здесь не предполагается. Подключение R2.

В терминале выполните:

npx wrangler login
npx wrangler whoami

Первая команда запускает вход через браузер, вторая помогает проверить пользователя и аккаунты. Если у вас несколько аккаунтов, убедитесь, что выбрали нужный перед созданием ресурсов. Команды Wrangler.

Шаг 2. Создайте отдельный учебный бакет

npx wrangler r2 bucket create materials-demo-files

Используйте новое имя, если такое хранилище уже существует. В этом случае замените имя и в wrangler.jsonc, и в командах загрузки. Аналогично проверьте name Worker: размещение приложения с именем существующего Worker может обновить его.

Оставьте прямой публичный доступ бакета выключенным. Для этого примера не требуется включать r2.dev или подключать к бакету собственный домен: выдачу файлов выполняет Worker.

Шаг 3. Загрузите файл в облако

npx wrangler r2 object put materials-demo-files/public/checklist.txt --file=checklist.txt --remote

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

Шаг 4. Разместите приложение

npm run deploy

Команда загружает код и статические файлы проекта. Откройте адрес, который вернёт Wrangler. Для учебного запуска достаточно выданного адреса workers.dev; переносить существующий домен не нужно. Размещение Worker через CLI.

Повторите три проверки: страница открывается, /api/files возвращает список, файл скачивается полностью. Затем проверьте тот же сценарий из сетей, которыми пользуется ваша аудитория.

Обновление файлов и страницы

Новый документ без изменения сайта

Положите рядом с checklist.txt ещё один несекретный файл, например template.pdf. Загрузите его:

npx wrangler r2 object put materials-demo-files/public/template.pdf --file=template.pdf --remote

Обновите страницу. Документ должен появиться в каталоге без повторного deploy: список формируется из текущего содержимого R2.

Для локального теста замените --remote на --local. Обновляйте страницу именно локального проекта, а не облачного.

Новая версия существующего документа

Повторная загрузка по тому же ключу заменяет объект. Если старую версию нужно сохранить, используйте разные имена: guide-v1.pdf и guide-v2.pdf. Это простое правило помогает понять, какую редакцию скачал читатель.

Храните исходники отдельно от бакета. Объектное хранилище с единственным экземпляром файла не заменяет резервную копию.

Новый заголовок или оформление

Измените public/index.html, проверьте страницу через npm run dev, затем выполните npm run deploy. Файлы R2 при таком обновлении отдельно загружать не требуется.

Получается два независимых действия: размещение страницы и загрузка документов. Эту границу полезно сохранить и при дальнейшей автоматизации.

Расходы и ограничения

У проекта несколько источников расхода. Статические файлы, выполнение Worker и операции R2 учитываются по правилам соответствующих продуктов. Бесплатная выдача статических файлов не означает, что обработчики /api/files и /files/... тоже выполняются без ограничений. Тарифы Workers.

На дату проверки R2 Standard включает бесплатный месячный объём: 10 ГБ-месяцев хранения, 1 млн операций класса A и 10 млн операций класса B. Для Infrequent Access этот бесплатный объём не применяется. Исходящий трафик непосредственно из R2 не тарифицируется, но хранение и операции сверх включённого объёма оплачиваются. Тарифы R2.

В нашем примере запрос списка вызывает list, а скачивание — get. Много запросов к каталогу тоже создают нагрузку и расходуют операции. Поэтому для первого теста достаточно нескольких небольших файлов; публичную библиотеку с большим трафиком нужно проектировать с учётом кэширования и ограничения запросов.

Перед открытием проекта для широкой аудитории проверьте текущие тарифы и доступные уведомления о расходах. Не считайте уведомление гарантированным ограничителем счёта.

Доступ и безопасность

В этом примере нет регистрации пользователей. Его назначение — открытые материалы, которые вы готовы отдать любому посетителю.

  • Используйте отдельный учебный бакет без рабочих документов.
  • Загружайте в public/ только то, что можно публиковать вместе с именем файла.
  • Не помещайте токены, .env и резервные копии проекта в папку public сайта.
  • Не добавляйте открытый HTTP-метод загрузки или удаления файлов без авторизации.
  • Не принимайте пользовательские загрузки на основе этого примера без отдельной проверки форматов, размеров и прав доступа.

Привязка FILES даёт серверному коду доступ к ресурсу; разрешения посетителя определяет код приложения. Если понадобится закрытая библиотека команды, сначала спроектируйте вход пользователей и проверку прав при каждом обращении к файлу.

Что делать, если пример не работает

СимптомЧто проверитьСледующий шаг
В локальном каталоге пустоКуда загружен файл: --local или --remoteЗагрузить тестовый объект в локальное хранилище из той же папки проекта
Файл есть в R2, но отсутствует в спискеНачинается ли ключ с public/Проверить полное имя объекта
Worker сообщает об отсутствующем ресурсеСовпадают ли binding FILES и имя бакетаСверить wrangler.jsonc с аккаунтом
Видны только первые файлыЕсть ли продолжение спискаНажать «Показать ещё», проверить cursor
Вместо списка ошибкаОтвет /api/files и сообщения WranglerПроверить API отдельно от оформления страницы
Страница открылась, скачивание оборвалосьПолный размер файла и результат из другой сетиОтдельно проверить сетевую доступность; не считать это доказательством ошибки кэша
После правки заголовок прежнийБыл ли выполнен deploy и тот ли адрес открытПроверить локальную страницу, затем результат размещения

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

Проверка результата

Проект готов к дальнейшему эксперименту, когда:

  1. На странице есть первый тестовый документ.
  2. API возвращает его имя, размер и ссылку.
  3. Скачанный файл совпадает с исходным по содержимому и размеру.
  4. После загрузки второго файла каталог обновляется без повторного размещения сайта.
  5. Несуществующий файл возвращает HTTP 404.
  6. Попытка POST к API возвращает HTTP 405.
  7. Вы понимаете, какие файлы публичны, где лежат исходники и какие операции могут оплачиваться.
  8. Для облачного проекта отдельно проверена доступность у целевой аудитории.

Для возврата после неудачной правки кода сохраните предыдущую рабочую папку или версию в Git и разместите её повторно. Файлы R2 восстанавливайте из собственных копий: возврат версии Worker не отменяет изменения в хранилище.

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

Куда развивать проект

Начните с одного сценария: открытые документы мероприятия, шаблоны для читателей или материалы небольшого проекта. Не добавляйте базу данных только ради списка файлов, если достаточно объектов R2.

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

Следующий шаг

Cloudflare AI Search: как превратить сайт или набор файлов в поисковый индекс для агента — возможное продолжение, когда простой список перестанет помогать находить нужные документы.

Связанные материалы

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

Если захотите обсудить, как это применить у себя или в команде — пишите в Telegram @pimenov