IPFS: каталог выпуска и относительные ссылки
Каталог выпуска должен работать после переноса к другому хранителю. Если HTML обращается к абсолютным путям основного домена, он может показать чужую текущую версию стилей вместо включённой в архив. В уроке подготовим переносимые связи между страницами и ресурсами, сохраняя точное назначение каждой ссылки.
Продолжаем course-17-edition-1. Мы не собираем сайт и не открываем его в браузере: готовим исходники и ожидаемое поведение. Указатели ROOT_CID пока не являются вычисленными значениями.
Два значения корня
Для обычного сайта путь /assets/site.css начинается от корня текущего origin. При выдаче каталога через path-шлюз выпуск может располагаться внутри /ipfs/ROOT_CID/. Тогда абсолютный путь /assets/site.css уйдёт к корню самого шлюза, а не к корню нашего выпуска.
Относительный путь assets/site.css на главной странице каталога сохраняет связь с её расположением. Для урока в подпапке понадобится ../assets/site.css. Выбор зависит от структуры файла, поэтому единая строка для всех уровней без обработки не подходит.
<!-- Фрагмент index.html в корне выпуска -->
<link rel="stylesheet" href="assets/site.css">
<a href="lessons/01-introduction.html">Первый урок</a>
Если страницу переместили в другой каталог, пути пересматриваются вместе с ней. Имя корня CID меняется при новом импорте, но относительная связь между включёнными файлами может остаться прежней.
Внутренний маршрут и внешняя ссылка
Не всякая ссылка обязана быть относительной. Ссылка на официальный справочник остаётся обычным внешним URL. Ссылка на страницу оплаты библиотеки тоже может вести к основному сайту: эта функция зависит от серверного состояния и не входит в статический архив.
Важно назвать различие. Внутренние ссылки должны приводить к файлам этого выпуска; внешние — явно обращаться к независимому сервису. Если кнопка «следующий урок» ведёт на текущую статью основного домена, читатель покидает объявленную версию и может получить обновлённый текст.
Для архива библиотеки составляем опись внутренних переходов. Удалённый урок не заменяется текущим аналогом без обозначения. Если файл отсутствует, выдача сообщает ограничение выпуска. Это сохраняет понятный договор содержания.
Ресурсы и скрытые зависимости
CSS может загружать шрифт через url(...), а HTML — картинку, скрипт или данные с внешнего домена. Если эти зависимости изменяются, визуальный или функциональный результат выпуска также меняется. CID одного HTML при этом остаётся прежним.
Для стабильного учебного набора включаем критические локальные ресурсы или объявляем внешние зависимости в манифесте. Данные динамического API не превращаются в неизменные от того, что запрос расположен в адресуемом файле. Это отдельная услуга с собственной свежестью и доверием.
Особенно аккуратно используем клиентские скрипты. Неизменный вредоносный код не становится безопасным благодаря правильной проверке CID. Политика разрешённых зависимостей и origin-изоляция остаются необходимыми; подробности появятся в следующих уроках.
Пути и имена
Выбираем устойчивые имена файлов в нижнем регистре для нашего набора. Если исходная система различает регистр иначе, ошибка может быть незаметна локально и проявиться после импорта. Site.css и site.css не следует считать одинаковыми без установленного правила.
Имена с пробелами и Unicode требуют правильного URL-кодирования. Нельзя вставить произвольное имя в ссылку без обработки и рассчитывать на одинаковую интерпретацию всех шлюзов. В манифесте сохраняются точные пути, а HTML формируется безопасным генератором.
Выход за пределы каталога через ../ также зависит от положения страницы. Для вложенного урока один шаг вверх нужен к ресурсам выпуска. Несколько лишних шагов могут привести к другому контексту path-шлюза. Поэтому структура должна быть очевидной, а генерация ссылок — связанной с известным местом файла.
Страница ошибки и SPA
Если выпуск представляет набор отдельных HTML, каждый путь имеет собственный файл. Если используется одностраничное приложение, обычный переход на виртуальный маршрут может требовать серверного fallback. Шлюз не обязан повторять настройки вашего привычного хостинга.
Для первой библиотеки выберем настоящие статические страницы. Это соответствует задачам учебного архива и упрощает перенос. Если позже нужен SPA-маршрут, профиль явно описывает поддерживаемый способ навигации и ожидаемую обработку неизвестного пути. Не предполагаем, что любой шлюз выдаст index.html для произвольного адреса.
Внутренние якоря остаются частью HTML. Переход #example не требует отдельного IPFS-объекта, но идентификатор должен существовать в этой странице. Изменение структуры заголовков в новом выпуске не исправляет старый архив задним числом.
Вложенный урок и перенос корня
Откроем lessons/01-introduction.html в составе выпуска. Ссылка ../assets/site.css разрешается относительно расположения этого урока и ведёт к стилю того же каталога. Ссылка /assets/site.css начинается с корня HTTP-origin и может обращаться совсем к другому ресурсу, если выпуск выдан через путь /ipfs/ROOT_CID/. Поэтому одна и та же строка HTML на разных способах выдачи способна иметь разное окружение. CID гарантирует байты строки, а правила URL определяют её дальнейшее действие.
Для нашего статического набора заранее выбираем переносимую структуру относительных ссылок. Оглавление ссылается на lessons/01-introduction.html, урок — на ../index.html, локальные ресурсы — на соответствующее относительное положение. Нельзя механически добавить ../ ко всем ссылкам: глубина папок различается, а некоторые адреса сознательно ведут к внешней услуге. Каждая категория имеет свою роль в выпуске.
Теперь перенесём ту же копию к другому хранителю. При сохранённых путях внутренние переходы должны остаться внутри того же объявленного набора; внешняя ссылка оплаты продолжает обращаться к обычному серверу библиотеки. Если новый хранитель по-своему обрабатывает отсутствующие пути, это не исправляет ошибку в самом HTML. Ответ с оглавлением вместо неизвестного урока способен скрыть дефект навигации и выдать успешный HTTP-статус для неправильного содержания.
Отдельно описываем входной документ и поведение адреса без завершающей косой черты. Шлюз может применять перенаправление при работе с каталогом; приложение не должно строить адреса на случайном поведении одного сервиса. В будущую опись навигации входят существующие пути, требуемые ресурсы и явно внешние адреса. Ожидаемый результат — переносимость учебного выпуска, а не создание универсального сервера для произвольной веб-программы.
Переносимый результат
Опишем ожидаемый разбор: открывается корневая страница, затем вложенный урок, загружается включённый CSS, а ссылка на оплату явно уводит к основному домену. При смене хранителя внутренние переходы сохраняются, поскольку связывают файлы одного каталога.
Сейчас этот маршрут не исполнялся. Мы готовим критерии для будущего просмотра после отдельного разрешения. В опись входят пути, внешние зависимости и правила отсутствующего файла. Она позволяет другому разработчику понять границы статического выпуска без догадок о настройках сервера.
Структуры выдачи описаны в документации шлюзов и правилах Path Gateway. После урока каталог можно перемещать, сохраняя внутренний смысл ссылок. Следующим шагом объявим его состав через манифест.