Improve Angular Navigation UI Responsiveness and INP Scores by Breaking Up Route Changes
- Dominant language
- TypeScript
- Stars
- 101k
- Forks
- 27.5k
- Avg merge
- 1d 19h
- Merged PRs (30d)
- 288
Description
### Which @angular/* package(s) are relevant/related to the feature request?
core, router
### Description
I have found Angular navigation events can often be slow to update the UI when navigating to complex components.
It would be nice to be able to break up routing so that a loading bar or similar could be presented at the start of navigation before the new component or module code is loaded and the UI is updated with the new component.
When navigating to a lazy loaded module for the first time, this is possible as you can subscribe to the NavigationStart router event and update the UI with a loading bar or spinner to show that the route navigation has started. However, on subsequent navigations to the module, the route change is performed synchronously, so from my knowledge you can’t immediately update the UI – you must wait until the navigation completes which can be slow.
This often means Angular apps can feel slow or unresponsive when navigating to complex components or modules, and it also leads to poor Interaction to Next Paint (INP) scores, which is an incoming Core Web Vital metric and will become a Google ranking factor.
Here is a minimal repo demonstrating the issue with a 2s timer in place of a complex component. You can use the Chrome Web Vitals extension to view the INP scores drop after the modules are lazy loaded (as the loading bar doesn’t display).
[https://github.com/matthew-whitfield-uk/module-routing-inp](https://github.com/matthew-whitfield-uk/module-routing-inp)
**What is INP?**
Interaction to Next Paint (INP) is a Core Web Vital metric that will be introduced in March 2024. It measures a page’s responsiveness to user interactions and is usually the latency of the longest click, tap, or keyboard interaction.
A Chrome developer’s blog highlighted Angular as the worst-performing framework, with only 19% of Angular apps passing the maximum 200ms INP score on mobile devices:
[https://developer.chrome.com/blog/inp-in-frameworks/
](https://developer.chrome.com/blog/inp-in-frameworks/
)
Even fairly lightweight Angular projects such as Angular.io are currently failing INP on mobile:
[https://pagespeed.web.dev/analysis/https-angular-io/1mdibpcdkh?form_factor=mobile ](https://pagespeed.web.dev/analysis/https-angular-io/1mdibpcdkh?form_factor=mobile )
### Proposed solution
Some SPAs present a loading bar on all route navigations (e.g. YouTube desktop / Github) to give immediate user feedback that the navigation has started.
Angular could add an option for similar functionality by breaking up the route change process into - Navigation Start, Update UI with spinner, and then load new component code. This already happens when navigating to a lazy loaded module for the first time (presumably because the HTTP request for the module js is performed asynchronously which allows for a UI update) but subsequent navigations are performed synchronously.
Subsequent navigations could be moved into a setTimeout to allow the UI to update and give some immediate user feedback.
### Alternatives considered
Using custom route animations doesn't seem to fix this issue, and neither does adding progress bars within modules/components.
Contributor guide
Research direction
Start with the linked minimal repository and reproduce the difference between first and subsequent lazy-module navigations, observing NavigationStart and the loading UI. Then read the @angular/core and @angular/router navigation behavior involved; done would require an agreed design and verified improvement to UI responsiveness without breaking navigation.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- angular, typescript
- Domain
- frontend, performance
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100