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
Version: 2.0.0-rc.8 (@solidjs/web), packages/web/src/index.ts ~282–381 and index.server.ts ~81–142
dynamic(() => "button") — a string tag that can never change — still allocates a factory memo over source, a per-instance memo, and on the client goes through createElement + a full spread. That's the cost @yak/solid measured its way out of by reimplementing the element path from template/getNextElement/spread/insert (createElementRenderer in next-yak#644), i.e. by hand-writing what the compiler emits for <button {...props}>.
Proposal
When source is a string (or Dynamic's component is a non-reactive string):
No memos. Resolve the tag once at factory time; the per-instance function returns the element directly. Hydration ids stay aligned because no owner is created on either side (the server path mirrors it).
Template + static class. Accept a static class (and other static attrs) to bake into a cached template() like compiled JSX does, so the per-instance work is clone + getNextElement + reactive bindings only.
Public shape is open: either dynamic() detects it, or a small explicit primitive (element(tag, props, { class })) that libraries with a runtime styled() API can target. The second is what yak actually needed.
Measured
ryansolid/yak-bench: yak's base runtime rendered every styled element through Dynamic and sits at 0.65× React on SSR and ~2× slower than the PR on hydrate/mount; the PR's hand-rolled element path is 25× React on SSR for static tags. Acceptance for this issue: a yak-runtime variant that uses the new path instead of createElementRenderer lands within noise of it on compose-1 / button-variants-nested / btn-variant.
Version: 2.0.0-rc.8 (
@solidjs/web),packages/web/src/index.ts~282–381 andindex.server.ts~81–142dynamic(() => "button")— a string tag that can never change — still allocates a factory memo oversource, a per-instance memo, and on the client goes throughcreateElement+ a fullspread. That's the cost@yak/solidmeasured its way out of by reimplementing the element path fromtemplate/getNextElement/spread/insert(createElementRendererin next-yak#644), i.e. by hand-writing what the compiler emits for<button {...props}>.Proposal
When
sourceis a string (orDynamic'scomponentis a non-reactive string):class(and other static attrs) to bake into a cachedtemplate()like compiled JSX does, so the per-instance work is clone +getNextElement+ reactive bindings only.runHydrationEvents()after binding (missing today, seedynamic()/Dynamicwith a string tag: norunHydrationEvents(), namespace ignores parent #3386), and take the namespace from the mount context or an explicit option instead ofSVGElements.has(tag)alone (seedynamic()/Dynamicwith a string tag: norunHydrationEvents(), namespace ignores parent #3386).Tracker: #3389.
Public shape is open: either
dynamic()detects it, or a small explicit primitive (element(tag, props, { class })) that libraries with a runtimestyled()API can target. The second is what yak actually needed.Measured
ryansolid/yak-bench: yak's base runtime rendered every styled element through
Dynamicand sits at 0.65× React on SSR and ~2× slower than the PR on hydrate/mount; the PR's hand-rolled element path is 25× React on SSR for static tags. Acceptance for this issue: a yak-runtime variant that uses the new path instead ofcreateElementRendererlands within noise of it oncompose-1/button-variants-nested/btn-variant.