Three days ago the tool started recording the weight of every script, stylesheet and font a site
serves, and two days ago we gave it a sheet in the
spreadsheet. Both write-ups ended with the same
sentence, in those words: the sheet shows the number and no rule judges it. Nothing warns you that
the bundle.js is too heavy.
0.10.0 closes that, and three other things along the way.
What gets judged now
A script over 250 KB as delivered, and a stylesheet over 100 KB. The CSS bar is lower on purpose: it blocks rendering, the browser paints nothing until it has it, so the same bytes cost more. The script bar sits above what a normal framework runtime weighs, so what fires is a bundle nobody split rather than the decision to use React.
Both rules only look at what the audited site serves itself. A heavy script hosted on someone
else’s CDN is not something its owner can split, and its size reaches us from a HEAD request
rather than a body actually downloaded: asserting on that number would mean judging a figure of a
different quality.
An <iframe> pointing at a broken URL of yours, leaving a blank hole where the map should be.
And a form whose action does not exist, the only rule in this family at critical severity: a
form that fills in fine and is lost on submit costs customers, and you never find out, because
whoever hits it leaves without a word.
That last one has a limit we would rather declare than have you discover: only forms submitted with GET are checked, a search box or a catalogue filter. Checking a POST would mean submitting the form, and this tool does not submit forms. The parser does not even record those destinations: a row that cannot be judged is worse than no row. It is the same reasoning that keeps a foreign server’s 403 to a probe out of the broken-link rule.
An archaeological note: <form> had been in the parser’s element list since day one and was never
emitted. That is why the earlier attempt at this rule was a false one.
The port is part of the site
Until now, “same site” was decided by comparing hosts. Auditing http://localhost:3000 — the
normal thing when you check before deploying — a link to http://localhost:8080 was crawled as
your own: its pages entered the internal count, its 404s came out as internal errors, and the link
graph mixed two different applications. In production this is rare; in development it is routine,
and development is exactly where the mode that audits your output folder before publishing gets
used.
Now the port counts. https://example.com and https://example.com:443 still mean the same thing,
because the scheme’s default port normalises away on its own.
That change moved a piece I was not expecting: sitemap discovery worked out its own host, without the port, so a sitemap of your own site served on an explicit port started being discarded whole as “outside the audited site”. It was caught by a basic-authentication test that has nothing to do with ports or sitemaps, and that exists because someone wanted to prove a protected staging site gets crawled with its credentials.
The 24% the test let pass
With everything green, the pre-publish check produced this:
elementos/s 81169 · páginas/s 1980 · RSS 31.5 MB
The previous version gave 107,702. A 24% drop, and the regression test passed: its threshold sits below that, so it does not fail on the noise of a busy machine. A test that measures without asserting enough lets exactly this through.
The first explanation I came up with was sound, reasonable and wrong. Adding the port made the comparison build a string on every call, and that function runs once per link of every page: millions of allocations on a large crawl. I fixed it to compare without building anything, measured again, and gained 4%. That was not it.
This was:
QUERY PLAN
|--SCAN l
The two new frame and form rules filter on the link’s element type, and that column had no index, so each of them walked the entire links table. On the real site where I measured, that is 145,191 rows; on a large site, the final pass sits down and waits. Migration 010 adds the index and the number goes back where it belongs:
elementos/s 108585 · páginas/s 2648 · RSS 32.3 MB
Both fixes stay, the string one included: it was real, just small. And there is a new test that
does not measure time but reads the query plan and fails if that SCAN ever comes back. A timing
test measures the machine too; a plan test asserts on the decision.
What is not here
List mode still treats only the first domain in the file as internal, so a list mixing sites audits the first and status-checks the rest as foreign. We could have changed it today and it would have been the worst moment: a change of meaning in the same version that already moves findings from one side to the other. It is declared in the manual, in both languages, until it is lifted.
The balance: 63 rules, 1,047 tests green, the linter clean and performance above where it started. And the sentence we had been carrying since Monday is no longer needed: the sheet shows the number, and now a rule says whether it is too much.