Глава 48 / 51
Том 5 · Расширения, эксплуатация и проекты

Публикация одним файлом

В названии xs сказано «один файл» — эта глава выполняет обещание: конфигурация, статический сайт, исходники на C и TLS-сертификаты упаковываются в один exe. Скопировали — развернули.

Введение

Место главы: финал всех форм развёртывания. Все приложения из предыдущих глав (xs.json + исходники + wwwroot + сертификаты) здесь сходятся в один файл — сайтовый VFS (пакет приложения) дописывается в конец бинарника xs и автоматически распознаётся при запуске без аргументов. Вывод с пометкой проверено на реальном запуске получен исполнением упакованного exe.

48.1 Упаковка и запуск

В xs встроена собственная команда упаковки — внешние инструменты не нужны (зависимости от Python нет):

Реальный запуск · pack в три шага
# упаковка (в каталоге сайта должен лежать xs.json; база = сам запущенный xs)
xs.exe pack site/ -o app.exe
[pack] base 6202368 bytes + 30 files, compressing...
[pack] 30/30 compressed
[pack] app.exe: 30 entries (lzma 28, store 2), archive 575363 bytes

# развёртывание: копируем один файл на целевую машину, запуск без аргументов
app.exe
[xs] app pack: 30 entries
[xs] config loaded: app-pack:xs.json (1 servers)
[xs] http host 'site' static root '...\wwwroot' on disk missing, serving from app pack

Сжатие — LZMA на каждый элемент (без выигрыша автоматический STORE): демо-сайт 1,7 МБ текста упаковывается в 542 КБ. В сочетании с расширением webview (14-я библиотека) продукт превращается в «настольное приложение по двойному щелчку».

48.2 Приоритет диска: горячее исправление без перепаковки

В однофайловом режиме правило чтения файлов одно: диск побеждает, пакет — запасной вариант.

Сценарийwwwroot/ на дискеРезультат
Только пакетотсутствуетвсе элементы отдаются из пакета (pRoot — пустой путь)
Горячее исправлениепустой каталог + файлы-переопределенияфайлы-переопределения с диска, остальное — из пакета
Возвратфайл-переопределение удалёнфайл автоматически возвращается к версии из пакета
Сертификаты работают так же: после продления положите новый cert.pem рядом с exe — он вступит в силу; чтение по путям идёт через единый выход (сначала диск, потом пакет), поэтому запись файла естественно отменяет устаревшую копию из пакета. Вместе с xsTlsRefresh (API горячей замены сертификатов) получается полностью автоматический цикл продления.

Замечание: сценарий переопределения с диска требует, чтобы каталог wwwroot существовал на момент старта (дескриптор статического корня открывается один раз) — заранее создайте пустой каталог.

48.3 Инструменты и отладка

Реальный запуск · четыре команды pack
xs pack --list app.exe            # список элементов (метод/размер/CRC/путь)
xs pack --extract app.exe -d out/  # распаковка (diff побайтово совпадает с исходным)
xs pack --strip app.exe -o orig.exe # восстановить исходный бинарник (cmp побайтово равен)
app.exe --no-vfs                   # игнорировать пакет, отладка в режиме каталогов

Формат архива защищён четырьмя уровнями CRC (концевой маркер → заголовок архива → индекс → элемент после распаковки); повреждённый пакет отвергается при загрузке. Повторная упаковка автоматически снимает старый пакет (после проверки CRC, чтобы не задеть посторонние бинарники). Пословная спецификация формата — в репозитории, docs/站点VFS设计.md.

48.4 Модель памяти и потоков

  • Индекс: загружается один раз при старте, неизменяем — конкурентный бинарный поиск без блокировок во всех worker'ах
  • Содержимое: ленивая распаковка при первом обращении, кэш на всё время жизни процесса (потолок — весь демо-сайт 1,7 МБ; холодные файлы памяти не занимают)
  • Область сжатых данных: в память не попадает — читается по смещению из файла exe, «температуру» держит файловый кэш ОС
  • Цена старта: проба читает последние 24 байта самого себя; без пакета — нулевые накладные расходы

Типичные ошибки

Грабли: переопределение с диска не работаетКаталог wwwroot должен существовать на момент старта (дескриптор статического корня открывается один раз) — сделайте mkdir пустого каталога до запуска, и только тогда файлы, появившиеся во время работы, станут видны дисковому слою.
Грабли: после перепаковки размер удвоилсяpack автоматически снимает старый пакет, но если у базового exe пакет с непрошедшим CRC, он считается безпакетным — сначала восстановите через --strip либо убедитесь, что база — чистый артефакт сборки.
Грабли: dev_inc не находит заголовкиЗаголовки из пакета монтируются под виртуальным корнем /xs/site/<относительный путь>; абсолютные пути dev_inc автоматически очищаются от префикса appPath и отображаются — проверьте, что пути элементов в pack --list совпадают с конфигурацией (регистр важен).

Упражнения

База
Упакуйте статический сайт из тома 2, проверьте число элементов через --list, затем --strip и сравнение cmp побайтово.
Продвинутый
После упаковки положите рядом с exe переопределяющий index.html и пройдите три сценария: приоритет диска и восстановление удалением.
Зачёт
Упакуйте самоподписанный сертификат openssl, поднимите https и проверьте curl -k, что сертификат распакован из пакета (подсказка: глава 12).

Итоги

pack site/ -o app.exe = развёртывание одним файлом · диск побеждает, пакет запасной = горячее исправление без перепаковки · --list / --extract / --strip = встроенные инструменты · --no-vfs = отладка в режиме каталогов · LZMA по элементам + четыре уровня CRC = нижняя планка формата