Skip to content

Conversation

@ZerGo0
Copy link
Contributor

@ZerGo0 ZerGo0 commented Oct 13, 2025

Overview

I did some benchmarking in my prod. ext. and noticed that ~8% (~65ms) of the initial page render time is spent in splitShadowRootCss. It is pretty unoptimized right now and this PR changes that.

image

Main problem with the original one seems to be GC and regex related:

Original:
image

Optimized:
image

Manual Testing

Benchmark script (copy and paste this in the Chrome dev tools, ai generated):

function splitShadowRootCss(css) {
  let shadowCss = css;
  let documentCss = "";

  const rulesRegex = /(\s*@(property|font-face)[\s\S]*?{[\s\S]*?})/gm;
  let match;
  while ((match = rulesRegex.exec(css)) !== null) {
    documentCss += match[1];
    shadowCss = shadowCss.replace(match[1], "");
  }

  return {
    documentCss: documentCss.trim(),
    shadowCss: shadowCss.trim(),
  };
}

const AT_RULE_BLOCKS = /(\s*@(property|font-face)[\s\S]*?{[\s\S]*?})/gm;

function splitShadowRootCssOptimized(css) {
  const documentCss = Array.from(css.matchAll(AT_RULE_BLOCKS), (m) => m[0])
    .join("")
    .trim();
  const shadowCss = css.replace(AT_RULE_BLOCKS, "").trim();

  return {
    documentCss,
    shadowCss,
  };
}

function generateTestCss(size = 5000) {
  const rule =
    `  @property --x { syntax: "<color>"; inherits: true; initial-value: red; }\n` +
    `\t@font-face { font-family: "Test"; src: url("test.woff2"); }\n` +
    `.foo { color: blue; background: var(--x); }\n` +
    `\n/* comment */\n  .bar{font-family:"Test"}\n\n` +
    `@supports (font-variation-settings: "wght" 400) { .baz { letter-spacing: 0; } }\n`;
  return rule.repeat(size);
}

function assertEqual(a, b, label) {
  const same = a.documentCss === b.documentCss && a.shadowCss === b.shadowCss;
  if (!same) {
    console.error(`❌ Validation failed: ${label}`);
    process.exit(1);
  }
}

function benchmark(fn, css, label, iterations = 1000) {
  for (let i = 0; i < 5; i++) fn(css);

  const start = performance.now();
  for (let i = 0; i < iterations; i++) fn(css);
  const end = performance.now();

  const total = end - start;
  const avg = total / iterations;
  console.log(
    `${label}: total ${total.toFixed(2)} ms (${avg.toFixed(3)} ms avg per run)`
  );
}

const css = generateTestCss(500);

console.log("Benchmarking splitShadowRootCss (1000 iterations)...\n");

const resultOriginal = splitShadowRootCss(css);
const resultOptimized = splitShadowRootCssOptimized(css);
assertEqual(
  resultOriginal,
  resultOptimized,
  "Outputs differ between implementations"
);

console.log("✅ Validation passed — outputs are identical.\n");

benchmark(splitShadowRootCss, css, "Original");
benchmark(splitShadowRootCssOptimized, css, "Optimized");

console.log("\n✅ Done.");

Related Issue

None

@netlify
Copy link

netlify bot commented Oct 13, 2025

Deploy Preview for creative-fairy-df92c4 ready!

Name Link
🔨 Latest commit 1f4c181
🔍 Latest deploy log https://app.netlify.com/projects/creative-fairy-df92c4/deploys/68ffdcfb19419900083c2a51
😎 Deploy Preview https://deploy-preview-1934--creative-fairy-df92c4.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@ZerGo0 ZerGo0 changed the title chore: optimize splitShadowRootCss ref: optimize splitShadowRootCss Oct 13, 2025
Copy link
Member

@aklinker1 aklinker1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, great find. I need to get better at this sort of performance optimization.

@aklinker1 aklinker1 changed the title ref: optimize splitShadowRootCss fix: Optimize splitShadowRootCss Oct 27, 2025
@codecov
Copy link

codecov bot commented Oct 27, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 81.29%. Comparing base (d28a5c7) to head (1f4c181).
⚠️ Report is 6 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1934      +/-   ##
==========================================
- Coverage   81.31%   81.29%   -0.03%     
==========================================
  Files         131      131              
  Lines        6680     6677       -3     
  Branches     1096     1098       +2     
==========================================
- Hits         5432     5428       -4     
- Misses       1238     1239       +1     
  Partials       10       10              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Oct 27, 2025

Open in StackBlitz

@wxt-dev/analytics

npm i https://pkg.pr.new/@wxt-dev/analytics@1934

@wxt-dev/auto-icons

npm i https://pkg.pr.new/@wxt-dev/auto-icons@1934

@wxt-dev/browser

npm i https://pkg.pr.new/@wxt-dev/browser@1934

@wxt-dev/i18n

npm i https://pkg.pr.new/@wxt-dev/i18n@1934

@wxt-dev/module-react

npm i https://pkg.pr.new/@wxt-dev/module-react@1934

@wxt-dev/module-solid

npm i https://pkg.pr.new/@wxt-dev/module-solid@1934

@wxt-dev/module-svelte

npm i https://pkg.pr.new/@wxt-dev/module-svelte@1934

@wxt-dev/module-vue

npm i https://pkg.pr.new/@wxt-dev/module-vue@1934

@wxt-dev/runner

npm i https://pkg.pr.new/@wxt-dev/runner@1934

@wxt-dev/storage

npm i https://pkg.pr.new/@wxt-dev/storage@1934

@wxt-dev/unocss

npm i https://pkg.pr.new/@wxt-dev/unocss@1934

@wxt-dev/webextension-polyfill

npm i https://pkg.pr.new/@wxt-dev/webextension-polyfill@1934

wxt

npm i https://pkg.pr.new/wxt@1934

commit: 1f4c181

@aklinker1 aklinker1 merged commit 3f4e32f into wxt-dev:main Oct 27, 2025
18 of 19 checks passed
@github-actions
Copy link
Contributor

Thanks for helping make WXT better!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants