LIGHTWEIGHT TEMPLATES
They are not two separate files. Before the template reaches the browser, both tabs are compiled into a single component function: the JS tab becomes its body, the JSX tab becomes what it returns. Roughly this:
export default function execute(data) {
const components = data.components;
const html = data.components.html;
const context = data.context;
const dispatchSignal = data.dispatchSignal;
const {
batch, createEffect, createMemo, createResource, createSignal,
mergeProps, onCleanup, onMount, splitProps, /* … */
} = data.solidJs;
function Custom() {
// ─── everything from your JS tab is inlined here, verbatim ───
return components.html`
/* ─── your JSX tab, rewritten into a tagged template ─── */
`;
}
return Custom;
}
Four consequences follow from that shape, and they explain most of the surprises in the questions below:
-
One scope. The JS tab and the JSX tab share the component's scope, so the JSX can read anything the JS tab declared at its top level — and nothing it declared deeper.
-
JS runs first, once per instance. The JS tab executes on every render of the widget, before the markup exists. A
refis therefore still empty while the JS tab runs. -
No imports, ever.
context,html,dispatchSignaland the Solid primitives (createSignal,createEffect,createMemo,onMount, …) are already in scope. Writingimportin the JS tab is both unnecessary and a syntax error.
Component reference: Lightweight templates components. DOM handlers (onClick, onInput, …): Lightweight templates events.