Single-file deployment
The name says "single binary" — this chapter cashes that check: config, static site, C sources and TLS certificates all packed into one exe. Copy it away and it's deployed.
Overview
48.1 Pack and run
xs ships its own packing subcommand — no external tools needed (no Python dependency):
# pack (the site directory must contain xs.json; base = the running xs itself)
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
# deploy: copy this one file to the target machine, zero-arg start
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
Compression is per-entry LZMA (auto-STORE when there is no gain) — the demo site packs 1.7 MB of text into 542 KB. Combined with the webview extension (the 14th library), the artifact becomes a double-click desktop application.
48.2 Disk priority: hot-fix without repacking
Single-file mode has exactly one file-read rule: disk wins, the pack is the fallback.
| Scenario | On-disk wwwroot/ | Result |
|---|---|---|
| Pure pack | absent | every entry served from the pack (pRoot becomes an empty path) |
| Hot-fix | empty dir + override files | override files come from disk, the rest fall back to the pack |
| Restore | override file deleted | that file automatically reverts to the packed version |
xsTlsRefresh (the hot certificate-swap API) for a fully automated renewal loop.Note: the disk-override scenario requires the wwwroot directory to exist at startup (the static root handle is opened once) — create an empty directory before launch.
48.3 Toolchain & debugging
xs pack --list app.exe # entry listing (method/size/CRC/path)
xs pack --extract app.exe -d out/ # unpack for forensics (diff = byte-identical to the source)
xs pack --strip app.exe -o orig.exe # restore the pristine binary (cmp = byte-identical)
app.exe --no-vfs # ignore the app pack, debug in directory mode
The archive format is guarded by four CRC levels (trailer → archive header → index → entry after decompression); a corrupt pack is rejected at load time. Repacking automatically strips the previous pack (stripped only after CRC confirmation, to protect unrelated binaries). The field-by-field format spec lives in the repo at docs/站点VFS设计.md.
48.4 Memory & threading model
- Index: loaded once at startup, immutable — lock-free concurrent binary search across workers
- Content: lazily decompressed on first access and cached for the process lifetime (the whole 1.7 MB demo site is the ceiling; cold files never occupy memory)
- Compressed data region: never enters memory — read by offset from the exe file, heat left to the OS file cache
- Startup cost: probing reads the last 24 bytes of itself; zero cost without a pack
Common mistakes
Exercises
Summary
pack site/ -o app.exe = single-file deployment · disk wins, the pack falls back = hot-fix without repacking · --list / --extract / --strip = built-in tooling · --no-vfs = directory-mode debugging · per-entry LZMA + four-level CRC = the format floor