Newer Version Available
Create Components with Offline Analysis In Mind
Specifically, an LWC Offline-enabled mobile app must prime:
- The component, and all its dependencies.
- The data to be displayed by the component, and all its dependencies.
The process for determining and resolving component dependencies is complex, and our implementation is continually improving. The fundamental aspect to understand is that this dependency resolution is done without executing or rendering the component. Dependency calculations are performed by static analysis of the component code, recursively applied to every child component, module, and wire adapter used by the top-level component.
In general, anything that requires code to execute to determine its execution path can’t be resolved during static dependency analysis. The following guidelines are an incomplete list of ways to avoid anti-patterns that can prevent a complete dependency analysis of a component.
- Don’t use a private property as an input value to a wire adapter.
- Don’t use a getter as an input value to a wire adapter when the getter result depends on an instance member or any computation.
- Don’t use any computed value as an input value to a wire adapter where the value can’t be determined without creating and executing the component, or which might be null when the component is instantiated.
- Don’t create a wire adapter chain where an earlier wire adapter outputs its results into a function.
- Don’t reference an array member from an array that is chained between wire adapters.
- Don’t reference an inherited property in an input value to a wire adapter in a subclass.
- Don’t create getter functions or properties that match an imported name. If a property name
and import name are the same, the static analyzer can’t differentiate them, and the imported
item can’t be primed. For
example:
1import { recordContextQuery } from 'c/myModule'; 2export default class GetterTest extends LightningElement { 3 @api objectApiName;\ 4 5 // Don’t make the getter name the same as the import name 6 // This prevents priming the imported recordContextQuery 7 get recordContextQuery() { 8 return recordContextQuery(this.objectApiName); 9 } 10}
Example and Workaround
Let’s consider an example. It’s common for a component to use CurrentPageReference in its code.
1import { CurrentPageReference } from 'lightning/navigation';
2// ...@wire(CurrentPageReference) pageRef;During initial priming when the app loads, the “current page” can’t be known. This means that resources associated with that page — layout metadata, object and field metadata, record data — can’t be fully determined in advance. And so the component can’t be primed completely.
The workaround in this case, and in general, is to find another way to make these dependencies explicit, instead of implicitly defined by a reference that can’t be resolved until runtime. Referencing a specific recordId, recordTypeId, or apiName provides enough information to determine the dependencies without the specific page context.