You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Ensure MDS works correctly inside the hot-reload / HMR dev workflows of every bundler we ship — Vite, Rollup, Webpack — and add first-class Rspack support. During a dev session, editing a .mds file (or any transitively @import-ed dependency) must reliably trigger a recompile and browser/app update, with compile errors surfaced in the dev overlay and cleared on the next good build.
This is a verify-and-harden task: we have the transform plumbing, but no one has exercised these plugins end-to-end against a live dev server. Where a bundler's hot-reload path is broken or unverified, we make it work.
Motivation
The mds watch CLI (#57) covers the standalone iterate-on-prompt loop. But most consumers embed MDS in a JS/TS app via a bundler plugin, where the expectation is the bundler's native HMR/watch: save a .mds, see the app update without a manual rebuild. If that path silently fails (stale module served, edit ignored, error not surfaced), the plugins look broken in exactly the workflow users live in. We ship four integration surfaces and have validated the hot path on none of them.
Current State (code audit)
Vite — packages/vite-plugin/src/index.ts
handleHotUpdate fires a full-reload on .mds change; transitive deps registered via addWatchFile in transform. Errors thrown for the Vite error overlay.
Status: wired up but unverified against a running dev server. Full-reload (not granular HMR) is an intentional v0.1.0 choice (MDS modules export plain strings — nothing to hot-swap).
Rollup — packages/rollup-plugin/src/index.ts
Deps registered via addWatchFile → rollup -w rebuilds on change. Rollup has no dev-server/HMR concept, so "hot reload" here is watch-mode rebuild.
Status: plausible but unverified; need to confirm @import dep edits re-trigger and errors don't kill the watcher.
Webpack — packages/webpack-loader/src/index.ts
Deps registered via addDependency → watch-mode recompiles. No explicit module.hot self-accept handling — behavior under webpack-dev-server HMR is unverified (may fall back to full reload, may serve stale, may warn).
Status: most likely gap.
Rspack — no package today. Rspack is webpack-loader- and Vite-plugin-compatible, so our existing loader probably loads, but it is entirely unverified, and we've committed to first-class support.
The existing __test__/plugin.spec.mjs suites validate the transform in isolation; none drive a dev server or assert HMR/watch behavior.
Scope
Hot-reload verification matrix — for each, an automated (or scripted-reproducible) dev-session smoke test:
Bundler
Mode under test
Ship today?
Vite
vite dev server (HMR)
yes
Rollup
rollup -w watch
yes
Webpack
webpack serve (HMR)
yes
Rspack
rspack serve (HMR)
new
For each: confirm (a) editing a .mds entry triggers reload, (b) editing a transitive @import dependency triggers reload, (c) a compile error is surfaced in the dev overlay/console and the watcher stays alive, (d) the next successful edit clears the error and serves fresh output.
Rspack: add first-class support. Prefer reusing the webpack-loader compat path; introduce a dedicated @mdscript/rspack package only if clean HMR integration requires it (e.g. distinct plugin hooks or builtin-loader registration). Decision to be recorded in the issue once verified.
Design Considerations
Dependency-driven invalidation: the import graph already flows through CompileOutput.dependencies → addWatchFile / addDependency. Verify it survives a dev session, not just a one-shot build, and that newly-added @imports register on the next compile.
Error resilience: a compile error during a dev session must never terminate the watcher/server. Vite throws for the overlay; Rollup uses this.error(); webpack/rspack pass the error to the loader callback — confirm each keeps the session alive and recovers.
Webpack/Rspack HMR acceptance: determine whether the emitted module needs module.hot.accept self-acceptance (or an HMR runtime hint) to avoid stale modules vs. relying on parent-module bubbling to a full reload. Pick the simplest correct behavior and document it.
Test harness: prefer programmatic dev-server APIs (Vite createServer, webpack/rspack watch + compiler.watch, rollup.watch) driven from .mjs specs so this runs in CI on ubuntu, rather than manual example apps. Example apps under examples/ are a fine secondary deliverable for docs but should not be the only verification.
Vite dev server: editing a .mds and a transitive @import each trigger a reload; errors show in the overlay and clear on recovery — covered by an automated test.
Rollup watch: .mds and @import edits re-trigger the rebuild; an error does not kill the watcher — covered by an automated test.
Webpack dev server (HMR): .mds and @import edits update the app without manual rebuild; stale-module behavior is understood and documented; errors surface and recover — covered by an automated test.
Rspack: first-class support confirmed working under rspack serve HMR (reusing webpack-loader compat or a new @mdscript/rspack package); same edit/error/recovery guarantees — covered by an automated test.
Any gaps found during verification are fixed (not just documented).
README / docs note the supported HMR behavior per bundler (full-reload vs. watch rebuild).
Out of Scope (future)
Granular HMR for Vite (hot-swapping only the importing modules instead of full-reload) — a later optimization once the module-graph integration is validated; tracked separately if pursued.
Summary
Ensure MDS works correctly inside the hot-reload / HMR dev workflows of every bundler we ship — Vite, Rollup, Webpack — and add first-class Rspack support. During a dev session, editing a
.mdsfile (or any transitively@import-ed dependency) must reliably trigger a recompile and browser/app update, with compile errors surfaced in the dev overlay and cleared on the next good build.This is a verify-and-harden task: we have the transform plumbing, but no one has exercised these plugins end-to-end against a live dev server. Where a bundler's hot-reload path is broken or unverified, we make it work.
Motivation
The
mds watchCLI (#57) covers the standalone iterate-on-prompt loop. But most consumers embed MDS in a JS/TS app via a bundler plugin, where the expectation is the bundler's native HMR/watch: save a.mds, see the app update without a manual rebuild. If that path silently fails (stale module served, edit ignored, error not surfaced), the plugins look broken in exactly the workflow users live in. We ship four integration surfaces and have validated the hot path on none of them.Current State (code audit)
packages/vite-plugin/src/index.tshandleHotUpdatefires afull-reloadon.mdschange; transitive deps registered viaaddWatchFileintransform. Errors thrown for the Vite error overlay.packages/rollup-plugin/src/index.tsaddWatchFile→rollup -wrebuilds on change. Rollup has no dev-server/HMR concept, so "hot reload" here is watch-mode rebuild.@importdep edits re-trigger and errors don't kill the watcher.packages/webpack-loader/src/index.tsaddDependency→ watch-mode recompiles. No explicitmodule.hotself-accept handling — behavior underwebpack-dev-serverHMR is unverified (may fall back to full reload, may serve stale, may warn).The existing
__test__/plugin.spec.mjssuites validate the transform in isolation; none drive a dev server or assert HMR/watch behavior.Scope
Hot-reload verification matrix — for each, an automated (or scripted-reproducible) dev-session smoke test:
vitedev server (HMR)rollup -wwatchwebpack serve(HMR)rspack serve(HMR)For each: confirm (a) editing a
.mdsentry triggers reload, (b) editing a transitive@importdependency triggers reload, (c) a compile error is surfaced in the dev overlay/console and the watcher stays alive, (d) the next successful edit clears the error and serves fresh output.Rspack: add first-class support. Prefer reusing the webpack-loader compat path; introduce a dedicated
@mdscript/rspackpackage only if clean HMR integration requires it (e.g. distinct plugin hooks or builtin-loader registration). Decision to be recorded in the issue once verified.Design Considerations
CompileOutput.dependencies→addWatchFile/addDependency. Verify it survives a dev session, not just a one-shot build, and that newly-added@imports register on the next compile.this.error(); webpack/rspack pass the error to the loader callback — confirm each keeps the session alive and recovers.module.hot.acceptself-acceptance (or an HMR runtime hint) to avoid stale modules vs. relying on parent-module bubbling to a full reload. Pick the simplest correct behavior and document it.createServer,webpack/rspackwatch +compiler.watch,rollup.watch) driven from.mjsspecs so this runs in CI on ubuntu, rather than manual example apps. Example apps underexamples/are a fine secondary deliverable for docs but should not be the only verification.mds watch: dependency tracking and error-recovery semantics should match the CLI watch behavior (feat: mds watch command (file watcher with auto-recompile) #57) so the two stories don't diverge.Acceptance Criteria
.mdsand a transitive@importeach trigger a reload; errors show in the overlay and clear on recovery — covered by an automated test..mdsand@importedits re-trigger the rebuild; an error does not kill the watcher — covered by an automated test..mdsand@importedits update the app without manual rebuild; stale-module behavior is understood and documented; errors surface and recover — covered by an automated test.rspack serveHMR (reusing webpack-loader compat or a new@mdscript/rspackpackage); same edit/error/recovery guarantees — covered by an automated test.Out of Scope (future)