0% found this document useful (0 votes)
89 views58 pages

06 - Lightning Best Practices

The document provides best practices for developing Lightning components on the Salesforce platform. It discusses architectural best practices like using service components to encapsulate server-side logic, helper components for shared code, and experience components for common user experiences. It also covers design best practices for security, performance, and development vs. production settings. Finally, it outlines some performance best practices related to data retrieval, caching, and component rendering.

Uploaded by

Francys Garcia
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
89 views58 pages

06 - Lightning Best Practices

The document provides best practices for developing Lightning components on the Salesforce platform. It discusses architectural best practices like using service components to encapsulate server-side logic, helper components for shared code, and experience components for common user experiences. It also covers design best practices for security, performance, and development vs. production settings. Finally, it outlines some performance best practices related to data retrieval, caching, and component rendering.

Uploaded by

Francys Garcia
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 58

Salesforce Lightning Platform

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

• Performance Best Practices


• Data retrieval
• Data caching
• Component instantiation
• Conditional rendering
• Data binding
Architectural Best Practices
Lightning Component Architecture
Purpose Markup Comments
Extended/used by other
components
Service Components Handle server calls
Minimal Extensible = true
Shared code base

Event interaction
Helper Components Metadata caching
Minimal When applicable

Base Lightning Components


Implement UX functionality
Building Block Lightning Design System
at different levels of Majority of code
Components granularity
Building Block
Components/Content
Simple:
Lightning Data Service
Available in App Builder /
Building Block
Experience Components AppExchange for
Components/Content Advanced:
Components
Dynamic if applicable
Potentially metadata-driven
Service Component: Example
Component Markup

<aura:component description=”ServiceComponent" extensible="true"> <div>{!v.body}</div>


</aura:component>

Client-side Helper
callToServer function:

Parameters:
Name of Apex @AuraEnabled Method
Method Parameters
Action properties:
setAbortable()
setStorable() + ignoreExisting
setBackground()

Fires $A.enqueueAction(), defines callback function


Service Component: Example
<c:ServiceComponent/> <c:UtilityBarMenu/> UtilityBarController
extends c:serviceComponent Apex
+
SOQL
UtilityBarConfig__c

<c:CardListView/> CardListViewController
extends c:serviceComponent Dynamic
Apex
+
SOQL

Account Opportunity Custom__c


Example Experience Components
Designing a custom Experience Component
Dynamic, metadata-driven Components
• Support your own use cases
• When possible support any SObject
• Maximise code reusability
• Simplify component logic
• Providing admins with a greater degree of
flexibility…
Metadata:
• ... while simplifying App Builder experience
Field to filter on
Standard actions available
Lightning actions available
Columns to display
SOQL query

App Builder attributes:


Card List View title
Number of rows
Enable pagination
Reference to metadata record
Component Tree: custom Card List View
App Builder Component event
Attributes (incl. bubbles up, handled,
<c:CardListView/> Metadata reference) pagination attributes
updated

Which type of list


view?
<c:GenericListView/> Handle UI events
Render pagination? Or
link to list view?

Render filters? What data to render?


<c:Header/> <c:Table/>
Which mass actions? Which actions?<c:Footer/> Display and fire
pagination events

Display and fire mass Renders data and


<lightning:buttonGroup/> actions
<c:TableData/>
actions <c:Pagination/>
Record selection

<c:OutputField/> <lightning:buttonMenu/> Display and fire record-


<c:OutputField/> <lightning:buttonMenu/> level actions
<c:OutputField/> <lightning:buttonMenu/>

Links e.g. Visualforce,


<ui:(…)/> <lightning:(…)/> <c:Action/> Record Home Page
How do I fire platform actions?
Firing Platform Actions
• Which actions to display?
– Metadata – pre-selected actions
– Display all available actions for SObject in specific context
• Query PlatformAction object to obtain action type e.g.:

Action Type Examples Implementation

Standard Action View, Edit Fire createRecord, editRecord event

Visualforce Action E-mail PDF CV Fire force:navigateToURL event

Display Modal, inject Lightning Component, pass


Lightning Action Reject Candidate
appropriate parameters
Lightning Components
Component Encapsulation
Components share the DOM
• Locker Service
• Using global DOM-access methods risks modifying or affecting
other components
• This includes CSS!
• Be aware of mixing 3rd party libraries with Lightning
– JavaScript MVC frameworks (Angular, React, etc)
– DOM-modification libraries (jQuery)
– Utility libraries (D3, Leaflet.js, moment.js)
– Use Lightning Container Components
Component Encapsulation – Do’s and Don’t’s
DO Using provided methods to search for
• cmp.find(“myId”)
elements will restrict DOM access to
the component calling the method.

DON’T These methods accomplish the same


• document.getElementById(‘myId’) goals while ensuring that the
component actions remain
• $(“.myClass”).[…]
encapsulated.
• CSS: position:fixed

Respect other components!


Aura Lifecycle
• Respect the Aura Lifecycle in your components
• Load everything with <ltng:require>
• Don’t modify DOM directly, use aura attributes
– Except in renderer and init
– Think about how 3rd party libraries interact with the the DOM
Event Handlers
• All event handlers should be called through Aura
• Asynchronous code needs to be declared to Aura
• Similar concerns to other encapsulation problems
• Adding handlers through Aura ensures handlers affect
only component
Event Handling– Do’s and Don’t’s
DO
• <button onclick=“{!c.handleThis}”>hi</button>
• window.setTimeout($A.getCallback(asyncFunction),1000);

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

Lazy instantiation in your own components


– You can use <aura:if> to lazily instantiate parts of the UI (see conditional rendering section).
– Some components (like <lightning:tabset> and <lightning:tab>) support lazy instantiation by default.
– You can also instantiate components programmatically using $A.createComponent(); however, that approach is
generally harder to code, maintain, and debug.
Conditional Rendering
Toggling Visibility using CSS
Example:
<div aura:id="error" class="slds-hide">{!v.errorMessage}</div>
cmp.find("error").toggleClass(!isError, "slds-hide");
or
<div class="{! v.isError ? null : 'slds-hide'
">{!v.errorMessage}</div>

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>

In the DreamHouse sample application The PictureGalleryCard and Map components


use <aura:if> to toggle between regular and full-screen mode.
Data Binding
Bound and Unbound Expressions
Bound expressions provide an implementation of bidirectional data binding - a convenient
and powerful abstraction but comes at a cost:
– The framework has to set up two event listeners for each bound expression
– It also creates an entanglement between the model and the view that can make your code harder to maintain and
issues harder to debug in non-trivial situations.

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)

• Use minified versions of libraries and style sheets


Base Lightning Components
Base Lightning Components
• There are two sets of core user interface components:
– The original components that were made available when the Lightning Component Framework first came out live in the ui
namespace (<ui:button>, <ui:inputText>, and so on).
– The new and improved components, also known as the Base Lightning Components, live in the lightning namespace
(<lightning:button>, <lightning:input>, and so on).

• Whenever possible, use the Base Lightning Components


– Styles: Base Lightning Components are styled with the native Lightning look and feel.
– Performance: Base Lightning Components are already loaded at the client-side and don’t require additional download or
processing. Our performance optimization efforts are also focused on components in the lightning namespace.
– Innovation: The Lightning namespace is where components are being actively developed. This is where you can expect to see
new and improved components moving forward.
– Accessibility: Base Lightning Components are built for accessibility.
– Client-side validation: Base Lightning Components include client-side validation when applicable.
Image Optimization
Image Optimization
• When possible, use the (sprite-based) Lightning Design System icons (using <lightning:icon>
and <lightning:buttonIcon>) instead of custom icons.
• Lock image dimensions (to avoid reflows) and serve the image in those dimensions when possible.
For example, don’t load a high-resolution image to display a thumbnail.
Rendering and reflow
Rendering and reflow
• Understand when and why your component is being re-rendered. Read the Rendering Lifecycle
and Events Fired During the Rendering Lifecycle sections in the documentation.
• Minimize the number of times your component is being re-rendered.
• Lock DOM regions to specific dimensions to avoid browser reflows of surrounding areas.
• Avoid direct DOM manipulation.
Dev vs Production settings
Development Settings vs Production Settings
• Optimizations for a production environment and a development environment are different.
• To optimize performance in a production environment, component definitions are cached at the
client-side. That isn’t a suitable developer experience.
• The solution is to disable client-side caching during development.
• Recommended settings:
Development Production
– Debug mode On Off
– Component caching Off On

• 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.

• Profile Components with Chrome Timeline


• Use the Salesforce Lightning Inspector Chrome Extension
• Analyze with the Salesforce Community Page Optimizer
Lightning Application - UI
<aura:application extends="force:slds">
<lightning:layout>
• Design your app's UI by including markup <lightning:layoutItem padding="around-large">
in the .app resource. App</h1>
<h1 class="slds-text-heading--large">Sample

</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>

You might also like