Using Lazy Loading in a Mashup
Lazy loading enables you to reduce or delay resource-demanding and data intensive operations to improve mashup load time and performance. You can use lazy loading to configure a mashup to load essential components, and then the load additional data and execute services based on actions that the user performs. Additionally, you can unload containers from the DOM to free system resources and improve performance when a container is out of view. This enables you to provide users with faster access to essential features, which improves the overall responsiveness of the mashup. In Mashup Builder, lazy loading is supported using properties, events, and services for the following types of containers:
• Layout containers
• Containers within the Tabs and Dynamic Panel widgets.
The mashup Loaded event is typically used to execute data services and functions in a mashup, even when the data is not visible. As you design more complex mashups, users can experience longer load times and decreased performance when a mashup contains the following:
• A high number of data services that are executed at the same time.
• Large media entities, which can affect the time it takes to download resources.
• Visualizations that display a large amount of data such as complex grids and Collection widgets, which can affect rendering performance.
For example, consider a mashup that uses a Tab widget to create a layout where each tab contains a different type of visualization or a set of input widgets. Loading data for all the tabs in parallel when a user only needs to view some of the tabs increases load time and the total number of network requests to the server. You can choose to load specific tabs based on actions that the user takes, output from a service, or an expression function. For more information about using lazy loading in a Tabs widget, see
Tabs Widget (Themable).
Best Practices and Usage Consideration
• Use the Loaded event of the container instead of the mashup event to execute services that are bound to a widget that is lazily loaded. Binding the mashup Loaded event to execute a service for a lazily loaded container will not display any results, unless the LoadContainer service is executed.
• Design the layout of your solution, then determine parts of your mashup that can be loaded separately. Consider the typical use cases for the solution and use that information to decide how to load content. In some cases, loading more data than what is required initially can create a better user experience when a user has to switch between different views quickly, which leaves less time to load each tab at a time. Instead of loading data for a second or two each time a container or a tab is opened, you can choose to load specific data in advance. After creating your mashup, you should measure its load time and performance, and then compare this to the expected use cases for your design.
• When a container takes multiple seconds to load its content, consider keeping it loaded, even when its no longer in the current view. Keeping the content loaded prevents the user from waiting for content to reload each time they switch to a different view and then return to the previous one. You can add a button and bind it to the ReloadContainer widget to allow users to manually reload the data.
• Make sure that data from a lazily loaded container is used by other widgets, functions, or services only after the container is loaded.
• Mashups can contain many widgets and sections that are not relevant for all users all the time. Create rules using services and functions to control the loading and visibility of widgets and data. You can load content based on user input, or events that occur at run time.
Use visibility rules in the lazily loaded containers so that they are displayed only when required.
• Make sure functions that use input parameters from lazily loaded widgets are executed after the parent container is loaded. Mashup functions might only work when all bound participants are visible or at least have been visible once.
To configure lazy loading properties for a container:
1. In Mashup Builder, select a container on the canvas or using the Explorer panel.
2. On the Properties panel, set the container LazyLoading property to True. Additional properties, services, and events for lazy loading are displayed.
◦ To unload data for the container, set the EnableContainerUnload property to True, then bind an event that executes the UnloadContainer service.
◦ To load the container at run time, bind the LoadContainer service to a widget, function, or data service event.
|
Lazily loaded containers within the Tabs widget are automatically loaded, unloaded, and reloaded when you switch to a tab that is configured for lazy loading.
|
◦ To reload content within the container, bind the ReloadContainer service to an event, such as a button click.
3. Bind the Loaded event of the selected container to execute services within widgets, data services, or functions.
Optionally, bind the Unloaded event to perform actions when the container is removed from the DOM.
4. Click Save, then View Mashup.
When the LoadContainer is executed at run time, the Loaded event triggers and executes any bound service, such as data for a chart or an Evaluate service of an Expression or Validator function.
Lazy Loading Properties
The following table lists properties, events, and services that are available to enable and configure lazy loading for containers in a mashup.
Property
|
Description
|
Base Type
|
Default Value
|
LazyLoading
|
Enables you to load, unload, and reload the container using widget, function, or service events at run time.
|
BOOLEAN
|
False
|
LoadContainer
|
A bindable service that enables you to load, unload, and reload the container at run time using widget, function, or service events.
|
Service
|
|
Loaded
|
An event that triggers when the container is loaded and displayed in the run-time mashup view. You can use this event to execute services that are bound to widgets within the container.
|
Event
|
|
EnableContainerUnload
|
Enables you to unload the container and its content using the UnloadContainer service when the LazyLoading property is enabled.
|
BOOLEAN
|
False
|
UnloadContainer
|
Unloads the container and its content, including child containers from the run-time mashup view. Bind this event to events in the mashup, such as the Button widget Clicked event or the Validation function True event.
|
Service
|
|
ReloadContainer
|
Reloads the container and its content by unloading and loading it in the run-time mashup view. This property is only available when EnableContainerUnload is selected.
|
Service
|
|
Unloaded
|
An event that triggers when the container is unloaded and removed from the run-time mashup view. This property is only available when EnableContainerUnload is selected.
|
Event
|
|
Using Lazy Loading within Custom Widget Extensions
The following section describes the steps required to update a custom widget extension to support lazy loading. To use lazy loading features for containers, you must review and update the widget <widgetname>.runtime.js file manually.
Widgets use a function named beforeDestroy() that is used to clear the widget bindings and data before it is removed from the HTML DOM. In previous versions of ThingWorx, a typical way to remove a widget from the DOM is to declare a variable that points to the widget object and then assign a null value to this variable when beforeDestroy is called. For example:
this.beforeDestroy = function(){
/** Destroy widget
thisWidget = null;
}
Destroying widgets using this method causes issues when reloading the widget as the called methods attempt to use this variable. To use lazy loading in a custom widget, you must update references to the beforeDestroy() function in your <widgetname>.runtime.js file of your custom widget extensions by adding the domOnly argument. The following code is an example:
this.beforeDestroy = function(domOnly) {
if (!domOnly) {
thisWidget = null;
]
};
The domOnly argument enables you to remove the widget from the DOM without destroying the widget, and you can reload it into the DOM later.
To update an existing extension, perform the following steps:
1. Extract your widget extension, then open the <widgetname>.runtime.js widget source file in a text editor. This JavaScript file defines the widget sturcture and its behavior when it is used in a mashup.
2. Search the file content for any references to the beforeDestroy() function. This function is called before the DOM element of the widget is removed and the widget is detached from its parent widget and destroyed.
◦ If the method is referenced, add the domOnly argument as follows:
this.beforeDestroy = function(domOnly) {
3. Add a conditional statement for the variable assignment to destroy the widget only when the value of the domOnly argument is false:
if (!domOnly) {
thisWidget = null;
}
4. Save theruntime.js file of the widget, and then repackage the custom extension.
5. Import the updated widget in Composer.
You can now use the custom widget in lazily loaded containers.