How to optimize web responsiveness with Interaction to Next Paint

How to optimize web responsiveness with Interaction to Next Paint


How to optimize web responsiveness with Interaction to Next Paint

Dive into Interaction to Next Paint (INP), the newest performance metric in the Web Vitals program. Learn from the Chrome team how INP works and see how to use it to diagnose input responsiveness issues. One third of websites still struggle to meet the 200ms threshold for ""good"" INP. See what real-world sites did to improve their INP and how it affected their bottom line.

Resources:
INP documentation → https://goo.gle/3U7rUuF
Optimize INP guide → https://goo.gle/40YEgYe
Optimize long tasks guide → https://goo.gle/3ZMFHbc

Speakers: Annie Sullivan, Michal Mocny

Watch more:
Watch all the Technical Sessions from Google I/O 2023 → https://goo.gle/IO23_sessions
Watch more Web Sessions → https://goo.gle/IO23_web
All Google I/O 2023 Sessions → https://goo.gle/IO23_all

Subscribe to Google Chrome Developers → https://goo.gle/ChromeDevs

#GoogleIO


Content

0.84 -> foreign
4.799 -> hi everyone I'm Annie Sullivan and I'm
8.22 -> Michael mockney we're Engineers on
11.04 -> Chrome web platform team
12.9 -> our team focuses on the core web vitals
15.78 -> metrics and today we want to talk to you
18.6 -> about interaction to next paint
21.66 -> as you heard in the keynote interaction
24.06 -> to next paint or inp for short is set to
28.08 -> replace first input delay as a core web
30.66 -> vital
31.619 -> in this talk we're going to review the
34.2 -> background from last year's talk on what
36.48 -> imp is then dig into a demo where we
40.079 -> show you how to optimize it and finally
42.36 -> show you some real world examples of how
45.18 -> sites optimize their own imp
48.539 -> first let's start off with a recap from
51.899 -> last year's talk if you'd like to watch
54.12 -> the whole talk click the video link in
56.46 -> the corner
57.66 -> the core web vitals metrics are designed
60.48 -> to measure your site's performance and
63.059 -> user experience you can check your
65.519 -> site's scores and get recommendations to
68.28 -> improve in tools like page speed
70.38 -> insights the Chrome user experience
72.6 -> report Lighthouse and chrome Dev tools
76.68 -> there are three core web vitals metrics
79.799 -> largest contentful paint measures how
82.259 -> long it takes a web page to load
84.659 -> cumulative layout shifts measures how
87.18 -> much content unexpectedly shifts around
89.52 -> the page and first input delay measures
92.759 -> how long it takes for the page to start
94.979 -> processing the first user interaction
98.4 -> first input delay is the metric we feel
101.1 -> needs an update
102.78 -> it has some major gaps that we want to
105.36 -> address
106.439 -> first it's very focused on the initial
109.32 -> page load only measuring the very first
112.259 -> interaction on the page but ninety
115.079 -> percent of user time on a web page is
117.42 -> spent after the initial load
120.18 -> second it only measures the time until
123.24 -> the browser starts processing the
125.219 -> interaction
126.479 -> so we have introduced imp to replace it
130.02 -> as a core web item inp measures the time
133.26 -> from each tap click or key press on the
137.04 -> page until the next update to this
139.14 -> screen
140.099 -> we feel it captures the user experience
142.44 -> of a web page much better than first
144.78 -> input delay
146.34 -> here's an example of the type of
148.379 -> frustrating user experience that imp
150.42 -> captures
151.68 -> the user tries to click on the menu but
154.68 -> it's slow to respond and it looks like
156.9 -> nothing happened
158.22 -> so they click again but it turns out the
161.4 -> first click did open the menu only
163.379 -> slowly and now their second click closes
165.959 -> it again
166.92 -> I've had this happen to me before and
169.319 -> it's very annoying
170.94 -> when the user clicks the same spot
172.739 -> multiple times in a row like this it's
175.379 -> called a rage click and it's a sign of
177.84 -> user frustration in Chrome we see that
181.08 -> on page loads with poor imp times users
183.84 -> are much more likely to rage click
186.72 -> so how do you make sure that your page
189.12 -> has Snappy interactions and happy user
191.879 -> first you need to look at how your
193.92 -> site's doing you can see how fast
196.14 -> interactions for real users in Chrome
198.18 -> are using page speed insights or the
200.7 -> Chrome user experience report they'll
202.62 -> break it down so you can see how many of
204.78 -> your users are getting experiences that
206.4 -> are good need Improvement or poor
209.94 -> but what do you do if your users are
211.739 -> seeing poor imp Michael has put together
214.26 -> a demo to help us dig into understanding
216.659 -> and improving interactions Michael take
219.239 -> it away
220.68 -> [Music]
223.019 -> thanks Annie hi folks I'm Michael and I
225.959 -> work with Annie on the Chrome web
227.34 -> platform speed metrics team
229.26 -> I have a bit of a passion for sailing
231.299 -> which means I always find myself
233.12 -> daydreaming about sailboats that's why I
236.099 -> decided to take this opportunity to
238.26 -> create a very simple app about boats
241.019 -> nothing fancy just the search box with
243.48 -> autocomplete search results I'll be
245.879 -> searching through some Json data
247.739 -> entirely client-side here
250.08 -> at this point I haven't implemented
252.12 -> proper search yet but let's go see what
254.28 -> the app shell feels like
256.199 -> for now when I type into the search box
258.72 -> only random results appear below I'll
261.9 -> fix that in a moment but how's the app
264.36 -> performing
265.38 -> it certainly feels pretty Snappy to me
267.479 -> but how can I know exactly how so
270.72 -> let's use inp to measure
273.36 -> now I could jump immediately into the
276.54 -> performance panel in devtools but I
279.6 -> prefer to do that only once I know I
281.699 -> have something specific to diagnose
284.22 -> when I'm just getting started debugging
286.32 -> interactivity I find it helpful to just
288.9 -> monitor the performance of each
290.82 -> individual interaction as it happens
293.4 -> for that I like to use console logging
296.04 -> which you can find in the web vitals
297.96 -> Chrome extension or you can add your own
300.54 -> logs using JavaScript let's take a look
303.84 -> I've already added the Imp JavaScript
306.24 -> snippet to this page so I can see a
308.759 -> real-time log of each part of every
310.74 -> interaction
311.82 -> ideally most interactions would come in
314.46 -> under 100 milliseconds but the threshold
317.16 -> for a good inp is 200.
319.919 -> looks like this is performing very well
321.84 -> so far so let's go Implement search
324.96 -> as a first attempt let's create a simple
327.6 -> filter results function we'll call this
330.539 -> function from our autocomplete component
332.34 -> every time we get a new search term
335.4 -> it will search through all items in our
337.74 -> Json assign a score to each and then
340.5 -> sort so that we can show the top results
342.6 -> let's try that out
345.74 -> well the search results certainly look a
348.96 -> lot more accurate but now the app
351.419 -> suddenly feels a lot more sluggish
353.52 -> I don't mean that it just takes a while
355.32 -> to load in search results over the
356.94 -> network or something I mean I can't even
359.039 -> see what I'm typing because the page
360.84 -> goes completely Frozen that's what inp
364.08 -> measures the ability of the browser to
366.9 -> show changes at all
368.82 -> this feels painful and looking at the
371.16 -> console the Imp metric reflects that too
374.58 -> the problem is our filter results
376.919 -> function is slow and it blocks every one
380.52 -> of our rendering updates what we really
382.8 -> want to do is to split the update update
385.979 -> the search box first quickly maybe add
388.74 -> an animation or progress indicator and
391.38 -> then start working on search results
392.88 -> afterwards
394.44 -> so let's change our code to leverage a
396.78 -> few common patterns available to most UI
399.6 -> Frameworks
400.86 -> first let's add a suspense boundary
403.919 -> between these two components this allows
406.62 -> the search box to render its update
408.66 -> without waiting for autocomplete
411.3 -> second let's wrap the autocomplete State
414.419 -> change inside of a start transition
416.759 -> transitions are requests to update state
419.28 -> but without blocking existing UI
422.28 -> finally let's also debounce this effect
425.419 -> meaning instead of crunching through
428.52 -> search results right away for each and
431.34 -> every keystroke let's delay a short
433.68 -> while until I stop typing debouncing is
437.16 -> a very common technique with lots of
439.56 -> Library support though it's not always
442.139 -> built into Frameworks let's try that
445.56 -> much better now I can see things
448.86 -> happening the text updates quickly and I
451.8 -> added some CSS to blur the search
453.96 -> results whenever they're stale
456.419 -> takes a while to get fresh results but
458.94 -> at least it feels like something is
460.56 -> happening that's a huge Improvement
463.5 -> except
464.639 -> it looks like I'm still getting hiccups
466.68 -> sometimes how come
469.259 -> I think it's time to reach for that
470.639 -> performance panel
472.8 -> all right I've already recorded a trace
475.8 -> which I know captured some slow
478.02 -> interactions so let's Dive In
480.419 -> notice we have an interactions Lane that
483.78 -> visualizes every single interaction
486.3 -> if you hover over one interaction you
488.58 -> will see its total duration
490.319 -> this one looks like the longest
492.96 -> what I'd really like to answer quickly
495 -> is where's my delay even coming from
498.3 -> is it input Delay from other tasks
501.18 -> totally unrelated to my interaction
503.759 -> or do I have long running event handlers
506.039 -> because of my interaction
508.139 -> was there expensive rendering work like
510.539 -> style and layout maybe I even had
512.94 -> rendering delays off the main thread
515.219 -> like decoding large images or expensive
517.74 -> CSS effects this time it looks like this
521.52 -> is a case of input delay this long task
524.399 -> here was preventing my keyboard input
526.98 -> event from even beginning to run
529.68 -> so where did it come from
531.42 -> at first glance it looks like it may be
533.64 -> caused by my framework
535.32 -> but if you look carefully all the real
537.779 -> time was spent inside our filter results
540.18 -> function which was actually still
542.339 -> running back from the previous search
545.42 -> debouncing the work into the future
547.38 -> fixed that interaction but it's now
550.14 -> affecting this interaction
552.54 -> all right so we started with every
555.3 -> interaction being slow and we did our
557.399 -> best to de-bounce that long task into
559.5 -> the future
560.459 -> that did improve responsiveness for many
562.74 -> interactions
564 -> but that works still has to run
565.5 -> eventually and once it does it blocks
568.56 -> everything
569.82 -> now UI Frameworks do their best to drive
573 -> efficient State changes to time slice
575.76 -> work to segment UI updates and to abort
578.7 -> needless transitions but none of that
581.76 -> can happen if our own code is long
584.22 -> running and blocking the main thread
586.8 -> this is an unfortunate and common
589.019 -> pattern on too many pages today
591.959 -> so let's make some final changes
594.899 -> first let's change our filter results
597.54 -> function to be async we'll need to
600.42 -> change our UI component when we do so
602.459 -> but these days this is getting a lot
604.44 -> easier to do
605.76 -> now that it's async we can follow a
608.04 -> pattern let's periodically yield to main
610.92 -> using scheduler.yield API or a polyfill
614.459 -> like I have here
616.26 -> that gives other work a chance to run in
619.14 -> the middle of our function here
621.3 -> allowing events to Fire and browser
623.76 -> rendering to happen
625.38 -> finally for this demo I chose to go one
628.2 -> step further and added support for
630.3 -> aborting any in-progress work as soon as
633 -> I start typing again using an abort
634.98 -> controller
636.6 -> with these changes filtering search
638.94 -> results won't be a dangerous long task
641.64 -> anymore
642.66 -> because of that I can even remove the
644.94 -> debounce delay that we added earlier
646.68 -> since now it doesn't matter if I get
649.079 -> started eagerly or with every keystroke
651.48 -> we'll get faster results to the user and
654.36 -> will still stay responsive The Best of
656.399 -> Both Worlds I can't wait to try this
658.62 -> version
661.14 -> look at that I can type into search as
664.2 -> much as I want whenever I want and
666.6 -> search results are being filtered one
668.94 -> bite-sized chunk at a time no more
671.7 -> hiccups blocking the page at all and our
675.06 -> imp scores are looking great
677.279 -> all right with that I think I'm ready to
680.519 -> deploy then I'll be eagerly waiting to
683.519 -> get field data back to confirm users are
686.399 -> saying the same great benefits I saw
688.38 -> here if not I'll have to reach for field
691.38 -> insights to help me go back and try
693.779 -> again
694.81 -> [Music]
697.2 -> now let's look at Imp in the real world
700.26 -> we'll go over some case studies of real
702.72 -> websites that have made big improvements
705.12 -> to responsiveness for their users
707.76 -> let's start with the economic Times they
710.94 -> began their work in Lighthouse cutting
713.22 -> down their total blocking time
715.38 -> total blocking time measures how much
717.42 -> time the main thread is blocked during
719.519 -> page load and it's correlated with
721.98 -> interaction to next paint because main
724.26 -> thread slowdowns are the main cause of
726.72 -> slow user interactions
728.7 -> Lighthouse offers a lot of advice for
731.1 -> improvement and the team found several
733.14 -> places to make Headway
735.48 -> they late loaded scripts which are not
737.339 -> business critical to free up the main
739.5 -> thread to process the main content
741.899 -> they removed unused JavaScript and CSS
744.66 -> which are still parsed and compiled even
747.12 -> when they're not needed
748.56 -> as part of this process they inlined the
751.44 -> necessary CSS
753.12 -> because over 90 percent of their common
755.279 -> CSS was not getting used
758.7 -> this made a big Improvement and they
760.98 -> kept going once they had optimized the
763.2 -> total blocking time they looked for
764.88 -> things that would specifically improve
766.44 -> interactions
767.82 -> first they reduced the Dom size this can
771.24 -> really improve the time it takes to
772.8 -> render after an interaction
775.019 -> and speaking of re-rendering they
777.18 -> avoided unnecessary re-rendering by
779.7 -> upgrading to next.js to take advantage
782.22 -> of better react hooks to avoid
784.26 -> re-rendering
785.7 -> they took advantage of request title
787.74 -> callback to render below the full
789.54 -> content when the main thread is freed up
792.72 -> and they use Party Town to move
795.06 -> third-party code off of the main thread
798.3 -> after all of these optimizations
800.48 -> Economic Times saw imp on their topics
803.639 -> Pages reduced by 75 percent
807.3 -> this big Improvement in user experience
809.94 -> translated to Big improvements to
812.16 -> business metrics they saw 50 decrease in
815.82 -> bounce rate and a 43 uplift in page
819.24 -> views with this success Economic Times
822.54 -> is going to press forward with this work
824.48 -> scaling these improvements site-wide
828.66 -> another great example is redbus redbus
832.2 -> is India's largest online bus ticketing
834.6 -> platform millions of people use the
837 -> website on their phone to book bus
838.92 -> tickets and not all of them have the
841.079 -> fastest phones those users that didn't
843.66 -> have fast phones were seeing some really
846.18 -> high interaction times so redbus added
849.24 -> real user monitoring using webvitals.js
851.94 -> to understand which elements have the
854.94 -> slowest interaction time and then dug
857.88 -> into the problems
859.5 -> they reduce the amount of render
861.24 -> blocking CSS and JavaScript
863.639 -> they reduce the amount of data sent in
865.98 -> API calls saving lots of time processing
868.8 -> and filtering
870.12 -> they removed unneeded JavaScript and CSS
872.82 -> then we're still slowing down
874.32 -> interactions
876 -> after fixing all of these issues and
878.459 -> adding some other optimizations they cut
880.8 -> their Imp in half and users love the
883.98 -> results redbus saw a 7.2 percent
887.16 -> increase in conversion rate
889.62 -> we're really excited about the big
891.72 -> improvements to business metrics that
893.699 -> redbus and the economic time saw when
896.22 -> they improve their imp we really hope
898.56 -> you'll try it out yourself we put
900.6 -> together a lot of resources to help you
902.519 -> get started please follow the link in
904.5 -> the slides to learn more
906.3 -> thank you so much for watching
908.03 -> [Music]
911.339 -> foreign

Source: https://www.youtube.com/watch?v=KZ1kxzsJZ5g