docusaurus icon indicating copy to clipboard operation
docusaurus copied to clipboard

Do not use React svg components for regularly used icons

Open slorber opened this issue 4 years ago • 9 comments

Have you read the Contributing Guidelines on issues?

Motivation

This issue about updating the number of visible archived versions in the version dropdown lead to a weird build size diff on HTML files:

https://github.com/facebook/docusaurus/pull/5862#issuecomment-958881323

The diff in size is due to using an inlined SVG component for external links 😅 the SVG markup is duplicated in the HTML file for each item

image

For reusable icons of our theme, we should rather require an svg file instead of using a React SVG component, to reduce HTML output size.

It can have a significant impact on pages with a lot of icons (due to navbar, footer, doc sidebar...)

Self-service

  • [ ] I'd be willing to do some initial work on this proposal myself.

slorber avatar Nov 03 '21 16:11 slorber

Interesting discussion related to this problem: https://twitter.com/_developit/status/1382838799420514317

slorber avatar Dec 01 '21 14:12 slorber

svg sprites look like a good solution: https://benadam.me/thoughts/react-svg-sprites/

slorber avatar Feb 08 '22 15:02 slorber

Related read: https://fotis.xyz/posts/introducing-svg-use/

slorber avatar Sep 02 '24 10:09 slorber

Some recent improvements for icons that are repeated multiple times per page:

  • ExternalLink icon: https://github.com/facebook/docusaurus/pull/10885
  • Code block button icons: https://github.com/facebook/docusaurus/pull/10866

These are the most important cases to optimize because those items are widely used in the content and/or layout.


The next things to optimize are:

  • blog authors' social icons
  • admonitions

These are not as widely used, and sometimes only apply to a single page.

I'd like to use SVG sprites for them too, but I'm not sure inlining the sprites directly into the HTML is a great idea considering this adds weight to pages that may not use these features. Possible solutions could be:

  • to lazy load an external SVG sprite file
  • find a way to inline only what's used in a static page (unfortunately, <Head> does not permit to hoist and deduplicate SVG sprite defs)

slorber avatar Jan 31 '25 16:01 slorber

@slorber, are these improvements transparent upon Docusaurus upgrade or do they require site owners to adjust anything?

PS: I know they were not released yet.

felipecrs avatar Feb 01 '25 15:02 felipecrs

@felipecrs those are implementation details of theme components and do not change any public API. Unless they swizzled unsafe theme components, site owners have nothing to do when upgrading. Our versioning policy applies as usual, with minor releases aiming to be easy to adopt: https://docusaurus.io/community/release-process

slorber avatar Feb 03 '25 11:02 slorber

Awesome, thank you.

felipecrs avatar Feb 03 '25 12:02 felipecrs

But how can I customize this icon?

anonsyn avatar Mar 08 '25 15:03 anonsyn

@anonsyn in any case we always use the sprites through an intermediate @theme/Icon/Xyz component.

This means that you can always swizzle them, and make the React component render an inline SVG with JSX, exactly like we did before:

export default function IconExternalLink() {
  return (
    <svg>
      <path d="..."/>
    </svg>
  );
}

Or you can provide a reference to your own SVG sprite ids, like we do now (more optimized)

If you want to inject new SVG sprites in your page you can use the plugin lifecycle like we do too:

    injectHtmlTags() {
      return {
        preBodyTags: [
          {
            tagName: 'svg',
            attributes: {
              xmlns: 'http://www.w3.org/2000/svg',
              style: 'display: none;',
            },
            innerHTML: `<defs>
<symbol id="my-custom-svg-id1" viewBox="0 0 24 24"><path d="..." /></symbol>
<symbol id="my-custom-svg-id2" viewBox="0 0 24 24"><path d="..." /></symbol>
</defs>`;
          },
       ]
    }; 
export default function IconExternalLink() {
    <svg>
      <use href="my-custom-svg-id1" />
    </svg>
  );
}

slorber avatar Mar 14 '25 17:03 slorber