Loading Javascript scripts that interact with ports

Hello, this is a question about optimal script loading.
Suppose you need to interoperate with some Javascript library, which you are doing through ports, so in the head you have something like:

 // This is the script that needs loading, let's suppose it defined `SomeJsWidget`
  <script src="http://somejswidgetthing.com/script.js"></script>

and after you have initialised your Elm app when you’re setting up your ports you have something like:

// Here I have to use `SomeJsWidget`
app.ports.initialiseSomeJsWidget.subscribe(function(args) {
    SomeJsWidget.init(args.config);
});

So putting it all together you might have an index.html file like:

<html>
<head>
  <meta charset="UTF-8">
  <title>Elm + Javascript</title>
  <script type="text/javascript" src="elm.js"></script>
  // This is the script that needs loading, let's suppose it defined `SomeJsWidget`
  <script src="http://somejswidgetthing.com/script.js"></script>
</head>
<body> <div id="myapp"></div>
</body>
<script type="text/javascript">

// Start the Elm application.
var app = Elm.Main.init({
    node: document.getElementById('myapp')
});
// Here I have to use `SomeJsWidget`
app.ports.initialiseSomeJsWidget.subscribe(function(args) {
    SomeJsWidget.init(args.config);
});
</script>
</html>

Now as I understand it, this is somewhat sub-optimal because rendering of the page is blocked so that http://somejswidgetthing.com/script.js can be downloaded and loaded. The normal solution is to add either async or defer attribute to the <script> tag a la:

  <script async src="http://somejswidgetthing.com/script.js"></script>

However, this unfortunately causes a problem in that when the port setup Javascript is run SomeJsWidget is not yet defined.

So I guess my question is, has any one looked into this issue and come up with a workable solution?
Or perhaps we just accept that script downloading takes place synchronously, maybe it doesn’t matter so much that rendering is blocked since it’s the Elm app that does most of the rendering. In my particular case here it’s a full SPA so Elm does all the rendering but in theory elm might only be rendering a single div in a larger page.

I also realise that if you do get something working so that you can asynchronously load SomeJsWidget whilst the Elm app gets to render, then you are necessarily delaying the setting up of the port, and hence you might want to send an additional message to the Elm app when that port is setup and ready.

Anyway I guess I’m asking is there a best practice here?

I’ve not tried this, but you could possibly leave the script async and then add an onload listener to connect up the ports? This means you only end up actually connecting to the elm ports once the script has loaded.

That’s definitely worth trying, thanks. I’ll post if this is successful.

Update

Yes that’s working for me. In my particular case I don’t need to worry about it, but it’s possible the initialise doesn’t occur before you attempt to use the port in the Elm app. In that case, you need to send a message to the Elm app when the initialisation is complete.

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.