1

I have an html document that contains the following code:

...
<head>
  ...
  <link href="//assets.example.com/css/bootstrap.min.css" rel="stylesheet">
  <script src="//assets.example.com/js/bootstrap.bundle.min.js"></script>
</head>
...

The context:

This html document sits in the SPIFFS of a microcontroller. The chip hosts a tiny webserver and can serve static files (like, for instance, this html file). The webserver can be reached either from the internet (automation.example.com) or from my local wifi network (192.168.0.49:1337).

The problem :

Reading static files from the chip's memory is very slow (it takes about 7s to get an HTTP 200 from the webserver when I request the self-hosted css).

This is why I moved all the css/js files to my CDN. The response is now lightning fast but I have to consider the case when the internet is down (assets would not load) and I can only reach the chip via my local network.

The solution :

I want to load those assets from my cdn if the chip is reached from the internet (with absolute urls), or from the SPIFFS if the internet is down (with relative urls).

In other words, I'm thinking about the following logic : if the browser's url is an ip or ends with ".local" (multicast dns), do include like this :

<link href="/bootstrap.min.css" rel="stylesheet">

otherwise, if the browser url is my domain "example.com", do include like this :

<link href="//assets.example.com/css/bootstrap.min.css" rel="stylesheet">

Can you help me with the js code? I can only use client-side code. I believe I am going to need window.location.hostname and a few regex but are there more elegant ways of doing this?

So far I've tried this without any great success :

<head>
  ...
  <script>
    let hostname = window.location.hostname;
    let cdn = '';

    if ('automation.example.com' === hostname) {
      cdn = '//assets.example.com';
    }

    var head = document.getElementsByTagName('head')[0];
    head.insertAdjacentHTML('beforeend', '<link href="' + cdn + '/css/bootstrap.min.css" rel="stylesheet">');
    head.insertAdjacentHTML('beforeend', '<link href="' + cdn + '/css/login.css" rel="stylesheet">');
    head.insertAdjacentHTML('beforeend', '<script src="' + cdn + '/js/bootstrap.bundle.min.js"></script>');
  </script>
</head>

It does not like the "script" insertion part : Uncaught SyntaxError: '' literal not terminated before end of script

Maybe I need Promises to avoid flashing of the DOM

Musa
  • 1,334
  • 1
  • 11
  • 21

1 Answers1

0
<head>
  ...
  <link id="aaa" href="//assets.example.com/css/bootstrap.min.css" rel="stylesheet">
  <link id="bbb" href="//assets.example.com/css/login.css" rel="stylesheet">
  <script id="ccc" src="//assets.example.com/js/bootstrap.bundle.min.js"></script>
  <script>
    let hostname = window.location.hostname;
    let cdn = ''; // SPIFFS

    if ('automation.example.com' === hostname) {
      cdn = '//assets.example.com';
    }

    // bootstrap.min.css
    let aaa = document.getElementById('aaa');
    aaa.href = cdn + '/css/bootstrap.min.css';

    // login.css
    let bbb = document.getElementById('bbb');
    bbb.href = cdn + '/css/login.css';

    // bootstrap.bundle.min.js
    let ccc = document.getElementById('ccc');
    ccc.src = cdn + '/js/bootstrap.bundle.min.js';
  </script>
</head>

This works but I am seeking a more elegant solution. It tries to load the assets from the cdn no matter the context (internet/local network). If we have internet, it will request the files twice, which is not a big deal as they are cached. If we do not have internet, it will load from the chip's file system.

Edit: see @ColdIV 's comment for the solution.

Musa
  • 1,334
  • 1
  • 11
  • 21