mdn/web-components-examples

Order of script and webcomponent

mitra42 opened this issue · 6 comments

I was trying to use what I'd learned from these examples and not making much progress until I noticed a counter-intuitive and (as far as I can find) undocumented issue.

In https://github.com/mdn/web-components-examples/tree/master/popup-info-box-web-component for example, the code is:

    <form>
      <div>
        <label for="cvc">Enter your CVC <popup-info img="img/alt.png" data-text="Your card validation code (CVC) is an extra security feature — it is the last 3 or 4 numbers on the back of your card."></popup-info></label>
        <input type="text" id="cvc">
      </div>
    </form>

    <script src="main.js"></script>

But if you put the <script line anywhere BEFORE the <popup-info> it fails e.g.

    <script src="main.js"></script>
    <form>
      <div>
        <label for="cvc">Enter your CVC <popup-info img="img/alt.png" data-text="Your card validation code (CVC) is an extra security feature — it is the last 3 or 4 numbers on the back of your card."></popup-info></label>
        <input type="text" id="cvc">
      </div>
    </form>

Then it fails to have any attributes in popup-info and displays the default image instead.

Is this a bug, or a feature ? For pretty much anything else the normal practice is to put the script in the <head> section, but in this example putting the <script> in <head> explicitly fails.

Further research shows that most of the examples use the defer property on the script, but that still seems counter-intuitive, as I'd expect the script to have to run BEFORE parsing the html so that the parser recognizes the webcomponent ?

It fails when you put the <script> element in the head because the code is executed sequently, from top to bottom. If a script is executed that manipulates part of the DOM, before the DOM has actually been parsed, then it will fail.

This is why old-fashioned code tended to put <script> elements at the bottom of the body, to make sure the DOM was in place before running scripts that rely on it.

There are various other means to get round this problem, which are documented at https://developer.mozilla.org/en-US/docs/Learn/JavaScript/First_steps/What_is_JavaScript#Script_loading_strategies.

The modern way to deal with this is to use the defer keyword, which basically says "don't stop here and download and execute the script — keep the loading the DOM".

My code here was old-fashioned, so I've updated the example to use <script src="main.js" defer></script> inside the document head.

Understood - I think it would be good if the MDN doc were clearer about this (to add "defer"), intuitively I assumed the opposite was required, i.e. that the script had to be loaded BEFORE the dom was parsed so that it would know the definition of the custom elements.

We do cover this in a number of places on MDN, but I am happy to add a note to the web components stuff too if that would help. What doc were you looking at in particular?

Sure - it was on
https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements
Which I got to from
https://developer.mozilla.org/en-US/docs/Web/Web_Components ;
which is what comes up top if you google MDN Web Components

OK, note added to the first article.