mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-03 05:08:53 +00:00
perf(build): the stylesheet minifier had never run
It looked for the tag written as `css` immediately followed by a backtick. The plugin is a Rollup transform, so the module has already been through TypeScript by the time it arrives, and the TS printer puts a space there: `css `. The guard therefore returned null for every stylesheet in the project, and minification never ran once — around 23 KB of explanatory comments went to every user in every release. Matching the tag as a word with optional whitespace turns it on: chunk, raw 1 079 508 -> 1 021 115 B (-58 393) initial view 300 111 -> 287 284 B gzip (-12 816) room to the budget 955 -> 13 782 B The ceiling moves down with the fact, as the tool asks when a graph shrinks past the band. The risk is not the two lines; it is that 23 KB of CSS is minified for the first time. Two witnesses cover it: a browser smoke that puts the original and the minified text into separate stylesheets and compares the serialised rules — 1 049 of them, identical up to the whitespace policy the minifier declares — and a test that takes real comment text out of src/styles and requires it to be absent from dist, so a plugin that silently stops working cannot pass again. Issue: #526 User-Visible: yes
This commit is contained in:
@@ -234,8 +234,16 @@ export const LOW_HEADROOM_WARNING_BYTES = 15_000;
|
||||
* меняется, но зазор между потолком и бюджетом сжался до 366 Б: долг #367
|
||||
* из предупреждения стал ограничением, следующая правка начального графа
|
||||
* упрётся в него всерьёз.
|
||||
*
|
||||
* 2026-09-11, #526: потолок опущен 300 700 → 288 300. Минификатор шаблонов
|
||||
* стилей не работал ни разу: его отсев искал `css` вплотную к бэктику, а
|
||||
* плагин видит вывод TypeScript, где принтер ставит пробел. Включение снимает
|
||||
* 58 393 Б сырого текста (комментарии и отступы 23 КБ таблиц стилей) и
|
||||
* 12 816 Б gzip. Измеренный факт 287 284 Б оставляет 1 016 Б сверху и 984 Б до
|
||||
* нижней границы полосы; общий бюджет 301 066 Б не меняется, запас до него
|
||||
* вырос с 955 Б до 13 782 Б.
|
||||
*/
|
||||
export const INITIAL_VIEW_GZIP_CEILING = 300_700;
|
||||
export const INITIAL_VIEW_GZIP_CEILING = 288_300;
|
||||
export const INITIAL_VIEW_CEILING_BAND = 2_000;
|
||||
|
||||
/**
|
||||
|
||||
@@ -60,14 +60,18 @@ export function minifyCssText(source, label = '<css>') {
|
||||
return out.trim();
|
||||
}
|
||||
|
||||
const CSS_TAG = /(^|[^\w$.])css\s*`/;
|
||||
|
||||
export function minifyStaticCssTemplates(code, id = '<module>') {
|
||||
let cursor = 0;
|
||||
let output = '';
|
||||
let changed = false;
|
||||
while (true) {
|
||||
const start = code.indexOf('css`', cursor);
|
||||
if (start < 0) break;
|
||||
let end = start + 4;
|
||||
const match = CSS_TAG.exec(code.slice(cursor));
|
||||
if (!match) break;
|
||||
const start = cursor + match.index + match[1].length;
|
||||
const tagLength = match[0].length - match[1].length;
|
||||
let end = start + tagLength;
|
||||
let escaped = false;
|
||||
for (; end < code.length; end += 1) {
|
||||
const char = code[end];
|
||||
@@ -85,7 +89,7 @@ export function minifyStaticCssTemplates(code, id = '<module>') {
|
||||
if (char === '`') break;
|
||||
}
|
||||
if (end >= code.length) throw new Error(`${id}:${start}: unclosed css template`);
|
||||
const css = code.slice(start + 4, end);
|
||||
const css = code.slice(start + tagLength, end);
|
||||
output += code.slice(cursor, start);
|
||||
output += `css\`${minifyCssText(css, `${id}:${start}`)}\``;
|
||||
cursor = end + 1;
|
||||
@@ -99,7 +103,7 @@ export function cssTemplateMinifier() {
|
||||
return {
|
||||
name: 'houseplan-css-template-minifier',
|
||||
transform(code, id) {
|
||||
if (!id.endsWith('.ts') || !code.includes('css`')) return null;
|
||||
if (!id.endsWith('.ts') || !CSS_TAG.test(code)) return null;
|
||||
const transformed = minifyStaticCssTemplates(code, id);
|
||||
return transformed == null ? null : { code: transformed, map: null };
|
||||
},
|
||||
|
||||
@@ -3611,6 +3611,32 @@ const MUTANT_DEFINITIONS = [
|
||||
replace: " if (ledger.caught[mutant.id] === fingerprint || mutant.id in ledger.caught) skipped.push(mutant);",
|
||||
}],
|
||||
},
|
||||
{
|
||||
id: 'css-minifier-skips-typescript-output',
|
||||
guard: 'node --test --test-name-pattern="#526 AC4|#526 AC2" test/bundle-assets.test.mjs',
|
||||
because: '#526: плагин видит вывод TypeScript, где тег отделён от шаблона пробелом; '
|
||||
+ 'строгий отсев `css` вплотную к бэктику молча выключает минификацию целиком — '
|
||||
+ 'так 23 КБ комментариев и 12,8 КБ gzip уехали пользователю и никто не заметил',
|
||||
patches: [{
|
||||
file: 'scripts/css-template-minifier.mjs',
|
||||
find: " if (!id.endsWith('.ts') || !CSS_TAG" + '.test(code)) return null;',
|
||||
replace: " if (!id.endsWith('.ts') || !code.includes('css" + String.fromCharCode(96) + "')) return null;",
|
||||
}],
|
||||
},
|
||||
{
|
||||
id: 'css-minifier-eats-required-space',
|
||||
guard: 'node demo/smoke_css_minifier_semantics.mjs',
|
||||
because: '#526: минификация 23 КБ CSS включилась впервые — свидетель обязан ловить '
|
||||
+ 'съеденный значащий пробел (потомковый комбинатор, аргумент calc), а не только '
|
||||
+ 'считать сэкономленные байты',
|
||||
patches: [{
|
||||
file: 'scripts/css-template-minifier.mjs',
|
||||
find: ' if (pendingSpace && out && !TIGHT_AFTER.has(out.at(-1))' + ' && !TIGHT_BEFORE.has(char)) {
|
||||
out += ' ';
|
||||
}',
|
||||
replace: ' void pendingSpace; // mutant: значащий пробел больше не восстанавливается',
|
||||
}],
|
||||
},
|
||||
{
|
||||
id: 'marker-shadow-animates-again',
|
||||
guard: 'node demo/smoke_marker_shadow_transitions.mjs',
|
||||
|
||||
Reference in New Issue
Block a user