Byte attribution of a served product snapshot: inlined CSS is 13%, attributes are 75%
まだ誰も着手していません。
評価
- 難易度
- 5/5
- 見積もり時間
- 1週間以上
- 初心者へのやさしさ
- 35/100
- issue の種類
- 機能追加
- 明瞭さ
- 説明が足りない
- 活発さ
- 活発
- 技術スタック
- javascript
- 領域
- performance
調査の方向性
まず postProcess パスと、既存の pruneUnmatchedCss および minifyInlineCss の動作を読み、次に指定された browser v1.21.0 のオプションを使って /prerender_admin/page-content のバイト内訳を再現します。SVG、クラス・トークン、繰り返される Style-URL の施策を、外部スタイルシートおよび paint またはジオメトリのパリティと比較してください。review widget の CSS は削除しないでください。完了条件は、レンダリングされるコンテンツを変更せず、1 MB の上限に向けた明確な道筋を備えた、選択済みで測定済みの最適化があることです。
索引モデルが issue の本文から書いたものです。
説明
Summary
A served product snapshot was reported as having a low text-to-HTML ratio, attributed to the CSS flattenShadowDom inlines for the review widget. Measured against a real served page, that attribution is wrong: inlined CSS is 13.4% of the document and attributes are 74.7%. Deleting every byte of injected styling moves the ratio 2.66% → 3.07%.
This issue records the byte attribution so the numbers aren't re-derived, and separates the levers that are provably safe from the one that isn't.
Method
One review-heavy product page (desktop), read from the serving cache via /prerender_admin/page-content, so these are the bytes a crawler receives. Rendered by browser v1.21.0 with flattenShadowDom, pruneUnmatchedCss and minifyInlineCss all on — i.e. the CSS below is already the residue after ~74% of style rules were pruned and the rest CSSOM-minified.
Class-token reference counts were computed against the inline <style> blocks and the four external stylesheets the snapshot still links. Measuring against inline CSS alone overstates the unreferenced total by ~6× (359 KB vs the true 61 KB) — the page keeps a 588 KB external utility stylesheet, so most tokens are referenced from a sheet that is not in the document.
Where 1,468,123 bytes go
| bytes | % of doc | |
|---|---|---|
class attributes |
451,713 | 30.8% |
inlined <style> CSS |
197,160 | 13.4% |
style= attributes |
140,957 | 9.6% |
href / src / srcset |
214,751 | 14.6% |
SVG d path data |
81,344 | 5.5% |
aria-label |
52,604 | 3.6% |
| tag names + brackets | 55,700 | 3.8% |
| ld+json | 17,486 | 1.2% |
| visible text | 39,078 | 2.66% |
10,137 elements. 74.7% of the document is HTML attributes.
The review widget
The flattened review container is 385,482 B — 26.3% of the page — carrying 7,707 B of review text (2.0% of itself). Eight review cards; one card is 22,446 B / 235 elements for 956 B of text.
| inside the review container | bytes | % of block |
|---|---|---|
inlined <style> (host sheet + nested shadow hosts) |
152,624 | 39.6% |
SVG markup (d alone = 62,473) |
108,954 | 28.3% |
class |
60,930 | 15.8% |
| review text | 7,707 | 2.0% |
Two candidates measured and rejected
- Deduplicating identical shadow stylesheets across hosts. 9 distinct sheets across 10 hosts; total bytes sitting in duplicate copies: 196 B. Not a lever.
minifyInlineCsson the flattened blocks. Already CSSOM output, so re-emission is a no-op — consistent with the existing docstring.
Levers that remain, with sizes
- Repeated SVG path data — ~64,093 B (4.4% of the document), concentrated in the review block. 193
doccurrences, only 61 distinct; a single 1,033-byte path appears 45 times (46,485 B). Hoisting exact-duplicate path data into<defs><symbol>+<use>renders identically. No such pass exists inpostProcesstoday. - Class tokens no surviving rule references — 61,277 B page-wide, 34,467 B inside the review block. Same soundness argument that already licenses
pruneUnmatchedCss: withstripScriptson, nothing can add a class after serialization, so a token no sheet mentions is inert. Must be evaluated against external sheets, not just inline ones. - A repeated background-image URL in
style=attributes — ~93,000 B. One sprite URL repeated 489 times acrossstyle=attributes. Origin-authored, not introduced by post-processing.
Cloaking: what actually carries risk here
Worth stating explicitly, because "fidelity" has been used to decline byte-cutting levers that do not actually implicate it.
Cloaking is presenting different content to users and crawlers in order to manipulate rankings. The unit is content — text, links, images, prices, availability, structured data — not markup. Removing an attribute no rule reads, deduplicating identical SVG path data, or pruning a rule that matches nothing changes zero content: a user and a crawler still perceive the same page. Levers 1–3 are outside the policy, and rendering-fidelity checks (paintParity, geometry) are the right bar for them for a different reason — Google indexes the rendered DOM and devalues content it determines is not visible, so a layout regression costs indexing quality on its own merits.
The risk is asymmetric, and it runs the other way: revealing content to a crawler that a user does not see is the cloaking-shaped move. That is exactly what dropping the review widget's CSS would do — the widget's own rules hold collapsed panels, modals and secondary UI at display:none, and stripping them injects text into the indexable page that no user is shown. It would also reintroduce the inbound-encapsulation defects fixed across v1.19–v1.21. Do not pursue "just drop the review CSS" for byte savings.
Note for answer/generative engines
Structured data carries aggregateRating (ratingValue, ratingCount) but no individual review objects. So the 385 KB review DOM is the only place individual review content exists in the snapshot — it is load-bearing for extraction, not redundant with the JSON-LD, and should not be treated as trimmable content. Emitting review items into the JSON-LD would serve extraction far better per byte than the DOM does, but that is an origin change, not a post-processing one.
Separately: text-to-HTML ratio is not a documented ranking signal — it is a third-party audit-tool metric. The documented hard constraint is the 1 MB soft cap a crawler applies to a document, and this page is at 1.47 MB. Sizing work against "get under 1 MB" is better defined than "raise a ratio", and levers 1–3 together are ~218 KB of the ~470 KB needed.
- 主要言語
- JavaScript
- スター
- 0
- フォーク
- 0
- 平均マージ
- 9時間 10分
- マージ済み PR(30日)
- 56
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
HarperFast/prerender-plugin のほかの issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 86/100
HarperFast/prerender-plugin#176 ·
-
難易度 4/5 3〜5日 初心者へのやさしさ 48/100
HarperFast/prerender-plugin#189 ·
-
難易度 5/5 1週間以上 初心者へのやさしさ 35/100
HarperFast/prerender-plugin#185 · コメント 1 件 ·
-
難易度 5/5 1週間以上 初心者へのやさしさ 25/100
HarperFast/prerender-plugin#183 ·
-
難易度 5/5 1週間以上 初心者へのやさしさ 35/100
HarperFast/prerender-plugin#180 ·
HarperFast/prerender-plugin の issue をすべて見る
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 65/100
antfu-collective/icones#398 ·
-
ECmail.com オープン
難易度 1/5 1時間未満 初心者へのやさしさ 90/100
wesbos/burner-email-providers#554 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 65/100
radiantearth/stac-browser#1023 ·
-
HMR stops working オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
-
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
components-web-app/docs#92 ·