perf(build): budget the runtime on what ships, not on source bytes
The runtime budgets measured raw source, which counts comments -- and the
production build minifies, so comments cost a visitor nothing. The metric
therefore rewarded deleting explanatory comments over writing smaller code,
and could not tell a real feature from a wall of prose.
They now measure the minified output, which is what is actually served:
/__wrnexus/reactive.js is its own file, minified, with an immutable year-long
cache. The reactive runtime is 69684 minified against a 80000 budget, from
175246 raw -- roughly 21kB gzipped, fetched once.
Also fixes two real bugs found while testing the showcase:
- object-valued props were serialised as a bare {...} attribute, which the
compiler read as interpolation and tried to parse as JavaScript. That
returned 500 for /components/navbar. Arrays start with [ and were never
affected, which is why only object props broke. All 108 pages now render.
- the runtime walked text nodes inside textarea, script and style, so a
JSON sample in a textarea was evaluated away.
Navbar styles move out of ui.css into the component, matching the rest of the
navigation group. No declarations changed: 4519 before and after.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -83,6 +83,15 @@ const escapeText = (value) =>
|
||||
*/
|
||||
const escapeCode = (value) =>
|
||||
escapeText(value).replaceAll("{", "<span>{</span>").replaceAll("}", "<span>}</span>");
|
||||
/*
|
||||
* JSON for a textarea. Entities keep the braces away from the WRN compiler,
|
||||
* which would otherwise read them as interpolation and fail the page build,
|
||||
* while the browser decodes them so the reader still sees valid JSON. The
|
||||
* span trick used for code samples cannot be used here: a textarea shows its
|
||||
* markup literally.
|
||||
*/
|
||||
const escapeTextareaJson = (value) =>
|
||||
escapeText(value).replaceAll("{", "{").replaceAll("}", "}");
|
||||
const escapeAttribute = (value) =>
|
||||
escapeText(value).replaceAll('"', """).replaceAll("'", "'");
|
||||
|
||||
@@ -418,7 +427,13 @@ function sampleValue(prop, component, variation) {
|
||||
function wrnAttribute(name, value) {
|
||||
if (typeof value === "object" && value !== null) {
|
||||
const expression = JSON.stringify(value).replaceAll("'", "\\u0027");
|
||||
return `${name}='${expression}'`;
|
||||
/*
|
||||
* An object literal has to be parenthesised. A bare {...} at the start of
|
||||
* an attribute is read as an interpolation, so the compiler tried to parse
|
||||
* the JSON as JavaScript and stopped at the first colon. Arrays start with
|
||||
* [ and were never affected, which is why only object props broke.
|
||||
*/
|
||||
return `${name}='${Array.isArray(value) ? expression : `(${expression})`}'`;
|
||||
}
|
||||
return `${name}="${escapeAttribute(String(value))}"`;
|
||||
}
|
||||
@@ -653,7 +668,7 @@ function playgroundControl(prop, component) {
|
||||
prop.type === "object" ||
|
||||
prop.type.includes("[]");
|
||||
if (structured) {
|
||||
return `<label class="playground-field" for="${id}"><span><strong>${label}</strong>${meta}</span><textarea id="${id}" name="pg_${escapeAttribute(prop.name)}" rows="5" spellcheck="false" data-playground-json>${escapeText(value)}</textarea><em data-playground-error></em></label>`;
|
||||
return `<label class="playground-field" for="${id}"><span><strong>${label}</strong>${meta}</span><textarea id="${id}" name="pg_${escapeAttribute(prop.name)}" rows="5" spellcheck="false" data-playground-json>${escapeTextareaJson(value)}</textarea><em data-playground-error></em></label>`;
|
||||
}
|
||||
|
||||
const options = playgroundOptions(prop, component, value);
|
||||
|
||||
Reference in New Issue
Block a user