06 - Lightning Best Practices
06 - Lightning Best Practices
Best Practices
<Name>
<Title>
Forward-Looking Statements
Statement under the Private Securities Litigation Reform Act of 1995:
This presentation may contain forward-looking statements that involve risks, uncertainties, and assumptions. If any such uncertainties materialize or if any of the
assumptions proves incorrect, the results of salesforce.com, inc. could differ materially from the results expressed or implied by the forward-looking statements we make. All
statements other than statements of historical fact could be deemed forward-looking, including any projections of product or service availability, subscriber growth, earnings,
revenues, or other financial items and any statements regarding strategies or plans of management for future operations, statements of belief, any statements concerning new,
planned, or upgraded services or technology developments and customer contracts or use of our services.
The risks and uncertainties referred to above include – but are not limited to – risks associated with developing and delivering new functionality for our service, new
products and services, our new business model, our past operating losses, possible fluctuations in our operating results and rate of growth, interruptions or delays in our Web
hosting, breach of our security measures, the outcome of any litigation, risks associated with completed and any possible mergers and acquisitions, the immature market in
which we operate, our relatively limited operating history, our ability to expand, retain, and motivate our employees and manage our growth, new releases of our service and
successful customer deployment, our limited history reselling non-salesforce.com products, and utilization and selling to larger enterprise customers. Further information on
potential factors that could affect the financial results of salesforce.com, inc. is included in our annual report on Form 10-K for the most recent fiscal year and in our
quarterly report on Form 10-Q for the most recent fiscal quarter. These documents and others containing important disclosures are available on the SEC Filings section of the
Investor Information section of our Web site.
Any unreleased services or features referenced in this or other presentations, press releases or public statements are not currently available and may not be delivered on time
or at all. Customers who purchase our services should make the purchase decisions based upon features that are currently available. Salesforce.com, inc. assumes no
obligation and does not intend to update these forward-looking statements.
Agenda
• Best Practices •
•
Lists (aura:iteration)
Events
• Architectural Best Practices • Third-party JavaScript libraries
• Base Lightning Components
• Design Best Practices • Image optimization
• Security Best Practices • Rendering and reflow
• Development settings vs production settings
• Lightning Components
• JavaScript in Lightning • Performance profiling tools
• CRUD/FLS
Event interaction
Helper Components Metadata caching
Minimal When applicable
Client-side Helper
callToServer function:
Parameters:
Name of Apex @AuraEnabled Method
Method Parameters
Action properties:
setAbortable()
setStorable() + ignoreExisting
setBackground()
<c:CardListView/> CardListViewController
extends c:serviceComponent Dynamic
Apex
+
SOQL
DON’T
• <button onclick=“javascript:alert(1);”>hi</button>
• window.setTimeout(asyncFunction,1000);
Javascript in Lightning
Unsafe Javascript
Security Rule #1: Never trust the user!
• Javascript that executes or evaluates user-supplied data
can be attacked
• Components have access to the shared DOM, increasing
impact
– Attacks against a component impact entire shared DOM
• Don’t store secrets on client-side
Unsafe Javascript – Do’s and Don’t’s
DON’T Never evaluate user input
• eval(“input”)
• new Function(“input”) Sanitize user data then check it to
• window[“eval”](“input”) determine what of your code you
should run
• window.location.href=“input”
CRUD/FLS
CRUD/FLS Enforcement
• CRUD/FLS is not checked by default
– Unlike Visualforce pages
• Permission checks should be implemented by server-side code
(controllers) that return data to Lightning components
• Lightning Data Service (beta)
Learn More!
• Developer Guidance and
Docs
– bit.ly/LightningSec
– bit.ly/CodeGuide
– bit.ly/LockerService
• Trailhead
– bit.ly/SecureTrail
– bit.ly/SecLightning
Performance Best Practices
SOQL Queries Limit
• Typical of chatty custom Experience Components
• Cause:
– Calls to server on init are aggregated into same Apex transaction
• Mitigation:
– Use Lightning Data Service when possible
111 W Illinois St, Chicago, IL 60654
– Use cached data (for static data/metadata)
– Leverage Custom Metadata Types
• Do not count against SOQL Limits
– Use setBackground() on calls to server
• Calls processed separately, designed for lower priority calls but generally processed quickly
– Chain component loading by groups
• Last component to load in a group fires application event to load 2nd group – and so on
Data Retrieval
Optimize Server Round-trips - 1
• Before making a call to the server, make sure there’s no other option to obtain the data.
• When appropriate, consider passing data between components (using attributes, events, or
methods) rather than retrieving the same data in different components.
• The Lightning Data Service (currently in Developer Preview and in Beta in Summer ’17)
also allows you to efficiently share data between components.
• When making a call to the server, limit the columns and rows of the result set:
– Only SELECT the columns you need.
– Set a LIMIT on the query and provide a paging mechanism if needed. Don’t return huge numbers of rows at once.
Optimize Server Round-trips - 2
• Lazy load occasionally accessed data. Don’t preload data that the user may never ask for
(for example, data hidden behind a tab the user may not click, or in a combobox the user
may not open).
• Client-side filtering and sorting: Don’t make a call to the server to filter or sort data you
already have at the client-side.
• Consider combining several requests (actions) in a single composite request.
• Cache data when possible (see Data caching).
Data Caching
Storable Actions
• The general guideline is to cache (mark as storable) any action that is idempotent and non-
mutating.
• Check out the DreamHouse sample application for examples. Storable actions are used in
the following components: PropertyListDaysOnMarketChart, PropertyTileList, and
SimilarProperties
Lightning Data Service
• Lightning Data Service provides a managed record approach: you’re not responsible for
writing data access logic (no Apex).
• The framework is responsible for managing records: fetching them from the server when
requested the first time, storing them in a highly efficient client cache, sharing them
between all components that request them, and sending changes to the server.
• Lightning Data Service also handles progressive loading: it only loads the requested fields.
If another component subsequently requires additional fields, these fields are loaded
transparently and added to the record in the cache.
• Check out the following components in DreamHouse to see the Lightning Data Service in
action: PropertyMap, PropertySummary, MortgageCalculator.
Custom Cache
• You can also implement your own custom cache approach when there is no standard way
to implement your caching requirements in the framework.
• For example, a custom cache can be a good solution for static data like a list of states in
the United States, picklist values, and so on.
• You can use a storable action in this case too, but it still generates unneeded server calls
(every time the data in the cache is older than the refreshAge, currently set to 30 seconds
in the framework).
• If you know that the data won’t change, or changes infrequently, you can implement a
custom cache solution that retrieves the data once after the user logs in and then never
goes back to the server.
Component Instantiation
Lazy Initialization
Lazy instantiation in Lightning Experience - Components can be hosted in specific areas in the
Lightning Experience where they are lazily instantiated:
– Quick or Global Actions
– Utility Bar
– App Builder tabs
The <div> component and all of its children are created and rendered up front, but they’re
hidden.
If there are event listeners attached to the <div> or any of its children, these event listeners
would be “live.”
Conditionally Creating Elements <aura:if>
• Use the <aura:if> approach because it helps your components load faster initially by
deferring the creation and rendering of the enclosed element tree until the condition is
fulfilled.
• Components inside an <aura:if> with the value of its isTrue expression evaluating to false
aren’t created and aren’t part of the DOM.
• Event listeners aren’t created either.
<aura:if isTrue="{!v.isError}">
<div>{!v.errorMessage}</code>
</aura:if>
Unbound expressions can have a positive impact on performance because they don’t
maintain event listeners.
In the DreamHouse sample application, components created inside <aura:iteration> use unbound expressions to
avoid the proliferation of event listeners. See PropertyListDaysOnMarketChart for an example. Also see how
PropertyTile is bound to property objects inside PropertyTileList.
Events
Events
• Minimize the number of event handlers:
• Use unbound expressions when possible.
• Use <aura:if> when you need to conditionally render UI elements. Components
inside an <aura:if> with its isTrue expression evaluating to false aren’t created,
which means that event listeners attached to these components aren’t created either.
• Limit the use of Application Events to coarse-grained application-level
communication. For example: Communication between components added to pages
in App Builder.
Events
• For finer-grained communication between components:
– Use Component Events for child-to-parent communication:
<Paginator onPageNext="{!c.pageNextHandler}”
onPagePrevious="{!c.pagePreviousHandler}"/>
– Use attributes or <aura:method> for parent-to-child communication
• When working with lists, letting events bubble, and registering a single event listener on a parent
element instead of a separate event listener on every list item can significantly reduce the number
of event listeners
In the Mutual Fund Explorer application check out the FundTileList component, and see how a single onmousemove event listener is registered on
the list element (<ul>) instead of a separate listener on every list item (<li>) (inside the FundTile component).
In DreamHouse, see the PropertyTileList and Paginator components for an example of inter-component communication using a component event.
See PropertyTileList and PropertyMap for an example of using an application event to communicate between components in App Builder.
3 Party JavaScript Libraries
rd
Third-party JavaScript Frameworks
• DOM manipulation libraries
– Lightning Component Framework also provide abstractions that make jQuery less relevant.
• UI libraries
– Reconsider the use of UI libraries like Bootstrap and jQuery UI. Their own UI identity can clash with the Lightning
Experience identity.
– The Base Lightning Components and the Lightning Design System offer similar capabilities while providing a consistent user
experience.
• MVC frameworks
– At a high level, libraries like React and AngularJS have the same focus as the Lightning Component Framework
– Using another MVC framework together with the Lightning Component Framework inside a component isn’t recommended.
– Use a Lightning component as a container to host components built with other frameworks (like React and AngularJS)
• To enable/disable debug mode: Setup > Custom Code > Lightning Components
• To enable/disable component caching: Setup > Security > Session Settings > Caching, and uncheck
Enable secure and persistent browser caching to improve performance
Performance profiling tools
Development Settings vs Production Settings
• If you face a performance problem in a component, make sure you understand what the real
problem is before trying to solve it.
• Don’t make assumptions.
• Use profiling tools to identify the performance bottlenecks.
</lightning:layoutItem>
• Each part of your UI corresponds to a </lightning:layout>
component, which can in turn contain <lightning:layout>
<lightning:layoutItem padding="around-small">
nested components. Sidebar
<!-- Other component markup here -->
• Compose components to create a </lightning:layoutItem>
<lightning:layoutItem padding="around-small">
sophisticated app. Content
<!-- Other component markup here -->
• An app’s markup starts with the </lightning:layoutItem>
</lightning:layout>
<aura:application> tag. </aura:application>