Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf: use svg sprite for icons #16135

Merged
merged 23 commits into from
Aug 8, 2024
Merged

perf: use svg sprite for icons #16135

merged 23 commits into from
Aug 8, 2024

Conversation

G3root
Copy link
Contributor

@G3root G3root commented Aug 8, 2024

What does this PR do?

Rendering icons as JSX components is expensive and significantly increases the size of your bundle. This PR aims to address that by replacing them with SVG sprite icons, which are cacheable and faster than the JS based solution.

here's a explanation why we shouldn't import SVG icons as JSX https://twitter.com/_developit/status/1382838799420514317?lang=en

Note

Since this change is one-to-one with the previous implementation, it might still introduce some regressions, so it needs to be tested thoroughly

here's how it's looks like after the changes

Screencast.2024-08-08.18.45.30.webm

Mandatory Tasks (DO NOT REMOVE)

  • I have self-reviewed the code (A decent size PR without self-review might be rejected).
  • I have added a Docs issue here if this PR makes changes that would require a documentation change. If N/A, write N/A here and check the checkbox.
  • I confirm automated tests are in place that prove my fix is effective or that my feature works.

Copy link

vercel bot commented Aug 8, 2024

@G3root is attempting to deploy a commit to the cal Team on Vercel.

A member of the Team first needs to authorize it.

@dosubot dosubot bot added the performance area: performance, page load, slow, slow endpoints, loading screen, unresponsive label Aug 8, 2024
@graphite-app graphite-app bot requested a review from a team August 8, 2024 14:32
@graphite-app graphite-app bot added the community Created by Linear-GitHub Sync label Aug 8, 2024
@graphite-app graphite-app bot requested a review from a team August 8, 2024 14:32
Copy link

graphite-app bot commented Aug 8, 2024

Graphite Automations

"Add community label" took an action on this PR • (08/08/24)

1 label was added to this PR based on Keith Williams's automation.

"Add foundation team as reviewer" took an action on this PR • (08/08/24)

1 reviewer was added to this PR based on Keith Williams's automation.

"Add consumer team as reviewer" took an action on this PR • (08/08/24)

1 reviewer was added to this PR based on Keith Williams's automation.

import glob from "fast-glob";
import fs from "fs-extra";
import path from "node:path";

Copy link
Contributor Author

Choose a reason for hiding this comment

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

script to import svg from lucide icons

// icon name from lucide-react
// this list is extracted based on what icons are currently used
export const lucideIconList = new Set([
"x",
Copy link
Contributor Author

Choose a reason for hiding this comment

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

list of icon names used throughout the app

Copy link
Member

Choose a reason for hiding this comment

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

if we want to add a new icon, we have to add it here?

@@ -0,0 +1,641 @@
<?xml version="1.0" encoding="UTF-8"?>
Copy link
Contributor Author

Choose a reason for hiding this comment

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

sprite sheet generated from build-icons command

@@ -20,7 +20,8 @@
"type-check": "tsc --pretty --noEmit",
"type-check:ci": "tsc-absolute --pretty --noEmit",
"lint:fix": "eslint . --fix",
"lint:report": "eslint . --format json --output-file ../../lint-results/ui.json"
"lint:report": "eslint . --format json --output-file ../../lint-results/ui.json",
"build-icons": "node ./scripts/build-icons.mjs"
Copy link
Contributor Author

Choose a reason for hiding this comment

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

command to generate the sprite sheet when new icons are added to the list

Copy link

New and removed dependencies detected. Learn more about Socket for GitHub ↗︎

Package New capabilities Transitives Size Publisher
npm/@calcom/platform-libraries@0.0.2 environment, network, unsafe 0 3.55 MB morgan-calcom
npm/@calcom/platform-libraries@0.0.23 environment, network, unsafe 0 3.7 MB lauris-cal
npm/@golevelup/ts-jest@0.4.0 None 0 20.1 kB wonderpanda
npm/@microsoft/microsoft-graph-types-beta@0.42.0-preview None 0 3.41 MB microsoftgraph
npm/@nestjs/bull@10.2.0 None +1 84.4 kB nestjscore
npm/@nestjs/cli@10.4.2 Transitive: environment, eval, filesystem, network, shell, unsafe +47 5.81 MB nestjscore
npm/@nestjs/common@10.3.10 None +1 494 kB nestjscore
npm/@nestjs/config@3.2.3 environment, filesystem +1 63.4 kB nestjscore
npm/@nestjs/core@10.3.10 environment, unsafe Transitive: filesystem, network, shell +5 804 kB nestjscore
npm/@nestjs/jwt@10.2.0 None +13 252 kB nestjscore
npm/@nestjs/passport@10.0.3 None 0 21.2 kB nestjscore
npm/@nestjs/platform-express@10.3.10 network Transitive: environment, filesystem, unsafe +37 1.04 MB nestjscore
npm/@nestjs/schematics@10.1.3 Transitive: eval, filesystem, network, unsafe +16 2.7 MB nestjscore
npm/@nestjs/swagger@7.4.0 Transitive: environment, eval, filesystem +7 14.8 MB nestjscore
npm/@nestjs/testing@10.3.10 None 0 34.7 kB nestjscore
npm/@nestjs/throttler@5.2.0 None 0 203 kB nestjscore
npm/@sentry/nextjs@8.24.0 environment, filesystem, network Transitive: eval, shell, unsafe +225 143 MB sentry-bot
npm/@types/cookie-parser@1.4.7 None 0 5.67 kB types
npm/@types/fs-extra@11.0.4 None +1 42.5 kB types
npm/@types/jest@29.5.12 Transitive: environment +12 586 kB types
npm/@types/luxon@3.4.2 None 0 120 kB types
npm/@types/node@20.14.14 None +1 2.17 MB types
npm/@types/passport-jwt@3.0.13 None +3 71.7 kB types
npm/@types/supertest@2.0.16 None +3 40.6 kB types
npm/body-parser@1.20.2 network Transitive: filesystem, unsafe +10 396 kB dougwilson
npm/bull@4.16.0 filesystem, shell Transitive: environment, eval, network, unsafe +12 2.79 MB manast
npm/class-transformer@0.5.1 None 0 776 kB typestack-release-bot
npm/class-validator@0.14.1 None +2 13.5 MB typestack-release-bot
npm/connect@3.7.0 environment, network Transitive: filesystem +11 229 kB dougwilson
npm/cookie-parser@1.4.6 None +2 34.1 kB dougwilson
npm/dotenv@16.4.5 environment, filesystem 0 79.1 kB motdotla
npm/fs-extra@11.2.0 Transitive: filesystem +1 74.7 kB ryanzim
npm/googleapis@84.0.0 Transitive: environment, filesystem, network, shell +22 94.2 MB google-wombot
npm/helmet@7.1.0 None 0 102 kB evanhahn
npm/http-proxy-middleware@2.0.6 network +5 2.48 MB chimurai
npm/http@0.0.1-security None 0 464 B andreeleuterio
npm/ioredis@5.4.1 network +7 847 kB ioredis-robot
npm/jest@29.7.0 Transitive: environment, eval, filesystem, network, shell, unsafe +108 3.75 MB simenb
npm/luxon@3.5.0 None 0 4.48 MB icambron
npm/memory-cache@0.2.0 None 0 36.7 kB ptarjan
npm/nest-winston@1.10.0 environment +1 71.3 kB gremo
npm/nestjs-throttler-storage-redis@0.4.4 None +1 363 kB kkoomen
npm/next-api-middleware@1.0.1 Transitive: environment +2 85.9 kB htunnicliff
npm/next-auth@4.24.7 environment, network Transitive: filesystem, shell, unsafe +25 1.2 GB thvu
npm/next-axiom@0.17.0 environment, network +1 428 kB lukasmalkmus
npm/next-swagger-doc@0.3.6 Transitive: environment, filesystem, network, shell +24 4.89 MB jellydn
npm/next-validations@0.2.1 eval 0 273 kB jellydn
npm/next@13.5.6 environment, filesystem, network, shell, unsafe +25 1.12 GB vercel-release-bot
npm/node-mocks-http@1.15.1 environment, network Transitive: eval, filesystem +23 2.54 MB eugef
npm/passport-jwt@4.0.1 None +13 244 kB themikenicholson
npm/passport@0.7.0 network +3 168 kB jaredhanson
npm/querystring@0.2.1 None 0 9.39 kB medikoo
npm/reflect-metadata@0.1.14 None 0 295 kB rbuckton
npm/rxjs@7.8.1 None 0 4.5 MB blesh
npm/stripe@15.12.0 network, shell +1 5.02 MB stripe-bindings
npm/supertest@6.3.4 network Transitive: environment, filesystem +10 1.05 MB titanism
npm/tzdata@1.0.40 None 0 444 kB rogierschouten

🚮 Removed packages: npm/@formkit/auto-animate@1.0.0-beta.5, npm/@types/detect-port@1.3.5, npm/@types/lodash@4.17.7, npm/@types/mime-types@2.1.4, npm/@types/node@16.9.1, npm/classnames@2.5.1, npm/ical.js@1.5.0, npm/rrule@2.8.1

View full report↗︎

@anikdhabal anikdhabal added the high-risk Requires approval by Foundation team label Aug 8, 2024
Copy link
Member

@PeerRich PeerRich left a comment

Choose a reason for hiding this comment

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

this looks all fun and games but what is the actual performance difference?

@PeerRich
Copy link
Member

PeerRich commented Aug 8, 2024

requesting @zomars review here as he worked on the Icon component the most

@PeerRich PeerRich added this to the Community Only milestone Aug 8, 2024
@PeerRich PeerRich added the Medium priority Created by Linear-GitHub Sync label Aug 8, 2024
Copy link
Member

Choose a reason for hiding this comment

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

I appreciate the README 🙏🏽

@zomars
Copy link
Member

zomars commented Aug 8, 2024

Got some missing icons
image

@@ -20,7 +20,8 @@
"type-check": "tsc --pretty --noEmit",
"type-check:ci": "tsc-absolute --pretty --noEmit",
"lint:fix": "eslint . --fix",
"lint:report": "eslint . --format json --output-file ../../lint-results/ui.json"
"lint:report": "eslint . --format json --output-file ../../lint-results/ui.json",
"build-icons": "node ./scripts/build-icons.mjs"
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
"build-icons": "node ./scripts/build-icons.mjs"
"build:icons": "node ./scripts/build-icons.mjs"

To match the READMEs and comments

Copy link
Member

Choose a reason for hiding this comment

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

Sorted alphabetically

@zomars zomars merged commit da5df71 into calcom:main Aug 8, 2024
27 of 35 checks passed
@sean-brydon
Copy link
Member

CleanShot 2024-08-09 at 11 22 23
This commit caused password inputs and any inputs with addon-leading/suffix to break massively

@PeerRich
Copy link
Member

PeerRich commented Aug 9, 2024

this looks all fun and games but what is the actual performance difference?

do we know the performance difference @G3root ??

@G3root
Copy link
Contributor Author

G3root commented Aug 9, 2024

@PeerRich here's the breakdown

  • The gzipped final bundle size went from 8.29 MB to 5.95 MB according to next-bundle-analyzer.
  • The first load JS for all pages went from 233 KB to 195 KB.
  • While testing /apps/installed/analytics in an incognito tab, the JS bundle size went from 6.26 MB to 5.95 MB, and the load time decreased from 2.26 s to 1.80 s.

before

Screenshot 2024-08-09 at 20-19-38 @calcom_web 9 Aug 2024 at 20 12

Screenshot 2024-08-09 20:21:49

Screenshot 2024-08-09 20:24:02

after

Screenshot 2024-08-09 at 18-54-50 @calcom_web 9 Aug 2024 at 18 52

Screenshot 2024-08-09 19:01:30

Screenshot 2024-08-09 19:04:35

@G3root
Copy link
Contributor Author

G3root commented Aug 9, 2024

Here’s an example of before and after. Before, when refreshing the page, the icons would flicker and show a skeleton. After, the icons no longer flash during refresh. there are some frame drops in the video due to my screen recorder

before

Screencast.2024-08-09.20.24.56.webm

after

Screencast.2024-08-09.20.41.25.webm

@Ryukemeister
Copy link
Contributor

Ryukemeister commented Aug 11, 2024

@G3root what if we want to use the Icon component outside of the web app, won't that cause the icons to break in this case since the href is tied to the web app path e.g. <use href={/icons/sprite.svg#${name}} /> ? Should not there be a fallback in case we're using this anywhere outside of the web app?

@zomars
Copy link
Member

zomars commented Aug 16, 2024

Just a heads up there's a fix for SVG and CORS in here #16244

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
community Created by Linear-GitHub Sync high-risk Requires approval by Foundation team Medium priority Created by Linear-GitHub Sync performance area: performance, page load, slow, slow endpoints, loading screen, unresponsive ready-for-e2e
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants