Slide 1

Slide 1 text

How to improve frontend performance ⚑ ta1m1kam 🐯

Slide 2

Slide 2 text

Why is performance important? πŸ€”

Slide 3

Slide 3 text

https://web.dev/why-speed-matters/ β€œPerformance has directly impacted the company's bottom line.” by Pinterest > Pinterest reduced perceived wait times by 40% and this increased search engine traffic and sign-ups by 15%. Performance is about improving conversions Performance is about user experience Performance is about people

Slide 4

Slide 4 text

In Shippioβ›΄ ? β­• Good experience makes customers pay for Shippio app ❌ Bad experience makes customers leave

Slide 5

Slide 5 text

Performance = πŸ’°

Slide 6

Slide 6 text

What is the most important thing to improve performance? πŸ€”

Slide 7

Slide 7 text

Measurement⏱ γ€œ Measure, Don’t guess γ€œ

Slide 8

Slide 8 text

Lighthouse is an open-source, automated tool for improving the performance Lighthouse

Slide 9

Slide 9 text

Trying to measure shipment list page 󰝊

Slide 10

Slide 10 text

FCP https://web.dev/i18n/en/lcp/ First Contentful Paint (FCP) metric measures the time from when the page starts loading to when any part of the page's content is rendered on the screen. https://web.dev/i18n/en/fcp/ SI Speed Index (SI) is a page load performance metric that shows you how quickly the contents of a page are visibly populated. https://developer.mozilla.org/en-US/docs/Glossary/Speed_index https://developer.chrome.com/docs/lighthouse/performance/speed-index/ LCP Largest Contentful Paint (LCP) metric reports the render time of the largest image or text block visible within the viewport, relative to when the page first started loading.

Slide 11

Slide 11 text

TTI https://web.dev/i18n/en/cls/ https://web.dev/evolving-cls/ TTI metric measures the time from when the page starts loading to when its main sub-resources have loaded and it is capable of reliably responding to user input quickly. https://web.dev/i18n/en/tti/ TBT Total Blocking Time (TBT) metric measures the total amount of time between First Contentful Paint (FCP) and Time to Interactive (TTI) where the main thread was blocked for long enough to prevent input responsiveness. https://web.dev/i18n/en/tbt/ CLS CLS is a measure of the largest burst of layout shift scores for every unexpected layout shift that occurs during the entire lifespan of a page.

Slide 12

Slide 12 text

Performance tab more details about each process σ°‘·

Slide 13

Slide 13 text

Bottom-up shows which scripts are slow 🐒

Slide 14

Slide 14 text

Performance.now() Focus on the specific process const t0 = performance.now(); doSomething(); ← Target const t1 = performance.now(); console.log(`Call to doSomething took ${t1 - t0} milliseconds.`); Call to doSomething took 11088.40000000596 milliseconds. Code Output (console.log)

Slide 15

Slide 15 text

Other Tools

Slide 16

Slide 16 text

Regular measurement with CI https://docs.datadoghq.com/integrations/lighthouse/ Lighthouse CLI : https://github.com/GoogleChrome/lighthouse Measurement Workflow Datadog could also do this?

Slide 17

Slide 17 text

Critical Rendering Path πŸ—Ί

Slide 18

Slide 18 text

Request Web page GET HTML Build DOM GET CSS GET JavaScript Build CSSOM Run JavaScript Render Page Idle Block Critical Rendering Path Network Process Rendering Process Start Goal Load HTML Documents Load Subresources Rendering

Slide 19

Slide 19 text

β‘  To transfer as little data as possible β‘‘ To transfer data as few times as possible β‘’ To keep the data transfer distance as short as possible Principles of optimisation of network part β‘  request β‘‘ request β‘’ data data far close

Slide 20

Slide 20 text

Improvement πŸ”§

Slide 21

Slide 21 text

Lighthouse tells us what to improve ● Enable text compresion ● Reduce unused JavaScript ● Reduce unused CSS

Slide 22

Slide 22 text

Resources πŸ“¦

Slide 23

Slide 23 text

Bundle Analyzer Webpack Bundle Analyzer https://github.com/webpack-contrib/webpack-bundle-analyzer Rollup Plugin Visualizer https://github.com/btd/rollup-plugin-visualizer You can find which package is big.

Slide 24

Slide 24 text

βœ… Using other packages βœ… Not Using packages Remove too big packages eg.) Lodash β†’ Rewriting to Vanilla JavaScript icons package β†’ Rewriting to SVG (Import only you need) css-ui package β†’ Rewriting to Pure CSS eg.) moment.js β†’ change to other package (day.js, date-fns) react-router β†’ wouter

Slide 25

Slide 25 text

Compression of the image Converting images to WebP or AVIF etc… Converting font to WOFF2 Assets Optimization https://github.com/GoogleChromeLabs/squoosh πŸ–Ό Images ✏ Fonts https://github.com/papandreou/subset-font β€»Some browsers are still not supported. Our clients may be using even older browsers 😩 https://github.com/imagemin/imagemin-cli

Slide 26

Slide 26 text

Assets are delivered via CDN. Assets Optimization

Slide 27

Slide 27 text

Network 🌐

Slide 28

Slide 28 text

HTTP3 is even faster with QUIC and UDP instead of TCP protocol. HTTP1 βœ• / HTTP2 β—― / HTTP3 β—Ž (depending on the browser)

Slide 29

Slide 29 text

Apps should be compressed by Brotil algorithm. Content encoding https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding https://firebase.blog/posts/2020/08/firebase-hosting-new-features Firebase hosting does everything automatically. πŸ‘πŸ‘

Slide 30

Slide 30 text

Server-Side Rendering Client Server Client Server Initial request

Slide 31

Slide 31 text

Parallel Request async function notUsePromiseAll() { console.log('Start!!'); const response1 = await fetch("https://example.com/api/1"); const response2 = await fetch("https://example.com/api/2"); console.log('End!!'); } async function usePromiseAll() { console.log('Start!!'); const [response1, response2] = await Promise.all([ fetch("https://example.com/api/1"), fetch("https://example.com/api/2"), ]); console.log('End!!'); } Good πŸ‘ Bad πŸ‘Ž fetch 1 fetch 2 fetch 1 fetch 2 Use Promise.all() time time

Slide 32

Slide 32 text

Using Skeleton Improve the score for CLS You can create the frame for the data after loading in advance Make for great user experiences To make the page loading speed feel faster for users

Slide 33

Slide 33 text

React Tips

Slide 34

Slide 34 text

Reduce Chunk Size Per Page React.lazy + Suspence import React, { Suspense, lazy } from 'react'; import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; const Home = lazy(() => import('./routes/Home')); const About = lazy(() => import('./routes/About')); const App = () => ( Loading...}> } /> } /> ); File sizes after gzip: 322.74 KB (+180.2 KB) build/static/js/18.aa12ce15.chunk.js 235.25 KB (+231.59 KB) build/static/js/28.a0c7e83f.chunk.js Home Component About Component Can download the required JS for each page. 😎 FYI: Similar solution

Slide 35

Slide 35 text

Reduce Chunk Size Per Page import { lazy } from 'react'; ... { path: '/dashboard', component: lazy(() => import('../pages/dashboard/Dashboard')), }, { path: '/shipment', component: lazy(() => import('../pages/shipments/ShipmentsContainer')), }, { path: '/shipments', component: lazy(() => import('../pages/shipments/ShipmentsContainer')), }, { path: '/quote', component: lazy(() => import('../../pages/quote/RoutesContainer/RoutesContainer')), }, ... File sizes after gzip: 322.74 KB (+180.2 KB) build/static/js/18.aa12ce15.chunk.js 235.25 KB (+231.59 KB) build/static/js/28.a0c7e83f.chunk.js 229.81 KB (-107 B) build/static/css/11.c8964559.chunk.css 154.53 KB (-14.75 KB) build/static/js/11.183c1d8c.chunk.js 132.47 KB (-211.45 KB) build/static/js/16.828d24e0.chunk.js 132.47 KB (-10.07 KB) build/static/js/17.96b0ee45.chunk.js 119.37 KB (-10.42 KB) build/static/js/12.59c03137.chunk.js Router file Build Output https://webpack.js.org/plugins/split-chunks-plugin/#optimizationsplitchunks SplitChunksPlugin Improve bit moreβ€¦πŸ€”?

Slide 36

Slide 36 text

Why-did-you-render React Memorization Avoid unnecessary re-rendering https://github.com/welldone-software/why-did-you-render ● React.memo() ● useCallback() ● useMemo() How to find the components to be adapted.β€¦πŸ€”

Slide 37

Slide 37 text

(to get backend response faster.) ● Scaling Sever ● SQL optimisation ● Thread handling ● Giving more detail properties to html tags ● Tuning Contents Cache-Policy ● Tuning Graphql Client Cache-Policy (Apollo-Client) ● Prefetch resources: preconnect, dns-prefetch, preload ● Using ServiceWorker ● WebAssembly Other Tips Improve Backend