3

I'm unable to get RequireJs to work with Locker Service turned on, so I'm trying to just use ltng:require. When using requirejs, I can load a dependency and inject it my module like this:

define(["helper/util"], function(util) {    
});

Is this possible with ltng:require? It seems like the only way to reference anything that was loaded with ltng:require is if it is explicitly set on the window object. I could edit existing libraries that follow the module pattern to assign their apis to window, but that doesn't feel like the right way to go.

1 Answer 1

5

RequireJS should work with LS (use of requirejs will not pass salesforce security review if you are ultimately looking to publish your package to appexchange though). Requirejs is also not LC lifecycle (rendering/event loop) lifecycle which is the other reason we created ltng:require.

Please keep in mind that Lightning Platform itself has a long stabnding security mandated restriction on CSP script-src that only allows your external javascript resources to be retrieved from Static Resources - this means no matter what you use (and also independent of Locker) no scripts can be retrieved from non Salesforce CDNs.

ltng:require is already compatible with the common module registration pattern of:

(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
  typeof define === 'function' && define.amd ? define(['exports'], factory) :
  (factory((global.d3 = global.d3 || {})));
}(this, (function (exports) { ...

What does the library export preamble look like that you are using? How are you loading requirejs itself?

I am trying out the latest requirejs now to see if I also hit an issue.

UPDATE: so after digging into require.js I've found that while the code has the appearance of using the standard module pattern it misses the mark by never actually exporting to global. Instead the code creates lexically scope var requirejs; which is not the same as exporting to global scope under strict mode. The good news is that requirejs does in fact load using ltng:require and if we get a trivial change to actually export global. require.js = requirejs; this would work. I am making that change to requirejs locally to test this to completion. If that is successful I'll look at opening a pull request to https://github.com/requirejs/requirejs to get this fixed in the library.

UPDATE #2: got quite a bit farther and finally hit a Locker specific issue but we're very close. SecureScriptElement is not quite emulating a real script element in the area of onload events that requirejs chokes on (and rightly so). I'm opening a bug to track getting this fixed now.

1
  • I'm loading require from a static resource by saying: <ltng:require scripts="{!$Resource.zip_name + '/require.js'}" afterScriptsLoaded="{!c.scriptsLoaded}" /> In the script I'm attempting to load a module from a static resource using require. I'm getting the error Uncaught TypeError: Cannot read property 'removeChild' of undefined throws at /resource/1478107281000/require.js:358:46. Is that the same issue you are noticing?
    – jwolf
    Commented Nov 3, 2016 at 20:03

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .