Skip to content

Comments

[web] Start using icons from Material Symbols #383

Merged
dgdavid merged 13 commits intomasterfrom
drop-eos-icons
Dec 30, 2022
Merged

[web] Start using icons from Material Symbols #383
dgdavid merged 13 commits intomasterfrom
drop-eos-icons

Conversation

@dgdavid
Copy link
Contributor

@dgdavid dgdavid commented Dec 27, 2022

Problem

We've noticed that the bundle dist/index.js file is rather big, a bit over 21M

➜ stat -c %s dist/index.js
21241291

Upon closer inspection, it appears that the EOS Icons package is being imported in full, rather than just the used icons. I.e., for some reason the expected tree-shaking is not working (as expected). See #383 (comment)

Development mode bundle sizes eos-icons @patternfly/react-icons
*** eos-icons-react: 8.34 MB (44.3%)
@patternfly/react-styles: 4.15 MB (22.0%)
*** @patternfly/react-icons: 1.78 MB (9.42%)
@patternfly/react-core: 1.01 MB (5.36%)
react-dom: 874.93 KB (4.53%)
@patternfly/patternfly: 615.24 KB (3.19%)
core-js: 523.87 KB (2.71%)
@remix-run/router: 108.19 KB (0.561%)
react: 70.64 KB (0.366%)
react-router: 47.98 KB (0.249%)
prop-types: 34.04 KB (0.176%)
  react-is: 7.01 KB (20.6%)
  <self>: 27.03 KB (79.4%)
ipaddr.js: 33.19 KB (0.172%)
react-router-dom: 29.72 KB (0.154%)
focus-trap: 27.17 KB (0.141%)
scheduler: 26.34 KB (0.137%)
regenerator-runtime: 24.61 KB (0.128%)
react-dropzone: 23.76 KB (0.123%)
tabbable: 19.23 KB (0.0997%)
tslib: 12.02 KB (0.0623%)
file-selector: 8.57 KB (0.0444%)
@patternfly/react-tokens: 7.41 KB (0.0384%)
attr-accept: 6.79 KB (0.0352%)
css-loader: 2.92 KB (0.0151%)
object-assign: 2.06 KB (0.0107%)
react-teleporter: 670 B (0.00339%)
<self>: 1.13 MB (5.97%)

Screenshot from 2022-12-29 16-36-06

Screenshot from 2022-12-29 16-40-21

That, for sure, has an impact in the needed time to have the UI ready for the user the first time. In fact, the First Contentful Paint (FCP) and Largest Contentful Paint (LCP) web vitals metrics are not good. See #383 (comment)

Solution

Despite not being a size or performance issue with the bundle generated in the production mode see comment below, it seems like a good time to start using the recently released Material Symbols icon set, but importing only the ones needed from https://github.com/marella/material-symbols instead of directly using the variable font.

To ease future updates, the import of icons has also been centralized into the layout/Icon component which (hopefully) will help to avoid having to change all components with icons.

Development mode bundle sizes @material-symbols @patternfly/react-icons
@patternfly/react-styles: 4.15 MB (47.2%)
@patternfly/react-core: 1.01 MB (11.5%)
react-dom: 874.93 KB (9.73%)
@patternfly/patternfly: 615.24 KB (6.84%)
core-js: 523.87 KB (5.83%)
@remix-run/router: 108.19 KB (1.20%)
react: 70.64 KB (0.785%)
react-router: 47.98 KB (0.534%)
prop-types: 34.04 KB (0.379%)
  react-is: 7.01 KB (20.6%)
  <self>: 27.03 KB (79.4%)
ipaddr.js: 33.19 KB (0.369%)
react-router-dom: 29.72 KB (0.331%)
focus-trap: 27.17 KB (0.302%)
scheduler: 26.34 KB (0.293%)
*** @patternfly/react-icons: 26.24 KB (0.292%)
*** @material-symbols/svg-400: 25 KB (0.278%)
regenerator-runtime: 24.61 KB (0.274%)
react-dropzone: 23.76 KB (0.264%)
tabbable: 19.23 KB (0.214%)
tslib: 12.02 KB (0.134%)
file-selector: 8.57 KB (0.0953%)
@patternfly/react-tokens: 7.41 KB (0.0824%)
attr-accept: 6.79 KB (0.0756%)
css-loader: 2.92 KB (0.0324%)
object-assign: 2.06 KB (0.0229%)
react-teleporter: 670 B (0.00728%)
<self>: 1.13 MB (12.9%)

Screenshot from 2022-12-29 16-35-19

Screenshot from 2022-12-29 16-40-44

Why not using the Material Symbols variable font directly?

Because at the moment we're using exactly 23 icons from that font (the animated Loading icon is a custom one). Thus, having all of them on hand "just in case" does not make sense even though the current approach loses most of the main advantages of variable fonts.

Testing

Changes has been tested manually.

To avoid breaking the unit tests, some Jest configuration changes and mocking were needed to deal with the @svgr/webpack package used to transform SVG files into React components.

Screenshots

Before After
Screen Shot 2022-12-29 at 18 42 36 Screen Shot 2022-12-29 at 18 51 55

Next steps

  • Look for a more suitable size/alignment of new icons in the context of keep working on layout improvements.
  • Choose better icons from the current icon set for existing pages, sections, and actions.

Web vitals metrics gathered by https://github.com/GoogleChrome/web-vitals
Treemaps generated by https://github.com/webpack-contrib/webpack-bundle-analyzer
Sizes were collected with https://github.com/robertknight/webpack-bundle-size-analyzer

It transforms SVG icons into React components, which will initially help using
Material Symbol icons imported from @material-symbols/svg package
And stop using icons from eos-icons-react and @patternfly. The only exception,
by now, is the "LoadingIcon", which does not come from @material-icon but from
a local .svg file borrowed from https://github.com/n3r4zzurr0/svg-spinners
For reducing imports and easing the way to use icon, using the original icon
name for importing it.
Because at this time TypeScript's React types rejects function components that
does not return null | JSX.Element.

See microsoft/TypeScript#51328 RFC and follow related
links to known more.

Other links:

* DefinitelyTyped/DefinitelyTyped#18051
* DefinitelyTyped/DefinitelyTyped#62876
* https://stackoverflow.com/a/70895599
To avoid breaking unit test because of the string mock.
@coveralls
Copy link

coveralls commented Dec 29, 2022

Coverage Status

Coverage: 76.117% (+0.01%) from 76.106% when pulling 980edb4 on drop-eos-icons into 8adf9fc on master.

This helps to simplify the Jest configuration and to reduce the mocking too.
It's somehow related to the fact that Jest does not fully support resource
queries, see jestjs/jest#6282
@dgdavid dgdavid changed the title Drop eos icons [web] Drop EOS icons in favor of Material Symbols Dec 29, 2022
@dgdavid dgdavid changed the title [web] Drop EOS icons in favor of Material Symbols [web] Drop EOS/@patternfly icons in favor of Material Symbols Dec 29, 2022
@dgdavid dgdavid marked this pull request as ready for review December 29, 2022 18:53
@dgdavid dgdavid requested a review from imobachgs December 29, 2022 18:54
@dgdavid
Copy link
Contributor Author

dgdavid commented Dec 30, 2022

for some reason the expected tree-shaking is not working (as expected).

Unfortunately, I was working under the wrong assumption when checking the generated bundle: it was the development bundle, not the production one. Rather than generating it with NODE_ENV=production npm run build, I used ENV=production npm run build and that lead to the problem 😞

Use the production mode configuration option to enable various optimizations including minification and tree shaking.

quotation from the Conclusions chapter of Webpack's tree-shaking page

With NODE_ENV=production npm run build the generated bundle (and the obtained web vitals metrics) are practically identical before and after the proposed changes.

Click to show/hide metrics of production build for both branches
before after
➜ ls -alh dist 
total 308K
 4,0K .
 4,0K ..
  59K index.css.gz
  269 index.html.gz
 223K index.js.gz
  406 index.js.LICENSE.txt.gz
  167 manifest.json
  138 po.de.js
{
    "name": "FCP",
    "value": 922,
    "rating": "good",
    "delta": 922,
    ...
}
{
    "name": "LCP",
    "value": 1157,
    "rating": "good",
    "delta": 1157,
    ...
}
➜ ls -alh dist 
total 308K
 4,0K .
 4,0K ..
  59K index.css.gz
  269 index.html.gz
 224K index.js.gz
  406 index.js.LICENSE.txt.gz
  167 manifest.json
  138 po.de.js
{
    "name": "FCP",
    "value": 879.5999999642372,
    "rating": "good",
    "delta": 879.5999999642372,
    ...
}
{
    "name": "LCP",
    "value": 1199,
    "rating": "good",
    "delta": 1199,
    ...
}

However, I would like to merge these changes since they are significant improvements to the code base, especially in development mode 😜

@dgdavid dgdavid changed the title [web] Drop EOS/@patternfly icons in favor of Material Symbols [web] Start using icons from Material Symbols Dec 30, 2022
Copy link
Contributor

@imobachgs imobachgs left a comment

Choose a reason for hiding this comment

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

LGTM. It is a big improvement, and we can switch to a different set of icons if needed in the future.

@imobachgs
Copy link
Contributor

Oh, I forgot: please, add an entry to the changes file.

@dgdavid dgdavid merged commit 32b1bbb into master Dec 30, 2022
@dgdavid dgdavid deleted the drop-eos-icons branch December 30, 2022 12:03
@imobachgs imobachgs mentioned this pull request Feb 13, 2023
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.

3 participants