Cloudflare на практике: небольшой сайт, файлы и автоматизация с Workers и R2
Не удалось запустить аудио. Нажмите кнопку воспроизведения в плеере.
Cloudflare Workers и R2 позволяют собрать небольшой сайт с каталогом документов, вынести файлы в отдельное хранилище и обновлять список материалов без ручного редактирования страницы. В этом руководстве разберём эти задачи на одном учебном проекте, который можно приспособить под портфолио, страницу курса или набор открытых шаблонов.
Для первого запуска достаточно готового примера и умения выполнять команды в терминале. Писать приложение с нуля не потребуется, но для изменения серверной логики пригодятся основы JavaScript. Если вы пока разбираетесь, чем Cloudflare отличается от хостинга и регистратора доменов, сначала откройте базовое руководство для новичков.
Документация и тарифы проверены 16 сентября 2026 года. Учебный пример проверен локально; размещение в аккаунте Cloudflare и доступность из сетей российских операторов в эту проверку не входили.
Содержание
- Что получится и за что отвечают сервисы.
- Что проверить пользователю из России.
- Полезные сценарии: сайт, библиотека файлов и обновление каталога.
- Подготовка и запуск на компьютере.
- Как связаны страница, Worker и R2.
- Размещение проекта в Cloudflare.
- Обновление файлов и страницы.
- Расходы, доступ и типичные ошибки.
- Проверка результата и дальнейшие шаги.
Что получится и за что отвечают сервисы
Соберём страницу «Материалы проекта». Посетитель открывает её, видит список документов и скачивает нужный файл. Вы добавляете материал в хранилище, и после обновления страницы он появляется в каталоге.
| Компонент | Его задача | Что хранится или выполняется |
| 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/
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 и тот ли адрес открыт | Проверить локальную страницу, затем результат размещения |
Если локальная версия работает, а облачная нет, сравните конфигурацию и содержимое двух хранилищ. Это разные экземпляры данных.
Проверка результата
Проект готов к дальнейшему эксперименту, когда:
- На странице есть первый тестовый документ.
- API возвращает его имя, размер и ссылку.
- Скачанный файл совпадает с исходным по содержимому и размеру.
- После загрузки второго файла каталог обновляется без повторного размещения сайта.
- Несуществующий файл возвращает HTTP 404.
- Попытка POST к API возвращает HTTP 405.
- Вы понимаете, какие файлы публичны, где лежат исходники и какие операции могут оплачиваться.
- Для облачного проекта отдельно проверена доступность у целевой аудитории.
Для возврата после неудачной правки кода сохраните предыдущую рабочую папку или версию в Git и разместите её повторно. Файлы R2 восстанавливайте из собственных копий: возврат версии Worker не отменяет изменения в хранилище.
После эксперимента ненужные облачные ресурсы можно удалить через панель, предварительно выгрузив нужные файлы и проверив имя бакета. Удаление ресурсов не отменяет уже начисленные расходы.
Куда развивать проект
Начните с одного сценария: открытые документы мероприятия, шаблоны для читателей или материалы небольшого проекта. Не добавляйте базу данных только ради списка файлов, если достаточно объектов R2.
Если понадобятся названия, описания, сортировка и редакционные статусы, следующий шаг — отдельный каталог метаданных. Если нужен закрытый доступ, начните с авторизации. Для поиска по содержимому документов потребуется поисковый сервис. Это разные задачи; готовый список файлов их сам по себе не решает.
Следующий шаг
Cloudflare AI Search: как превратить сайт или набор файлов в поисковый индекс для агента — возможное продолжение, когда простой список перестанет помогать находить нужные документы.
Связанные материалы
- Статья: Cloudflare OS: как компания собрала внутренний ИИ-воркспейс и раздала его всем сотрудникам.
- Блог: Что можно собрать на Cloudflare в 2026 году: десять практических руководств.
- База знаний: Cloudflare для новичков: что это, зачем нужен и как подключить сайт.
Если вы выбираете, где разместить небольшой проект и хранить его материалы, можно обсудить подходящую схему с учётом аудитории и ограничений.
Если захотите обсудить, как это применить у себя или в команде — пишите в Telegram @pimenov