Skip to content

Engine: Compile-time optimizations for Action View tag helpers#1613

Merged
marcoroth merged 32 commits intomainfrom
precompile-action-view-helpers
Apr 20, 2026
Merged

Engine: Compile-time optimizations for Action View tag helpers#1613
marcoroth merged 32 commits intomainfrom
precompile-action-view-helpers

Conversation

@marcoroth
Copy link
Copy Markdown
Owner

@marcoroth marcoroth commented Apr 5, 2026

This pull request adds compile-time optimization support for Action View tag helpers to Herb::Engine.

When optimize: true is passed to Herb::Engine, the parser transforms Action View helper calls (tag.*, content_tag, link_to, image_tag, javascript_tag, javascript_include_tag, turbo_frame_tag) into their HTML equivalents at compile time, producing optimized Ruby output that avoids runtime helper dispatch.

When compile-time optimizations are enabled, the engine checks whether the template contains supported Action View helpers via the Herb::ActionView::HelperRegistry.supported method. If helpers are detected, the parser is invoked with action_view_helpers: true and transform_conditionals: true, which also handles postfix if/unless and ternary conditionals containing helper calls.

The pull request also includes comprehensive snapshot-based tests for all supported helpers, an assert_optimized_output_match helper that validates optimized output against both standard Herb and ActionView+Erubi to ensure the rendered output matches.

Additionally, we added a YAML-driven benchmark framework in bench/action_view/ with a bin/bench CLI for compile-time and render-time comparisons. Early benchmarks show render-time improvements of 3-22x depending on the template, with a realistic 192-line page layout rendering 22x faster, and a helper-heavy template with all static values reaching up to 150x faster.

The trade-off is compile time: Herb's parser is currently 10-90x slower than Erubi at compile time, so optimization adds overhead that needs to be amortized over multiple renders. But this is typically won back with 15-100 renders depending on template complexity and could also be done ahead of time, instead of the current on-the-fly approach used in Action View today.

Warning

Compile-time optimizations are experimental. Output may differ from standard ActionView rendering.

CleanShot 2026-04-05 at 23 58 07@2x

Resolves #653
Enables #1111

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Apr 5, 2026

npx https://pkg.pr.new/@herb-tools/formatter@1613
npx https://pkg.pr.new/@herb-tools/language-server@1613
npx https://pkg.pr.new/@herb-tools/linter@1613

commit: 9926177

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 5, 2026

🌿 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 9926177


✅ Preview deployment has been cleaned up.

@marcoroth marcoroth changed the title Engine: Precompile Action View Tag Helpers Engine: Compile-time optimizations for Action View tag helpers Apr 19, 2026
@marcoroth marcoroth merged commit ceaffa4 into main Apr 20, 2026
32 checks passed
@marcoroth marcoroth deleted the precompile-action-view-helpers branch April 20, 2026 01:30
marcoroth added a commit that referenced this pull request Apr 20, 2026
This pull request adds `framework` and `template_engine` configuration
options to the `.herb.yml`.

These top-level settings tell Herb what environment it's running in and
what template engine is being used for compilation. This enables
context-aware behavior across the toolchain.

Configuration in `.herb.yml`:

```yml
framework: actionview      # ruby | actionview | hanami | sinatra (default: ruby)
template_engine: herb      # erubi | erb | herb (default: erubi)
```

Valid values are defined once in `config/options.yml` and code-generated
into the relevant configuration files in all bindings.

This allows us in the future to have more specific features tailored for
each target framework and engine. This pull request is meant to lay the
groundwork for:
- Framework-aware linter rules, so that we can automatically
enable/disable rules based on the framework (see
#480)
- Framework-aware compile-time optimizations. Knowing the framework
context determines which helpers are available for optimization (like
#1613)
- Template engine compatibility, surfacing invalid syntax or other
target engine's conventions across the toolchain (for example no ERB
block support)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Engine: Optimize Action View Tag Helpers when compiling template

1 participant