In this blog, we will explore a powerful scenario. A Visualforce page dynamically loads an external JavaScript library. It defines a global method and passes it to a Lightning Web Component (LWC) using Lightning Out. The LWC can then invoke this method, optionally passing parameters, to generate dynamic responses. This use case demonstrates seamless interoperability between Visualforce and modern Lightning Web Components.
Problem Statement –
Developers often faces a critical limitation when embedding an LWC in a Visualforce page using Lightning Out. This limitation is imposed by Lightning Locker / Lightning Web Security. This isolation ensures that LWCs run in a secure environment. They cannot directly access global objects, scripts, or functions defined in the Visualforce page.
If a Visualforce page dynamically loads a script like Lodash, it defines a global function (myUtilityFunction). This function is used to manipulate data. The LWC cannot directly invoke this function. This is due to the isolation boundary. This creates a barrier to leveraging shared utilities or libraries across these frameworks.
Key Challenges:
Direct interaction between the Visualforce page and the embedded LWC requires workarounds.
LWCs cannot access global methods or objects defined in the Visualforce page.
External libraries dynamically loaded in the Visualforce page are invisible to the LWC.
Example –
Consider the below LWC and VF page. In the VF page, we called the loadash script. We declared a function named “myUtilityFunction” and added it in the window object.
Now, while calling myUtilityFunction declared in VF page in LWC, it will through the error, as this function will not be exposed to LWC due to locker service –
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
To address this limitation, we implemented a structured workaround that facilitates communication between the Visualforce page and the embedded LWC. The solution involves three main steps:
Dynamic Script Loading in Visualforce: The Visualforce page dynamically loads the external script (e.g., Lodash) and initializes it. A utility function (myUtilityFunction) is defined using this library and exposed as a global method on the window object.
Bridging the Gap with Lightning Out: The utility function is passed to the LWC. It is used as an attribute. This uses the Lightning Out framework. This allows the LWC to invoke the function indirectly, bypassing the security isolation.
Dynamic Method Invocation in LWC: The LWC uses the passed attribute to dynamically invoke the utility function. The function can process parameters provided by the LWC and return responses dynamically.
Fix Implemented
Visualforce Page
The Visualforce page dynamically loads the external library (e.g., Lodash) and defines the utility function. The function is exposed globally to be accessed by the LWC indirectly via Lightning Out.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
The loadExternalScript function adds the Lodash.js library by dynamically adding a “script” tag to the document’s head to load Lodash.
This ensures that the library is only loaded when needed.
Global Method Definition:
The myUtilityFunction accepts a parameter. It uses the Lodash join method to concatenate strings. The result is a formatted response, such as Hello World.
Using Lightning Out:
The initializeLightningOut function dynamically loads Lodash, defines the global method, and then initializes the Lightning Out framework.
It passes the global method (myUtilityFunction) to the LWC as the invokeUtilityMethod property.
Lightning Aura App
The Aura application serves as a container for Lightning components. It extends ltng:outApp to support embedding into the Visualforce pages. It includes <c:myLwcComponent>, embedding the Lightning Web Component. This app enables seamless integration and interaction between Visualforce and the LWC, bridging the gap between legacy and modern frameworks.
The Aura app extends ltng:outApp, which makes it compatible with the Lightning Out framework.
This extension allows the app to be loaded in environments outside Salesforce’s Lightning Experience. These include Visualforce pages or standalone websites.
Global Access:
The access="GLOBAL" attribute ensures that the Aura app is accessible from the Visualforce page. Without this, the Visualforce page wouldn’t be able to initialize the app.
LWC as a Child Component:
The <c:myLwcComponent> tag embeds the LWC into the Aura app. The Aura application serves as a wrapper. It allows the LWC to be rendered and interact with the Visualforce page through Lightning Out.
Lightning Web Component (LWC)
The LWC receives the global method as a property via Lightning Out. It dynamically invokes the method, passing parameters and handling responses efficiently.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Dynamic Method Invocation: The invokeUtilityMethod property dynamically calls the global method defined in the Visualforce page.
Parameter Passing: Parameters are passed from the LWC to the global method.
Alerts: Messages returned from the method are displayed using LightningAlert.
Demo Flow
LWC call the myUtilityFunction of VF using invokeUtilityMethod property in renderedCallbackLWC call the myUtilityFunction of VF using invokeUtilityMethod property on “Call Utility Method” button click
Page Load:
The Visualforce page dynamically loads Lodash.js and defines the global method.
The Lightning Out framework initializes the LWC and passes the method as a property.
Rendered Callback:
The LWC invokes the global method on load, passing a parameter.
The response is displayed in an alert.
Button Click:
Clicking the button in the LWC triggers the global method with a different parameter.
The new response is displayed in an alert.
Some Practical Use Cases Embedding LWC in External Websites via Lightning Out WHERE VF Pages can be used for initial pOC and Testing
You can embed LWC components into external websites using Lightning Out. This involves creating a Lightning Out application and including the necessary scripts in your external site’s HTML. This setup allows the external website to host Salesforce components and interact with them.
You can use the VF page to test the scenarios below first in Salesforce. This approach mimics the behavior of an external website. Do this before using the actual LWC on external websites.
Customer Support Chat Widget
Scenario: An external website integrates a Salesforce-powered customer support chat widget built in LWC.
Example: The website provides a script to track user behavior (e.g., current page, time spent), which the LWC uses to create contextual chat interactions.
How:
The website passes methods like getCurrentPage() or trackSession() to the LWC.
The LWC uses these to log activity or suggest pre-filled queries in the chat.
Custom Checkout Page for E-Commerce
Scenario: An external e-commerce website wants to use Salesforce data for checkout but retains its own frontend design and logic.
Example: The LWC fetches pricing, inventory, and shipping details from Salesforce. The external site handles custom payment scripts or UI flows.
How:
The external site passes methods like calculateDiscounts or validatePaymentDetails to the LWC.
The LWC calls these methods to get additional data for processing.
Lead Capture Forms
Scenario: An external marketing site embeds an LWC for lead capture, with custom validation provided by the website.
Example: The LWC handles record creation in Salesforce, but field validations are driven by scripts from the external site.
How:
The website passes methods like validateLeadFields(fieldData) to the LWC.
The LWC invokes these methods before submitting the data to Salesforce.
Conclusion
This solution shows how to overcome the isolation boundary between Visualforce and LWCs. It leverages dynamic script loading and the Lightning Out framework. Developers can create highly interactive and responsive applications. They do this by defining reusable global methods and passing them as attributes. This approach bridges the gap between legacy and modern Salesforce technologies. This approach showcases the potential of integrating Visualforce and Lightning Web Components effectively and securely. This integration ensures that while the frameworks operate within their constraints, they can collaborate seamlessly, offering a cohesive user experience.
Leave a comment