Google Core Web Vitals - Best for Meteor

One of the features I love best with original Meteor is optimistic UI. This updates the UI asap before contacting the server, then corrects based on the response of the server - this second step seldom being required. This feature of Meteor is due to minimongo subscriptions with Blaze.

Well, Google has just announced that Core Web Vitals will use ‘INP’ as a criterion for page ranking. ‘INP’ measures reaction speed to user input - responsiveness. Certainly, this will bump up ranking on all sites that use optimisitic UI.

Thank you Meteor. Its great being on the first page of google for one of our websites, but it will be even better now - maybe even first on the first page!


That’s a big win for single-page web apps.

Optimistic UI also works with methods when you use a global state such as React Context or Redux.

As I understand INP, OptimisticUI has no influence here unless … let’s say you load your JS bundle to just pull HTML from your DB. You pages should not be conditioned by/waiting for your DB data.

How I understand it:

  1. FCP (First Contentful Paint) - clicking on the page is possible (JS has loaded, processed at least to a point when a click has any effect (such as it returns an event with a target).
  2. INP is past FCP and page has loaded or is still loading and an element on the page has eventually been drawn and clicking on it or typing in (for a text field) has an effect. The lowest result on all elements that can be interacted with gives the INP score.

Put in a different way, if you have method or a function on a click event that deals with DB data, the time measured is not related to data. If you put a console.log(‘’) at the top of the click event, it is the time for that console.log(‘’) return and not the time for the page or part of the page to change into something else.
If you get a console.log return, it means the element is responsive as opposed to FCP where only the first interaction is checked which tells that the page is … somehow responsive or starts to be responsive.

1 Like

INP in summary is the measurement of a gesture (click or tap) until the next paint after the effect of that gesture

Therefore, if you have a very slow fetch on a button, you can suffer on a low INP

Sample 1.
click button → 10 seconds to query/save content → display content

That 10 seconds delay could kill your INP measurement

Solution 1: Optimistic UI
click button → display content → query/save content

No lag between gesture and next paint (displaying of content)

Solution 2: Loader
click button → display loader animation → query/save content → display content

No lag between gesture and next paint (display of loader)


Ok, so some interactions may result in a navigation to something else in which case Mongo data is not (necessarily) a factor. Other interactions may result in staying on the same page and doing something like scroll down, open a modal, open an accordion, a menu etc. All these, as I understand, should not depend on data to load/move/open etc.
A problem I see here is when navigating to a dynamically loaded component. It takes time to get that component, you depend on the availability and network speed of the Meteor server, not even a CDN can help here.

@rjdavid I wonder whether an element reaction to a click can pass as INP. For example “depressing” a button by changing its shadow or a change in color/shade as the result of a click.

It will not. They are considered “group of events” together with the gesture.

How they are doing this? The lighthouse project should have a better explanation. It might rely on modern css so maybe an old js solution will be treated as start of a new paint

1 Like

That is why loadable and Suspense have backup UI to display e.g. displaying a loader/placeholder while waiting for the component

Thanks a bunch. I think this conversation has been really … revealing about some of the things I’ve been missing or wrongly understood.

I had no clue a fallback existed

I seem to be doing pretty well with React.lazy. My current Lighthouse Total Blocking Time is shown as 240ms.

Have people had better experience with Loadable Components than with React.lazy in terms of the Lighthouse score, package size, or in other ways?