1. 2

I am developing a JavaScript widget. As an example, let’s say the widget displays a list of posts published by a given customer.

The usual approach is something like this:

<div id="myposts-widget" data-customer-id="42">Loading...</div>
<script src="https://www.myposts.com/widget.js"></script>

First, the browser loads, parses and executes the script. Then, the script looks up the customer ID, fetches the list of posts and renders the widget. It is simple and it works. But the main drawback of this approach is the latency introduced by having two roundtrips to the server: one to fetch the script, another to fetch the data.

This is the reason why I’m thinking of injecting the initial data as a JSON snippet directly in the JavaScript sent by the server, in order to improve loading time by avoiding a roundtrip to the server.

The code would look like this:

<div id="myposts-widget">Loading...</div>
<script src="https://www.myposts.com/widget.js?customer_id=42"></script>

Advantage:

  • 1 roundtrip instead of 2

Drawbacks:

  • The script needs to be dynamically generated server-side and cannot be statically hosted on a CDN.
  • The script cannot be cached as efficiently because it differs for each customer.

I had a look at numerous widgets/embeds all over the web, and it’s like everybody uses the first approach (with two roundtrips). Am I missing something? Do you have any recommandation or comment?

(Edited for clarity)

  1.  

  2. 2

    Why not embed the JSON in a data attribute for the containing div, same as you do for the ID? Or even just in a script tag that gets evaluated before the other tag?

    1. 2

      I usually do exactly that in apps that I work on:

      <script id="bootstrap"
              data-version="1507142129"
              data-user='{&quot;username&quot;: &quot;&quot;, &quot;id&quot;: null, &quot;organizations&quot;: []}'></script>
      

      Then I can grap the script element by id and read the data attributes.

      1. 1

        I can’t because the widget is embedded on my customer’s website. I control the widget, but I don’t control my customer website. The data used by the widget are provided by my servers, not by my customer’s website. (I edited the initial post for clarity.)

      2. 2

        One marginal improvement—even though it still uses 2 round-trips—is to put the <script> tag in the <head>, make it async, and ensure the JS it serves knows to wait for DOMContentLoaded.

        <head>
          <script async src="..."></script>
        </head>
        <body>
          <div ...></div>
        </body>
        

        At the very least, this causes the browser to start downloading the script earlier without halting the rendering.

        1. 2

          But what I really should have said was: benchmark, benchmark, benchmark.

          Is 2 roundtrips actually bad compared to other things? What if you use a CDN for the widget? What would be the extra load on your application server to essentially concatenate the widget and the id-based response?

          You probably don’t know the answers to all of these without significant benchmarking, especially taking into account geography and disparate network bandwidths. Maybe you do, and that’s great! But that’s where I’d start, other than the async trick above.

        2. 1

          you could use http/2, so roundtrips are not the big issue anymore (or just for really old clients)

          1. 1

            HTTP/2 reduces the round-trip time because the same connection is used for both requests, but there is still the issue of doubling the network transmission time, which is not compressible for physical reasons, except if I use HTTP/2 Push to preventively “push” the JSON data to the client.

          2. 1

            You don’t need to use a separate JS file. You could use some kind of server template library to output your “JSON” data into a script tag.

            <script type="text/javascript">

            var dataFromServer = $dataFromServer;

            </script>

            So for example, $dataFromServer might be a variable in your templating language that would contain your data as a JSON-formatted string.

            Or you could use the templating language to loop through your data and write out rows one by one, or whatever.

            1. 1

              This is exactly what I’m doing. I’m just wondering why most widgets I’ve seen in the wild don’t do this. The only one I could find that doesn’t return a purely static JS script, and where the server injects some dynamic data in the script before sending it to the browser is the Disqus comments widget.