Overview
Lazy loading allows you to load code on-demand when a state is activated, reducing initial bundle size and improving application performance. UI-Router Core provides built-in support for lazy loading through thelazyLoad state property.
The lazyLoad Property
ThelazyLoad property (from src/state/interface.ts:545-666) is a function on state declarations that loads code asynchronously:
Function Parameters
transition: The current [[Transition]] object with access to parameters, injector, etc.state: The [[StateDeclaration]] that the lazyLoad function is declared on
Return Value
The function must return aPromise that resolves to a [[LazyLoadResult]]:
Basic Component Lazy Loading
ES6 Dynamic Import
React Example
Angular Example
Lazy Load Lifecycle
The lazy load hook (from src/hooks/lazyLoad.ts:32) is executed during transitions:Execution Flow
- Transition starts to a state with
lazyLoaddefined - Hook triggers via
onBeforetransition hook - Function invoked if not already loading (prevents duplicate calls)
- Promise tracked on the function itself to reuse across simultaneous transitions
- Code loads asynchronously
- States registered if promise resolves to [[LazyLoadResult]] with
statesarray - Property removed -
lazyLoaddeleted from state declaration after successful load - Transition retried - original transition is retried without
lazyLoadpresent - On failure - transition fails;
lazyLoadremains for potential retry
Implementation Details
From src/hooks/lazyLoad.ts:79-112:Key Behaviors
- Single execution: Promise is cached on the function to prevent concurrent loads
- Automatic cleanup: On success,
lazyLoadis removed from the state - Automatic registration: States in the result are registered automatically
- Transition retry: After loading, the transition is retried
Future States (Lazy State Definitions)
Future states act as placeholders for entire state trees that will be loaded later.Future State Pattern
A future state should have:- Name ending in
.**- Acts as a wildcard glob matching any nested state - URL prefix - Matches all URLs starting with this prefix
- lazyLoad function - Returns a [[LazyLoadResult]] with state definitions
Example
How Future States Work
- User navigates to
/admin/users - URL matches the
admin.**future state prefix lazyLoadfunction executes- Module loads and returns state definitions
- States are registered (including
admin.users) - Future state
admin.**is replaced byadminstate - Transition retries and matches the now-registered
admin.usersstate
Code Splitting Strategies
Route-based Splitting
Feature Module Pattern
Role-based Splitting
Lazy Loading with Resolves
Loading Dependencies
Preloading Data
Error Handling
Retry on Failure
Fallback State
Loading Indicators
Global Loading State
Webpack Configuration
Dynamic Import Comments
Output Configuration
Best Practices
- Use future states for modules - Lazy load entire feature areas with
.**pattern - Return LazyLoadResult - Always return
{ states: [...] }for automatic registration - Handle errors gracefully - Provide fallbacks or retry logic for load failures
- Avoid lazy loading critical paths - Don’t lazy load the initial/landing page
- Preload likely next states - Use route hints to preload probable next destinations
- Bundle related code together - Group interdependent states in the same lazy module
- Monitor bundle sizes - Use webpack-bundle-analyzer to optimize chunk sizes
- Test lazy loading - Verify that lazy states load correctly in development and production
Performance Tips
- Prefetch on hover: Load chunks when user hovers over links
- Preload critical paths: Use
<link rel="preload">for likely routes - Use service workers: Cache lazy chunks for offline support
- Optimize chunk sizes: Aim for 100-300KB per chunk
- Leverage HTTP/2: Parallel loading of multiple chunks
Debugging
Enable transition tracing to debug lazy loading:Reference
- Source:
src/hooks/lazyLoad.ts - Source:
src/state/interface.ts(lazyLoad property, LazyLoadResult) - Guide: Lazy Loading Guide