📢 Attention Salesforce Certified Trailblazers! Maintain your credentials and link your Trailhead and Webassessor accounts by April 19th. Learn more.
close
•
Start tracking your progress
Trailhead Home
Trailhead Home

Migrate JavaScript

Learning Objectives

After completing this unit, you’ll be able to:
  • Migrate JavaScript from Aura components to Lightning web components.
  • Share code between Aura components and Lightning web components.

Use JavaScript Modules

JavaScript is the beating heart of a Lightning web component. Without JavaScript, a component is a lifeless lump of mainly HTML. We got a glimpse of the JavaScript file in a Lightning web component in the previous unit when we saw how attributes in an Aura component map to JavaScript properties. Now we dig deeper into the JavaScript file.

Migrate JavaScript code from the separate client-side controller, helper, and renderer files in an Aura component to one JavaScript file in a Lightning web component.

A client-side controller in an Aura component is a JavaScript object in object-literal notation containing a map of name-value pairs. That’s a lot of words. Let’s look at an example in the PropertyPaginatorController.js file:

({
	previousPage : function(component) {
        var pageChangeEvent = component.getEvent("pagePrevious");
        pageChangeEvent.fire();
	},
    
	nextPage : function(component) {
        var pageChangeEvent = component.getEvent("pageNext");
        pageChangeEvent.fire();
	}
})

The format of JavaScript files in Aura components was designed several years before ES6 standards for features, such as JavaScript classes and modules, were standardized.

A JavaScript file in Lightning web components is an ES6 module, so you’re using standard JavaScript rather than the proprietary format used in Aura components. The JavaScript you write looks similar to the JavaScript you’d write for any other modern JavaScript framework.

Here’s similar JavaScript in the paginator Lightning web component.

import { LightningElement, api } from 'lwc';

export default class Paginator extends LightningElement {
    /** The current page number. */
    @api pageNumber;

    /** The number of items on a page. */
    @api pageSize;

    /** The total number of items in the list. */
    @api totalItemCount;

    previousHandler() {
        this.dispatchEvent(new CustomEvent('previous'));
    }

    nextHandler() {
        this.dispatchEvent(new CustomEvent('next'));
    }

    get currentPageNumber() {
        return this.totalItemCount === 0 ? 0 : this.pageNumber;
    }

    get isFirstPage() {
        return this.pageNumber === 1;
    }

    get isLastPage() {
        return this.pageNumber >= this.totalPages;
    }

    get totalPages() {
        return Math.ceil(this.totalItemCount / this.pageSize);
    }
}

We won’t look at each line of code. The main takeaway is that Lightning web components use standard JavaScript modules. That’s a good thing!

Share Code Between Aura Components and Lightning Web Components

To share JavaScript code between Lightning web components and Aura components, put the code in an ES6 module. Both programming models can access the shared code. Even if you don’t move all your code to Lightning web components, you can still access new functionality that you write in an ES6 module in an Aura component.

Let’s look at an example of a utils.js ES6 module.

/* utils.js */
/**
 * Returns whether provided value is a function
 * @param {*} value - the value to be checked
 * @return {boolean} true if the value is a function, false otherwise
 */
export function isFunction(value) {
    return typeof value === 'function';
}

The utils module exports an isFunction() function that returns whether the provided parameter is a function.

Here’s a c-libcaller Lightning web component that uses the utils module.

/* libcaller.js */
import { LightningElement, track } from 'lwc';

// import the library
import { isFunction } from 'c/utils';

export default class LibCaller extends LightningElement {
    @track result;
    
    checkType() {
        // Call the imported library function
        this.result = isFunction(
            function() {
                console.log('I am a function');
            }
        ); 
    }
}

The c-libcaller component imports the utils module and calls the isFunction function exported by the module. The argument passed into isFunction is a function so result is set to true.

Now, let’s look at a libcallerAura.cmp file that also uses the utils module.

<aura:component>
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>

    <p>Aura component calling the utils lib</p>

    <!-- add the lib component -->
    <c:utils aura:id="utils" />
</aura:component>

The libcallerAura Aura component includes a reference to the c:utils ES6 module. We added an aura:id so that we can get a reference to the module in JavaScript code.

Here’s the libcallerAuraController.js file.

({
    doInit: function(cmp) {
        // Call the lib here
        var libCmp = cmp.find('utils');
        var result = libCmp.isFunction(
            function() {
                console.log(" I am a function");
            }
        );
        console.log("Is it a function?: " + result);
    }
})

The component’s controller uses cmp.find('utils') to match the aura:id in markup and get a reference to the module. The utils ES6 module exports isFunction(), which the Aura component calls. The argument passed into isFunction() is a function so result is set to true.

Use Third-Party JavaScript Libraries

To use a third-party JavaScript library in an Aura component or a Lightning web component, you must upload the library as a static resource. The syntax for working with the static resource is different in the two programming models.

In an Aura component, use the <ltng:require> tag in markup to load the static resource.

<ltng:require scripts="{!$Resource.resourceName}"
    afterScriptsLoaded="{!c.afterScriptsLoaded}" />

resourceName is the name of the static resource. The afterScriptsLoaded action in the client-side controller is called after the scripts are loaded and the component is rendered.

In a Lightning web component, import the static resource in JavaScript.

import resourceName from '@salesforce/resourceUrl/resourceName';

You then use loadScript and loadStyle to load the third-party library.

For details on using the imported library, see Use Third-Party JavaScript Libraries in the Lightning Web Components Developer Guide.

Dynamically Creating Components

In an Aura component, you can dynamically create a component in JavaScript using $A.createComponent(). There’s no equivalent for dynamically creating a component in a Lightning web component.

This architectural decision is deliberate. The main reason for not replicating this pattern in Lightning web components is that the pattern in Aura components has led to buggy and convoluted code.

A better alternative in Lightning web components is to create multiple HTML templates for your component. The component’s render() method can switch templates based on the component needs. This pattern is more similar to the route splitting used in other JavaScript frameworks.

An Opportunity to Refactor

As you migrate JavaScript code, notice that it’s not a line-by-line conversion. It’s a good opportunity to revisit your component’s design.

Migrating to a new programming model is like taking a new path that leads you to the same destination. The sights and sounds (and code you write) along the way are different.

Migrating a component is also a great opportunity to use fancy new ES6 features, such as JavaScript modules, that you probably aren’t using in Aura components.

The Modern JavaScript Development Trailhead module gives you a great overview of these new features.

Resources

retargeting