Open
Conversation
## Problem A real-world coverage report with 1705 source files produces a **41MB HTML file** (~1.9M lines) that causes significant browser slowdown: - 96% of the file is the source files section (~41.3MB) - 51% of that section is whitespace from ERB template formatting (~21MB) - 142,254 `<li>` elements rendered into the DOM at page load (hidden) - 142K event handlers individually bound to line number elements - An unnecessary `<div>` wrapper around each `<li>` adds 142K extra DOM nodes ## Changes ### Phase 1: Template Optimizations **ERB whitespace trimming** (`lib/simplecov-html.rb`, all `.erb` views) - Add `trim_mode: '-'` to the ERB constructor - Add `<%-` / `-%>` trim markers to control flow tags in all templates - Eliminates ~21MB of blank lines produced by ERB conditionals/loops **Remove `<div>` wrapper around `<li>`** (`views/source_file.erb`) - These were semantically invalid inside `<ol>` and unnecessary - Saves ~2.8MB and 142K DOM nodes **Conditional `data-hits` attribute** (`views/source_file.erb`) - Only emit `data-hits="N"` when `line.coverage` is truthy - Previously emitted `data-hits=""` for ~83K "never" lines with no JS/CSS referencing the empty attribute **Compact `covered_percent.erb`** - Single-line template avoids multi-line whitespace across ~3,400 calls ### Phase 2: Browser Performance **`<template>` tags for source files** (`views/layout.erb`) - Each source file is wrapped in `<template id="tmpl-SHA1">` - `<template>` content is parsed but NOT rendered into the DOM until explicitly activated — removes ~500K DOM nodes from initial page load **Template materialization on demand** (`assets/javascripts/application.js`) - New `materializeSourceFile()` function clones template content into the `.source_files` container when a file is first viewed - Syntax highlighting applied on materialization (same deferred approach) - All code paths updated: click, colorbox onLoad, popstate, deep links **Event delegation for line number clicks** (`assets/javascripts/application.js`) - Replaced direct binding on 142K elements with a single delegated event handler on `document` - Required for `<template>` approach and eliminates 142K event bindings ## Results Tested against a real coverage report with 1705 source files: | Metric | Before | After | Change | |---------------------|-------------|-----------|--------------| | File size | 41 MB | 25 MB | **-39%** | | Lines | 1,944,847 | 573,916 | **-70%** | | Blank lines | 1,090,596 | 3,578 | **-99.7%** | | `<div>` wrappers | 142,255 | 2 | **-142,253** | | `data-hits` attrs | 142,253 | 59,101 | **-83,152** | | DOM nodes at load | ~500K+ | ~few K | deferred via `<template>` | | Event bindings | 142K | 1 | delegated | The remaining 25MB is predominantly the actual source code content inside `<li>` elements, which is irreducible. ## Files Modified | File | Changes | |---|---| | `lib/simplecov-html.rb` | `trim_mode: '-'` on ERB constructor | | `views/source_file.erb` | Trim markers, remove `<div>`, conditional `data-hits` | | `views/layout.erb` | Trim markers, `<template>` tags around source files | | `views/file_list.erb` | Trim markers on control flow tags | | `views/covered_percent.erb` | Single-line template | | `assets/javascripts/application.js` | Template materialization, event delegation | | `public/application.js` | Re-compiled asset | ## Test Plan - [x] `bundle exec rake test` passes - [x] Generate a coverage report against a test project and compare HTML file size - [x] Open in browser: file list loads, clicking a file shows source in modal - [x] Line numbers are clickable and scroll to correct position - [x] Syntax highlighting works on opened files - [x] Back/forward navigation works correctly - [x] Deep-linking to a specific file/line via URL hash works Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
c541a35 to
22250d2
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
A real-world coverage report with 1705 source files produces a 41MB
HTML file (~1.9M lines) that causes significant browser slowdown:
<li>elements rendered into the DOM at page load (hidden)<div>wrapper around each<li>adds 142K extra DOM nodesChanges
Phase 1: Template Optimizations
ERB whitespace trimming (
lib/simplecov-html.rb, all.erbviews)trim_mode: '-'to the ERB constructor<%-/-%>trim markers to control flow tags in all templatesRemove
<div>wrapper around<li>(views/source_file.erb)<ol>and unnecessaryConditional
data-hitsattribute (views/source_file.erb)data-hits="N"whenline.coverageis truthydata-hits=""for ~83K "never" lines with noJS/CSS referencing the empty attribute
Compact
covered_percent.erbPhase 2: Browser Performance
<template>tags for source files (views/layout.erb)<template id="tmpl-SHA1"><template>content is parsed but NOT rendered into the DOM untilexplicitly activated — removes ~500K DOM nodes from initial page load
Template materialization on demand (
assets/javascripts/application.js)materializeSourceFile()function clones template content intothe
.source_filescontainer when a file is first viewedEvent delegation for line number clicks (
assets/javascripts/application.js)event handler on
document<template>approach and eliminates 142K event bindingsResults
Tested against a real coverage report with 1705 source files:
<div>wrappersdata-hitsattrs<template>The remaining 25MB is predominantly the actual source code content
inside
<li>elements, which is irreducible.Files Modified
lib/simplecov-html.rbtrim_mode: '-'on ERB constructorviews/source_file.erb<div>, conditionaldata-hitsviews/layout.erb<template>tags around source filesviews/file_list.erbviews/covered_percent.erbassets/javascripts/application.jspublic/application.jsTest Plan
bundle exec rake testpasses