Starting in Spring ‘19,
lightning:container will be supported in Lightning communities as well as in Lightning Experience. In this post, we will cover examples of what you can do with
lightning:container in Lightning communities.
If you are familiar with how
lightning:container components operate in Salesforce Lightning Experience, there will be a few additional bits of configuration to pay attention to. I also want to show off some of the amazing feats you can accomplish when
lightning:container is used in conjunction with other web technologies.
Having a consistent online presence between all aspects of your sites is critical to your company’s brand, but it isn’t always easy to achieve when using multiple tools. In Lightning communities, pieces of your storefront application may be challenging or even impossible to reproduce with existing Lightning components, leaving you with an inconsistent web presence. The
lightning:container component is an essential tool to close those gaps and build a seamless online experience for your customers. New Content Security Policy options in Communities also give developers more freedom when developing
If you are unfamiliar with
lightning:container, I recommend you start with the Lightning Container documentation, and the first Lightning Container developer blog to begin your journey with
A review of Lightning Container
lightning:container component is a powerful developer-focused component intended to allow you to securely reuse code originally developed for use outside of the Lightning Framework.
lightning:container . I would even encourage you to mix in open source software in your Lightning applications when needed, using this approach.
Watch Lightning Container in action
Let’s take a quick look at a common commerce-focused solution. In this video, you can see a solution that uses React code working seamlessly within a Lightning community. No code understanding needed, just watch it all work without a hitch.
Want to know how it works? The sample application is included in our code samples.
What you’re seeing is just the tip of the iceberg in terms of what is possible. What follows are a series of more technical examples to help you explore other ideas.
Technical examples and sample code
There is a repository of samples, with complete readme, available here. The repository includes both pre-existing examples from this repo and the Lightning Container Component Sample App, plus new samples made specifically for Lightning communities. Some of these samples require you to run a Relaxed-CSP Community and thus will not work correctly in Lightning Experience. Please defer to the README.md files for each sample application, in the /js-apps folder.
Some of these examples require additional specific Content Security Policy (CSP) changes made in the Security tab in Community Builder, or by adding external domains to your CSP Trusted Sites. Please check out this blog post and this help document for more information.
In this section, I’ll be highlighting some common recurring themes you’ll run into when working with a
lightning:container component, as well as highlighting the appropriate code and referencing the examples in our GitHub repository.
Relative pathing in your application
When building apps for communities, you need to consider that different communities have different path prefixes. So, if you want to put your app on the AppExchange, it must work regardless of path prefix. I suggest telling your JS framework to use relative pathing. Most JS build tools can be configured this way.
In the rare cases where this isn’t possible, you’ll need to dynamically load all of your resources based on the current site and URL. This is a fragile approach and isn’t recommended unless there are no other options.
For example in Angular, go to the angular.json and add:
When using Angular, you also must build with the –base-path flag:
This will create the
<base href="./"> tag in the index.html file of your target output directory. All resources should then load correctly in all communities. Follow the configuration in our AngularJS Example.
Another common web development practice is to bootstrap your application using
create-react-app. For this use case, all you need to do is add the following to your
react-scripts build will create the appropriately pathed items. This is used in the react-commerce example.
There are many more examples of relative pathing in the sample GitHub repository. To see them, compare the build configurations of the sample JS applications with their build output, found in the static resources folder. You will see that each JS framework can be configured to use relative pathing, generally with only small modifications to a few configuration files.
Modern web design generally avoids scroll bars within the page content, especially nested scroll bars. This does not come for free with
lightning:container. One strategy to deal with this is to use a MutationObserver to keep track of the size of your content, and then use the post-messaging capabilities of
lightning:container to resize the iFrame appropriately. When used correctly, you can create a responsive iFrame that will never have double scrollbars on the desktop, and which works fluidly on mobile devices.
I’ve provided a simple, barebones example of this in action. The green background denotes the content of the
lightning:container. See the code in our resizing example.
Guest and portal users
Lightning communities fully support
lightning:container and it is available to all user types in your communities, including the Guest User Profile. If you are interacting with Salesforce objects via Apex, you’ll need to add access to the appropriate Apex classes to your org’s user profiles. From the profile page, click “Enabled Apex Class Access”, as shown here.
For guest users, check out the site Guest User Profile help doc.
WARNING: Guest User access to data is shared with all anonymous users using the Guest User Profile on the site. Make sure any data that you let the Guest User Profile access and create is truly public data and that everyone should have access to that data! Don’t let guest users access sensitive information, and don’t have guest users create records with their personal information.
Content Security Policy
Salesforce maintains a restrictive Content Security Policy (CSP) when using Lightning communities. The
lightning:container iFrame will inherit the same CSP policy as its parent container, so in Lightning Experience it will use the Lightning Experience policy and in a community, it will use the community policy. When using
lightning:container, there are a few best practices to follow.
First, we recommend avoiding inline scripts when using
lightning:container, especially if you are looking to create a
lightning:container for AppExchange. Inline scripting requires the
script-src: unsafe-inline directive, which is less secure and is only available in communities not running Strict CSP. Running without Strict CSP may not be an option for all of your potential customers and so that requirement should be avoided if possible. Using inline scripts would also block your
lightning:container from working in Lightning Experience.
If you for some reason need to use inline scripts, or you have to load external JS resources, you cannot use Strict CSP in your target community. External JS scripts must also be added to the trusted site whitelist for each community where the
lightning:container is intended to run.
A common example of External JS scripts is found in Polymer which, in many applications, downloads the required scripts from Cloudflare.
To load the script, you must add
Another common requirement are external resources such as external data sources and hosted images. External resource domains must all be added as “trusted sites” to your org so they are available. Additions to CSP Trusted Sites can be part of an AppExchange package and should be included in the package with the
lightning:container when they are needed.
Through this blog you’ve seen all kinds of technical examples about how to use Lightning Container in Communities. We can’t wait to see what you build next!
- Blog Post: CSP Options for Communities
- Documentation: Lightning Container Overview
- Blog Post: Lightning Container Component
- Trailhead Module: Security for Lightning Components
- Trailhead Module: Aura Component Tips and Gotchas
About the author
James Wonsever is a Lead Engineer on Community Cloud for 5 years since the inception of the Napili template. He has been involved with many parts of Community Cloud development.