Skip to content

Engine: Add client slot mode that parks untaken branches - #2268

Merged
marcoroth merged 3 commits into
mainfrom
slots/statics
Aug 18, 2026
Merged

Engine: Add client slot mode that parks untaken branches#2268
marcoroth merged 3 commits into
mainfrom
slots/statics

Conversation

@marcoroth

@marcoroth marcoroth commented Aug 18, 2026

Copy link
Copy Markdown
Owner

This pull request adds a client slot mode, which sends the browser the markup of the branches a request did not take, parked in a <template> that names its own region. One of them can then be built later without asking the server for markup the page was already given.

<%# herb:slots client %>

<%# herb:slots server %> stays the default and emits nothing beyond the markers, so nothing about a branch that did not render reaches the page.

What gets parked is decided while rendering, not while compiling. A branch that rendered is on the page already, so it is not sent twice, and a template whose every branch ran parks nothing at all. Herb::Engine::SlotStatics prints the markup a branch would render with everything dynamic left out, which is what a client needs to build it: the parts that never change, and the positions of the parts that do.

<template data-herb-region="app/views/posts/_card.html.erb:aaaaaaaa">
  <!--herb-branch:0:1--><b>Hello <!--herb-slot:3--><!--/herb-slot:3--></b>
</template>

Three smaller changes come with it. A conditional whose branches lay out the same way collapses into one set of slots, since which branch ran only changes what those slots hold. An element-anchored slot names the attribute it writes, so its name no longer has to be carried separately. And a template can be named by a digest of its path instead of by the path itself, because the markers go out with the page and a view tree says more about an application than its pages do.

Slots are experimental and the marker format is not stable yet.

@github-actions github-actions Bot added ruby Ruby source for the gem and its libraries rbs RBS type signatures in sig/ engine Herb engine and Rails template compilation rubygem The herb RubyGem and its packaging labels Aug 18, 2026
@marcoroth marcoroth added the reactivity Reactive ERB templates: diff and re-render only what changed label Aug 18, 2026
@nx-cloud

nx-cloud Bot commented Aug 18, 2026

Copy link
Copy Markdown

View your CI Pipeline Execution ↗ for commit 9eeae6f

Command Status Duration Result
nx run-many -t test --all --parallel --exclude=... ✅ Succeeded 3m 26s View ↗
nx run-many -t build --all --exclude=herb-langu... ✅ Succeeded 15s View ↗
nx build @herb-tools/tailwind-class-sorter ✅ Succeeded 1s View ↗

💡 Verify your cache is correct by running tasks in a sandbox. Read docs ↗


☁️ Nx Cloud last updated this comment at 2026-08-18 03:25:33 UTC

@github-actions

github-actions Bot commented Aug 18, 2026

Copy link
Copy Markdown

🌿 Interactive Playground and Documentation Preview

A preview deployment has been built for this pull request. Try out the changes live in the interactive playground:


🌱 Grown from commit 9eeae6f


✅ Preview deployment has been cleaned up.

@pkg-pr-new

pkg-pr-new Bot commented Aug 18, 2026

Copy link
Copy Markdown
npx https://pkg.pr.new/@herb-tools/formatter@2268
npx https://pkg.pr.new/@herb-tools/language-server@2268
npx https://pkg.pr.new/@herb-tools/linter@2268

commit: 9eeae6f

…ches

`<%# herb:slots client %>` sends the client the markup of the branches a
request did not take, parked in a `<template>` that names its own region, so
one of them can be built later without asking the server for markup the page
was already given. `<%# herb:slots server %>` is the default and emits nothing
beyond the markers, so nothing about a branch that did not render reaches the
page.

What gets parked is decided while rendering rather than while compiling. A
branch that rendered is on the page already, so it is not sent twice, and a
template whose every branch ran parks nothing at all.

Three smaller changes come with it. A conditional whose branches lay out the
same way collapses into one set of slots, since which branch ran only changes
what those slots hold. An element-anchored slot now names the attribute it
writes, so its name no longer has to be carried separately. And a template can
be named by a digest of its path rather than by the path itself, because the
markers go out with the page and a view tree says more about an application
than its pages do.

(cherry picked from commit d6b8667)
(cherry picked from commit ca7f737)
@marcoroth
marcoroth merged commit 1ed5dcf into main Aug 18, 2026
57 of 63 checks passed
@marcoroth
marcoroth deleted the slots/statics branch August 18, 2026 12:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

client-runtime Browser runtime for the Herb slots. engine Herb engine and Rails template compilation rbs RBS type signatures in sig/ reactivity Reactive ERB templates: diff and re-render only what changed ruby Ruby source for the gem and its libraries rubygem The herb RubyGem and its packaging

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant