trailhead

Work Well with JavaScript

Lightning bolt icon used to indicate that the content is for Lightning Experience

Attention, Trailblazer!

Salesforce has two different desktop user interfaces: Lightning Experience and Salesforce Classic. This module is designed for Lightning Experience.

You can learn about switching between interfaces, enabling Lightning Experience, and more in the Lightning Experience Basics module here on Trailhead.

Learning Objectives

After completing this unit, you’ll be able to:
  • Describe three things to watch out for in writing JavaScript for your Lightning components.
  • List three browsers that work well with Lightning components, and one that doesn’t. Explain why that one browser has problems.
  • Implement a supported pattern for including JavaScript library code into your components.

Tips & Gotchas

If the two previous modules in this trail were too abstract, or too slow for you, you’re in the right place. Indeed, we predict that many experienced Visualforce developers will skip right to this module.

And that’s OK! The other modules are important if you want to become a Lightning components expert. But this module is intended to stand alone, and be highly skimmable. We hope it’s helpful to you right away, and that you’ll return to it regularly.

Let’s dive in.

JavaScript Is Case-Sensitive

Chute! Nothing is going to cause you more grief than this major difference from Visualforce and Apex. If the API name of your object is Expense__c and a field is Amount__c, and you try to reference it with expense__c.amount__c (which works in Visualforce), it’s going to fail in JavaScript.

Worse, sometimes you don’t get an error message that’s helpful. You can spend a lot of time not seeing the problem; trust someone who’s been there, done that.

Apex and Visualforce let you play fast-and-loose with the names of oBjEcTs, FIELDS, mETHOD cALLS, and so on. You can’t get away with that in JavaScript. Case matters, everywhere. We wish this wasn’t true, but it’s not our programming language.

Ladder! We recommend that you use the exact, correct case always and everywhere—even in code where you can get away with being sloppy, such as your Apex or SOQL code. If you adopt strict discipline, you’ll never have case errors come back to haunt you.

This also means you’ll need to learn the correct names of system fields, like Id and Name. Ladder! Remember that you can always look up the correct names of an object’s fields in Setup.

LockerService and the Laws of Physics

Allowing safe, supported JavaScript execution in a complex, shared environment like Salesforce (where our code, your code, and code from managed packages all run in the same context) is a major challenge.

We developed an innovative isolation mechanism called LockerService. (It’s a great solution to a hard problem, so much so that new browser standards are pulling in aspects of the solution.) We’re in the process of transitioning LockerService to full activation for all customers. Previously this was done with a critical update, but with Summer ’17 you control LockerService activation by setting your component to API version 40.0 or higher.

We encourage you to do all of your Lightning components development with LockerService enabled (that is, with your components set for API 40.0 or higher). LockerService changes the “laws of physics” for your JavaScript code. We’ve found that it’s a lot easier to write new code with the new physics than to adapt code written in a parallel universe.

What, specifically, does LockerService do? Here’s a high-level list of its effects.
  • LockerService enforces JavaScript ES5 Strict Mode.
  • LockerService restricts access to global references.
  • LockerService ensures component DOM isolation.
  • LockerService blocks access to private or unsupported Lightning Component framework methods.
  • Additionally, via a separate critical update, LockerService combines with tighter Content Security Policy (CSP) to prevent cross-site scripting attacks.

We cover some highlights in this unit. For more details, see the Resources section.

JavaScript ES5 Strict Mode

When LockerService is enabled, it activates JavaScript ES5 Strict Mode for all of your JavaScript code. The effect is the same as starting all your JavaScript code with “use strict”. If you’re not familiar with strict mode, now would be a good time to read up.

Chute! The #1 thing you probably need to change is to declare your local variables using var. Here’s an example in an action method.

myAction : function(component, event, helper) {
    ...
    counter = 1;       // NO!!!!!
    var counter = 1;   // YES!
    counter++;
    ...
}

Ladder! “Strict” might sound scary, but it’s actually awesome. Think of strict mode like that teacher who frightened you when you were young, but who helped you more than you realized at the time. Strict mode enforces many JavaScript best practices. It’s a ladder up for all of your JavaScript, not just Lightning components.

Tip

Tip

Ladder! If you’re convinced of the benefits of discipline, you can use a validation tool, such as ESLint, to give you even more guidance than strict mode. ESLint can help you not just with JavaScript syntax, but point you at a wide array of best practices, and can even be used to ensure coding standards specific to your team. A good lint tool is definitely a ladder up.

Using Third-Party JavaScript Libraries

LockerService applies restrictions to global references. You’ll notice the restriction with the window object, for your own code and any third-party library code you use. LockerService provides secure versions of nonintrinsic objects, such as window. As a consequence, you need to make some small adjustments to how you add JavaScript libraries to your apps.

Ladder! To create a reusable library that’s easy to work with in your components, explicitly assign the library to the window object. This assignment makes the library available across all of the components that use the library. We can illustrate the general technique in just a few lines of code. To create a library with functions intended to be used in your code (like Util.logHere('Starting download'), for example), in a static resource declare the library using an immediately invoked function execution (IIFE), like so.
window.Util = (function() {
    return {
        logHere: function(msg){
            console.log('Got here.');
            if(msg) console.log(msg);
        }
    }
})();

This perhaps unfamiliar construction attaches our “library” to the window object, making it available to all of our components. Once you have the static resource, use <ltng:require> to include the library in your component.

For more details, including how to adapt this technique to complex or third-party libraries, check out Modularizing Code in Lightning Components on the Salesforce Developers blog.

Content Security Policy (CSP) Differences from Visualforce

The Visualforce container is isolated from all of the other Salesforce app containers, so it can have a fairly liberal CSP. Your Visualforce code can load JavaScript, graphics, and other assets from any URL. And you can treat any string as JavaScript, using eval().

Lightning components don’t run in an isolated container, so the framework has a tighter CSP. You can load graphics, styles, and other non-executable assets from non-Salesforce sites, but only after creating a CSP Trusted Site for each domain. Chute! You can’t load JavaScript from anything but a static resource on Salesforce.

Controlled by a pair of critical updates, the CSP active under LockerService is tightened even further. This CSP disallows the unsafe-inline and unsafe-eval keywords for inline scripts (script-src). This restriction is in addition to the general restrictions of the Lightning components CSP. You can’t use inline JavaScript, or eval() a string as JavaScript. Consequently, you need to update your third-party JavaScript to modern versions that don’t depend on these older, far less secure techniques.

Note

Note

Not all browsers support CSP. In particular, IE11 is…problematic. In browsers that don’t support CSP, such as IE11, LockerService is disabled. We strongly recommend that, for enhanced security, you update to a modern browser, such as the latest versions of Chrome, Safari, Firefox, or Microsoft Edge.

There are valid use cases where the preceding restrictions are a barrier. Ladder! In those situations, we recommend that you put code that needs access to external resources in a “worker iframe” using Visualforce. The technique looks something like this.
<aura:component ...>
    <aura:attribute name="message" type="String"/>
    <aura:attribute name="vfHost" type="String"/>

    <!-- Input field for message "data" -->
    <lightning:input type="text" label="Message:"
        value="{!v.message}"/>

    <lightning:button label="Send to Visualforce"
        onclick="{!c.sendToVF}"/>

    <!-- The Visualforce page to send data to -->
    <iframe aura:id="vfFrame"
     src="{!'https://' + v.vfHost + '/apex/myvfpage'}"/>

</aura:component>

The Visualforce page does the work that’s disallowed in Lightning components. You can pass messages (requests and responses) between the Visualforce iframe and your Lightning component using the window.postMessage() API, in JavaScript code you add to your Visualforce page and your component’s controller.

For more, including a much more complete code sample, see Communicating Between Lightning Components and Visualforce Pages on the Salesforce Developers blog.

retargeting