Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

lint is up to 40x slower than 0.8.106 on a long linked stylesheet: the canvas-zoom rule strips comments once per matched rule, and lint now reads stylesheets linked from sub-compositions

Aperta Adatta ai principianti
#5,681 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
75/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
css, typescript

Direzione di ricerca

Il percorso lento è stylesheetCanvasZoomHits in packages/lint/src/rules/composition.ts, dove il ciclo while chiama stripCssComments(style.content) a ogni corrispondenza (intorno alla riga 364). Inizia leggendo collectHeavyOverlayHooks (righe 203-206), che rimuove già i commenti una volta, e applica lo stesso schema al ciclo. È completato quando il tempo di lint della riproduzione cresce approssimativamente in modo lineare con il numero di regole e l'output di lint non cambia.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

bug triage/needs-triage
Describe the bug

lint takes 10 to 60 s a project in 0.8.158 where 0.8.106 took 0.5 to 1.6 s on the same projects and machine (one project measured alternately: 11.5 and 12.5 s on 0.8.158 against 2.2 and 1.7 s on 0.8.106). On a quiet machine, two projects measured alternately on 0.8.152 took 3.1 and 3.2 s against 0.8.106's 0.5 and 0.5 s, and 7.1 and 7.4 s against 0.6 and 0.5 s. check runs the lint too, so every check pays it, and a check split into parts pays it in every part.

A CPU profile of one 14.2 s run: 6.5 s in stripCssComments and 4.6 s in stylesheetCanvasZoomHits (chunk-7F3B5YYT.js of the package's dist, around line 6470). The canvas-zoom rule's loop is

while ((match = ruleWithBody.exec(stripCssComments(style.content))) !== null)

so it strips the whole stylesheet's comments again for every rule it matches, and the time grows with the square of the stylesheet's length. Our stylesheet is about 2,750 lines with some 800 rules, which is where it shows.

The loop itself is older: 0.8.106 is as slow on the same 3,000 rules when they sit in an inline <style> (4.4 to 5.2 s on 0.8.106, 4.2 to 4.8 s on 0.8.158). What changed is which stylesheets lint reads. A <link rel="stylesheet"> inside a sub-composition's <template> is now also resolved from the project root (packages/lint/src/project.ts, lines 108-113 at v0.8.162), where 0.8.106 looked only beside the sub-composition's file and skipped it. That matches how the runtime mounts the template, but it sends every such stylesheet through the quadratic loop, once for each composition that links it (line 246). Our sub-compositions each link the one shared stylesheet.

Measured on 0.8.158 (0.8.152 behaves the same). The code is unchanged in v0.8.162: packages/lint/src/rules/composition.ts, line 364 still calls stripCssComments(style.content) inside the while.

Minimal reproduction

A blank project with one sub-composition that links a long stylesheet (3,000 simple rules with a comment each):

npx hyperframes init repro --non-interactive --example blank
cd repro
mkdir compositions
# write index.html and compositions/scene.html as below, then:
node -e "require('fs').writeFileSync('long.css', Array.from({ length: 3000 }, (_, i) => '/* rule ' + i + ' */\n.r' + i + ' { color: #f4f4f5; }\n').join(''))"

index.html (the blank template plus the #scene clip, with the example comment removed from the script):

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=1920, height=1080" />
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/gsap.min.js"></script>
    <style>
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }
      html,
      body {
        margin: 0;
        width: 1920px;
        height: 1080px;
        overflow: hidden;
        background: #0a0a0a;
      }
      #root {
        width: 100%;
        height: 100%;
        display: flex;
        align-items: center;
        justify-content: center;
        font-family: Inter, ui-sans-serif, system-ui, sans-serif;
      }
      #title {
        color: #f4f4f5;
        font-size: 72px;
        font-weight: 600;
        letter-spacing: -0.03em;
      }
    </style>
  </head>
  <body>
    <div
      id="root"
      data-composition-id="main"
      data-start="0"
      data-duration="10"
      data-width="1920"
      data-height="1080"
    >
      <h1 id="title" class="clip" data-start="0" data-duration="10" data-track-index="0">Title</h1>
      <div
        id="scene"
        data-composition-id="scene"
        data-composition-src="compositions/scene.html"
        data-start="0"
        data-duration="10"
        data-track-index="1"
        data-width="1920"
        data-height="1080"
      ></div>
    </div>
    <script>
      const tl = gsap.timeline({ paused: true });
      window.__timelines["main"] = tl;
      tl.seek(0);
    </script>
  </body>
</html>

compositions/scene.html:

<!doctype html>
<html>
  <head>
    <meta charset="UTF-8" />
  </head>
  <body>
    <template>
      <link rel="stylesheet" href="long.css" />
      <div id="root" data-composition-id="scene" data-width="1920" data-height="1080"></div>
      <script>
        window.__timelines["scene"] = gsap.timeline({ paused: true });
      </script>
    </template>
  </body>
</html>
Steps to reproduce
  1. Set up the reproduction above.
  2. In repro, time npx [email protected] lint and npx [email protected] lint, alternately, a few times each (both report 0 errors, 0 warnings).
  3. Change 3000 in the node -e line to 1000 or 6000, regenerate long.css and time again: on 0.8.158 the time grows with the square of the rule count.
Expected behavior

lint about as fast as 0.8.106 on the same project (0.4 to 0.5 s here), its time growing linearly with the stylesheet's length.

Actual behavior

Wall-clock times of lint on the reproduction, versions run alternately (the installed CLI started with node, so no npx resolution is included):

rules in long.css 0.8.106 0.8.152 0.8.158
1,000 0.47, 0.48 s 0.95, 0.83 s
3,000 0.44, 0.42, 0.44 s 5.3, 5.1, 4.8 s 4.4, 5.4, 6.7 s
6,000 0.45, 0.48 s 21.4, 17.3 s

A CPU profile of 0.8.158 on the 3,000-rule reproduction: of 3.6 s, 1.4 s in stripCssComments, 1.3 s in stylesheetCanvasZoomHits and 0.6 s in garbage collection.

Environment
OS:          Windows 11 (build 26200)
Node.js:     v24.14.0
HyperFrames: 0.8.158 and 0.8.152 against 0.8.106 (code unchanged at v0.8.162)
Chrome:      Chrome Headless Shell 152.0.7977.30
Additional context

Request: strip the comments once, before the loop (and run the regular expression over that one string), as collectHeavyOverlayHooks in the same file already does (composition.ts, lines 203-206 at v0.8.162).

Lingua principale
TypeScript
Stelle
54.1k
Fork
4.9k
Merge medio
8h 32m
PR unite (30g)
707

Preparare l'ambiente

Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di heygen-com/hyperframes

Tutte le issue di heygen-com/hyperframes

Issue simili

Altre issue su TypeScript

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.