Skip to content

Solar v0.2.1 — host build target: self-contained served bundle (no bare specifiers) #9

Description

@ClodoCapeo

Implements ADR 001 — Dual-build (docs/adr/001-dual-build-host-bundle.md, status: proposed). Refs docs/adr/001 §3.

Problem

The served bundle (/orion/static/solar/v0.2.0/, loaded by Pulsar CEF) ships bare ESM specifiers (react, react-dom/client, @preact/signals-react, @preact/signals-react/runtime, framer-motion, react/jsx-runtime, motion*) because vite.config.ts builds library mode with deps as rollupOptions.external. The CEF has no bundler and no import map → mount() never runs → black frame. This is B4, the last blocker to broadcast.

Scope (Solar repo)

  1. Add a second Vite build target — "host / standalone" (docs/adr/001 §3.1):
    • New config (e.g. vite.config.host.ts, or --mode host switch). Non-library app build. No rollupOptions.external — Rollup inlines react / react-dom / @preact/signals-react / framer-motion / motion* into the chunks.
    • Host entry that imports mount from src and bootstraps from URL params (the current build-host-html.mjs bootstrap surface: orion/token/mode/scene/session, #scene target, onError console-only).
    • Output to dist/host/** (self-contained index.html + hashed JS/CSS).
  2. Keep the library build untouched (docs/adr/001 §3.1, D2): dist/solar.js keeps externals; package.json exports map and main/module unchanged — Prism vendors this entry as-is.
  3. npm run build runs both sequentially (library, then host, then host-html reconciliation). Reconcile scripts/build-host-html.mjs: if the host app build already emits a hashed index.html importing the hashed JS, reduce/remove the script; else point it at the host bundle filename. Minimal mechanic at Forge's discretion — the invariant is the test below.
  4. Anti-bare-specifier test (docs/adr/001 §6.2): scan the built dist/host/** JS for any import/from of a non-relative / non-absolute specifier; fail on any survivor. Wire it into CI as a gate.
  5. Browser smoke test (docs/adr/001 §6.3): Playwright loads dist/host/index.html + JS in a real browser with no import map against mock-orion; assert #scene mounts and there is no unresolved-module console error.
  6. Host-bundle size budget (docs/adr/001 §4): add a host-bundle budget line to scripts/check-bundle-size.mjs (deps inlined → bigger than library; do NOT hold it to the 200/280 KiB library budgets).
  7. Bump to v0.2.1 (docs/adr/001 §3.2): package.json version → 0.2.1; CHANGELOG [0.2.1] entry (patch — served-bundle bundling fix, mount()/LSDP unchanged). meta[name=generator] reflects 0.2.1. Served path becomes /orion/static/solar/v0.2.1/.

Branch

forge/solar-host-bundle-v0.2.1

Acceptance criteria (= ADR 001 §6)

  • npm run build emits two artefacts: library entry (dist/solar.js, externals preserved) and host bundle (dist/host/**).
  • Served host JS contains zero bare ESM specifiers (asserted by test on the artefact).
  • dist/host/index.html + JS load and mount() in a real browser with no import map (Playwright/mock-orion): #scene mounts, no unresolved-module console error.
  • Prism path unaffected: import { mount } from "@zablab/solar" resolves to externals build; exports unchanged; library gzip budgets still pass.
  • package.json 0.2.1 + CHANGELOG [0.2.1] + generator meta 0.2.1.
  • CI gates: anti-bare-specifier assertion + browser smoke test green.

Out of scope

  • No change to mount() / SolarError / LSDP wire dialect (would be a minor/major, not this patch).
  • Orion serving config and Pulsar CEF URL flip: not touched here — same URL shape, new version path. Conduit validates the Orion↔Pulsar bundle contract; Keeper deploys v0.2.1.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions