Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

aeharding
Copy link
Contributor

What is the current behavior?

GitHub Issue Number: None

Since Ionic v8.6.0 I've been experiencing component instance creation performance issues, especially in virtual lists, where it can take items longer to appear. This was originally identified by end users: https://vger.social/post/20787019

I narrowed it down to the stencil upgrade here.

From there I found the regression occurring in Stencil v4.33.0 specifically. When I reverted 33363d4077728793e0c6f635a22dccbb5740be49 the problem went away.

Once I identified the source of the issue, I found some suspicious code that was creating a new CSSStyleSheet every time a new component instance is created.

What is interesting is this performance issue exists even if globalStyles is empty. Simply creating a new CSSStyleSheets and calling replaceSync on an empty string every instantiation is enough to hurt performance.

What is the new behavior?

I have modified the code to only create one global CSSStyleSheet (if necessary) on startup that is appended to adoptedStyleSheets in the createShadowRoot function.

This solves performance issues of using globalStyles. In addition, I added an early return to not create the global style sheet at all, if globalStyles is empty. This doesn't seem to affect perf, just makes the DX a bit nicer by not having a useless/empty CSSStyleSheet in the adoptedStyleSheets array.

Documentation

Does this introduce a breaking change?

  • Yes
  • No

Testing

I tested these changes against Voyager by building stencil, building ionic, and finally installing in Voyager.

Other information

@aeharding aeharding requested a review from a team as a code owner June 27, 2025 22:34
aeharding added a commit to aeharding/voyager that referenced this pull request Jun 27, 2025
aeharding added a commit to aeharding/voyager that referenced this pull request Jun 27, 2025
Copy link
Member

@christian-bromann christian-bromann left a comment

Choose a reason for hiding this comment

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

Great patch 👌 LGTM

* This singleton avoids the performance and memory hit of
* creating a new CSSStyleSheet every time a shadow root is created.
*/
export const globalStyleSheet = createStyleSheetIfNeededAndSupported(globalStyles);
Copy link
Member

Choose a reason for hiding this comment

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

It seems like the way the runtime is bundled doesn't allow to initiate it at the root level? Maybe we can do something like:

let globalStyleSheet

export function createShadowRoot(this: HTMLElement, cmpMeta: d.ComponentRuntimeMeta) {
  const shadowRoot = BUILD.shadowDelegatesFocus
    ? this.attachShadow({
        mode: 'open',
        delegatesFocus: !!(cmpMeta.$flags$ & CMP_FLAGS.shadowDelegatesFocus),
      })
    : this.attachShadow({ mode: 'open' });

  /**
   * If constructable stylesheets are supported, we can use them to
   * add the global styles to the shadow root.
   */
  if (supportsConstructableStylesheets) {
    const sheet = new CSSStyleSheet();
    sheet.replaceSync(globalStyles);
    shadowRoot.adoptedStyleSheets.push(sheet);
  }
  if (!globalStyleSheet) {
    globalStyleSheet = createStyleSheetIfNeededAndSupported(globalStyles)
    shadowRoot.adoptedStyleSheets.push(globalStyleSheet)
  };
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Interesting! I wonder why it worked in Voyager but not the test environment. I just added lazy initialization. Although, if it's possible rejigger the build to avoid that error in the first place, that would probably be a cleaner solution than the lazy initializer.

Lmk what you think!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Decided to do a simpler approach in 1414c08. lmk if you like it, or 20d4046 better.

Copy link
Member

@christian-bromann christian-bromann left a comment

Choose a reason for hiding this comment

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

LGTM 👍

@christian-bromann christian-bromann merged commit fe5d130 into stenciljs:main Jun 29, 2025
70 checks passed
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