As a final part of the Winter ’24 Release recap, I prepared a selection of my favorite LWC new features that will undoubtedly benefit every Salesforce Developer.
Custom Component Instrumentation API (currently in Beta)
Salesforce brought in beta Custom Component Instrumentation API, a tool that enhances the observability of your Lightning web components.
With this API, you can directly monitor and track custom Lightning web components’ events and interactions within your org’s Event Monitoring. In the past, Event Monitoring tools only provided insights into your application as a whole, such as loaded records and page performance.
API’s limitations:
1. The feature is only available to customers who have acquired Salesforce Shield or subscribed to the Salesforce Event Monitoring add-on.
2. Custom Component Instrumentation API focuses specifically on Lightning web components and does not support Aura components.
How it works: By importing the log from the lightning/logger module into your component, you can easily log data messages to Event Monitoring. The log() function publishes data to a new event type in EventLogFile called Lightning Logger Event. This event type provides a structured representation of the event data, maximizing its utility within Event Monitoring.
<!-- myComponent.html -->
<template>
<lightning-button label="Approve"
onclick={handleClick}>
</lightning-button>
</template>
// myComponent.js
import { LightningElement } from 'lwc';
import { log } from 'lightning/logger';
export default class HelloWorld extends LightningElement {
constructor() {
super();
}
let msg = {
type: "click",
action: "Approve"
}
handleClick() {
log(msg);
}
}
Creation of Custom Elements using Lighting Web Security Enabled (currently in Beta)
From the Winter ’24 release, another fantastic feature is in Beta. When Lightning Web Security (LWS) is activated, you will be able to create custom elements in your Lightning web components.
Being a key feature of the Web Components standard, custom elements serve as an additional benefit of LWS in comparison to Lightning Locker.
So, custom elements are the building blocks of reusable web components, which you can create using customElements.define(). A basic custom element looks like this:
customElements.define('my-custom-element', class extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'closed' }).innerHTML = '<div>Custom Element Constructor</div>';
}});
To include a third-party web component within your Lightning web component, you can use the lwc:external directive. This directive allows you to add the third-party web component to your template. Once added, the third-party web component will be rendered as a native web component within your LWC template.
<template>
<my-custom-element lwc:external></my-custom-element>
</template>
How can you use a third-party web component?
- Insert the third-party web component as an LWC module with a .js-meta.xml configuration file. In this approach, the component’s JavaScript file should not exceed the maximum file size limit of 128 KB.
- Upload the third-party web component as a static resource. This can be achieved by using the loadScript method from the lightning/platformResourceLoader module. After that, include the custom element in your template using the lwc:external. Keep in mind that the maximum file size for each static resource is 5 MB, and an org can have up to 250 MB of static resources.
import { LightningElement } from 'lwc';
import { loadStyle, loadScript } from 'lightning/platformResourceLoader';
loadScript(this, myResourceName + '/myResourceName.js').then(() => {
// your code with calls to the JS library
});
Dynamic Import and Instantiation of Lightning Web Components
Dynamic component creation helps you to avoid loading large modules that are not always necessary. Also, It allows you to instantiate component instances when the underlying component constructor is not known until runtime.
Dynamic import is convenient for making components more customizable. However, it’s important to be mindful of potential performance issues introduced by dynamic imports.
To use dynamic import and instantiation with Lightning web components, you need to enable Lightning Web Security.
How it works: When you want to instantiate a dynamic component in Salesforce, there are a few steps you need to follow. First, make sure that the component’s configuration file has the lightning__dynamicComponent capability included.
<?xml version="1.0" encoding="UTF-8"?> <LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata"> <apiVersion>59.0</apiVersion> <capabilities> <capability>lightning__dynamicComponent</capability> </capabilities> </LightningComponentBundle>
To instantiate the component dynamically, you’ll need to use the <lwc:component> managed element in the component’s HTML file.
<template> <div class="container">
<lwc:component lwc:is={componentConstructor}></lwc:component>
</div> </template>
This element acts as a placeholder in the DOM and is responsible for rendering the specified dynamic component. And don’t forget, you should use the lwc:is directive along with <lwc:component>. This directive is used to provide an imported constructor at runtime to the <lwc:component> managed element. You can pass an expression to lwc:is, which should resolve to a LightningElement constructor at runtime.
Note that if the constructor is falsy, the <lwc:component> tag, along with all its children, won’t be rendered. On the other hand, if the expression value is defined but not a valid LightningElement constructor, an error will be thrown.
In the component’s JavaScript file, import the custom element using the import() syntax.
import { LightningElement } from "lwc";
export default class extends LightningElement {
componentConstructor;
// Use connectedCallback() on the dynamic component
// to signal when it's attached to the DOM
connectedCallback() {
import("c/concreteComponent")
.then(({ default: ctor }) => (this.componentConstructor = ctor))
.catch((err) => console.log("Error importing component"));
}
}
The import() call returns a promise that resolves to a LightningElement constructor. This constructor determines the tag name used for rendering the dynamic component, replacing the lwc:component placeholder.