4

I was trying to use Mapbox in an LWC component, by importing its library using loadScript, but I am only getting an undefined error in the promise.

I created a ZIP bundle with the CSS and JS files (mapbox.css and mapbox.js), and also a test JS file to check there is no problem with the ZIP itself (example.js with a console.log message).

I have uploaded it using the Metadata API, and set it as an application/zip, here is the XML file contents:

<?xml version="1.0" encoding="UTF-8"?>
<StaticResource xmlns="http://soap.sforce.com/2006/04/metadata">
    <cacheControl>Private</cacheControl>
    <contentType>application/zip</contentType>
</StaticResource>

This is the example code I am trying to run:

import { api, LightningElement } from 'lwc';
import { loadScript, loadStyle } from 'lightning/platformResourceLoader';
import MAPBOX from '@salesforce/resourceUrl/mapbox';

export default class InquiryMap extends LightningElement {
    @api recordId;
    mapboxInitialized = false;

    renderedCallback() {
        this.bootMapbox();
    };

    bootMapbox() {
        if (this.mapboxInitialized) {
            return;
        }

        this.mapboxInitialized = true;
        
        loadStyle(this, MAPBOX + '/mapbox.css')
        .then(() => {
            console.log('Mapbox CSS is ready! =)');
        })
        .catch((err) => {
            console.log('Error (CSS)', err);
        });

        loadScript(this, MAPBOX + '/example.js')
        .then(() => {
            console.log('Mapbox Example JS is ready! =)');
        })
        .catch((err) => {
            console.log('Error (Example)', err);
        });

        loadScript(this, MAPBOX + '/mapbox.js')
        .then(() => {
            console.log('Mapbox JS is ready! =)');
        })
        .catch((err) => {
            console.log('Error (JS)', err);
        });
    };
}

But this is the output in the console:

I am a example JS file
Mapbox Example JS is ready! =)
Mapbox CSS is ready! =)
Error (JS) undefined

The line with the content Mapbox Example JS is ready! =) is from the example.js file.

I have checked the files are OK by opening them in a browser window in the Salesforce URL, and everything looks fine, but as I am not getting any details about the error I do not know what can I do.

mapbox.js load mapbox.js contents

The contents of the failing JS library can be found here: Mapbox GL 2.0.1.

Any help would be much appreciated!

0
7

Upon debugging with the Regular Mapbox GL regular version using the Salesforce Locker Console discovered that the issue is because the CSP required for getting this working is not supported by Salesforce Locker service.

worker-src blob child-src blob are not supported MIME types in the locker.

Next, I discovered that Mapbox provides an alternative approach documented in this section for sites that have a Strict CSP policy. This is documented here.

Upon using this approach I discovered that there is this error that pops up

Error (JS) TypeError: a.Worker is not a constructor at new gp (mapbox:1) at xp.acquire (mapbox:1) at new Eh (mapbox:1) at new Id (mapbox:1) at Map._updateStyle (mapbox:1) at Map.setStyle (mapbox:1) at new Map (mapbox:1) at eval (mapbox.js:67)

This error is because the Locker Service prevents the use of JavaScript Worker

Here are a few suggestions I would like to leave here

  1. Use the out of box base component using the lightning-map component

If the above does not meet then use the below options

  1. Use a Visualforce and iframe the page inside the LWC Component. Using this approach there won't be any locker restrictions.
  2. Reach out to MapBox support to see if they have any recommendations. Is there an alternative SDK without using the Javascript worker? You can point them to this post.
5
  • If you have to use Visualforce and iframe be careful about URLs - there is no API in Salesforce to generate a VF URL from a Lightning context or vice versa. If you are able to rely on redirection of URL then "/apex/PageName" will work. Next worry about how to communicate between the Visualforce page and the LWC. If you are in a community you cannot use Lightning Message Service, and there is no real viable approach since the standard pubsub code does not work in this scenario.
    – Phil W
    Dec 27 '20 at 8:44
  • @phil W The LMS is available from spring 21 for communities as well! Note you can always use post messages to post messages. The Salesforce Map component uses iframe and uses window.postMesages to communicate Dec 27 '20 at 13:34
  • good to know that community support is on the way. As to post message, this only works when the locker service permits it (so certainly not across package namespace boundaries, for example).
    – Phil W
    Dec 27 '20 at 13:54
  • Why would it not work with namespace? Locker does not restrict post messages. If locker is preventing it that means it's a bug within the locker service. V2 of locker will make this much easier! Dec 27 '20 at 14:06
  • It is by design, I believe. See this Q&A.
    – Phil W
    Dec 27 '20 at 15:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.