Component re-exported from a .ts module breaks hydration in production builds (crash with a sibling event handler, silently dead without)
[!NOTE] Issue text and repro written by Claude (AI); every result personally verified by me in a real browser.
Using a component that is re-exported from a TypeScript file breaks client hydration — but only in production builds (marko-run build). The dev server is fine.
Repro repo: https://github.com/svallory/marko-run-dynamic-tag-repro — the whole app is three files:
// src/manifest.ts
export { default as Demo } from "./demo.marko";// src/demo.marko
<let/count=0>
<button onClick() { count++ }>Button (clicked ${count} times)</button>// src/routes/+page.marko
import { Demo } from "../manifest.ts";
<Demo/>
<button onBlur=() => {}>another button</button>bun run build && bun run start, open /. Two scenarios:
- Just
<Demo/>(remove the second button): no error — but the Demo button is dead. No client bundle is emitted for the route at all (0.0 kB). - With any other tag carrying an event handler (an inert
onBlur=() => {}is enough): the console throws on load and nothing hydrates:
TypeError: effects[(i++)] is not a function
at runEffects
at runResumeEffects
at init
at initEmbedded(stack from a minify: false + sourcemaps build — the crash is identical minified)
One-line fix/workaround: import the component directly — import Demo from "../demo.marko"; — identical HTML, everything hydrates.
Scenario 2 reproduces without @marko/run: the repo's plain/ variant (plain @marko/vite, ~25-line build+serve harness) throws the identical error — which is why this is filed here rather than at marko-js/run (originally marko-js/run#266, closed in favor of this issue). Scenario 1 (silently emitting no client bundle) is the @marko/run-specific symptom of the same import shape. Neither reproduces in the dev server or the Marko playground (unoptimized compiles).
Versions (all verified): marko 6.3.35 and 6.3.45 (latest), @marko/run 0.11.9 and 0.11.12 (latest), @marko/vite 6.1.9/6.1.11, vite 8, Node 22/26, macOS.
Source: marko-js/marko