Skip to content

1.0.1

Choose a tag to compare

@davidwhitney davidwhitney released this 07 Aug 01:42
· 10 commits to main since this release

Behaviour change

ServerRendering.Timeout now bounds a whole render rather than each entry into the JavaScript
engine. One render enters the engine several times, so a view could previously consume several
multiples of the configured budget. A view that only fitted inside the old per-entry budgets can
now time out; ServerRendering.Timeout is the knob.

HttpContext.RequestAborted now stops running JavaScript, rather than only cancelling the wait for
a pooled engine.

Faster server rendering

Thanks to @lahma (#5) for the whole of this work, and for the benchmarks behind it.

  • Modules are parsed once per build and shared by every pooled engine, so growing the pool costs no
    extra parsing. The npm CommonJS to ESM transform runs once per build as well.
  • The host shims are parsed once per process, and the per-render ({}) and JSON.parse(...)
    evaluations are gone.
  • The model and context are serialised once per response instead of twice.
  • Server markup is returned as the string it already is, rather than being JSON-escaped inside the
    engine and unescaped on the way out.
  • An engine returning to the pool has its global surface restored, so anything a view left on
    globalThis no longer persists into a later request.
  • Jint updated to 4.15.3.

Measured on a warm engine: 2 to 10% faster depending on the view, and a pool-growth burst allocates
around half what it did. A cold start is 17 to 20% slower, because the first engine pays for the
static analysis that every later engine reuses; in production that is once per process.

Fixes

  • The first dotnet publish of a clean checkout omitted node_modules from the output, so
    container images and CI builds produced applications that returned 500 from any view importing a
    package (#3, reported by @jloor). The analysis that locates node_modules ran before the restore
    that creates it, and its answers were not re-read afterwards.
  • ServerRendering.Timeout could not be turned off. TimeSpan.Zero, Timeout.InfiniteTimeSpan and
    TimeSpan.MaxValue each armed a deadline at or before the render's own start, so every render
    failed immediately. Non-positive now means no budget, as it did before the whole-render deadline.

Documentation

Reported by @jloor (#4), from a full Razor to JsxCore port:

  • Troubleshooting entries for a model value rendering as nothing, which is what a casing mistake
    looks like from the outside, and for a form POST returning 400.
  • A "Razor request-state helpers" section in the .NET interop page, covering antiforgery and the
    validation helpers.