The last piece heralding the dawn of modern JavaScript (sometimes thought of as ES6, but we're past that now) arrived last month when two browsers (Chrome and Safari) shipped support for ES6 modules natively without developer flags. It's now possible to write all this stuff (modules, classes, arrow functions, const/let variables, Promises) using just your code and not relying on transpilers!
I've been using Traceur on a hobby project for a couple years now but I had put development on hold for a few months. Traceur is the transpiler-that-lost (development community declared Babel the winner and Traceur hasn't had a commit in over a year).
Picking the project up again in October 2017 and doing some debugging, I was mystified when my code was instantiating two instances of what should have been a singleton JavaScript service. Here is what my main HTML file looked like:
<script src="traceur.js"></script>
<script>
var options = new traceur.util.Options();
new traceur.WebPageTranscoder(document.location.href, options).run();
</script>
<script type="module" src="main.js"></script>
The first script loads the main Traceur library, the second script does the transpilation of any scripts of type "module" in the page. Browsers that do not understand ES6 modules ignore the main.js script element (up until September, this was every shipping browser).
Of course what was happening was that Chrome 61 was also loading in the main.js ES6 module itself (in addition to doing the transpilation). Thus, I was seeing two copies of things running in the browser.
The nomodule Attribute
The trick is to use the nomodule attribute on script elements that we want the browser to ignore if they understand what an ES6 module is:
<script nomodule src="traceur.js"></script>
<script nomodule>
var options = new traceur.util.Options();
new traceur.WebPageTranscoder(document.location.href, options).run();
</script>
<script type="module" src="main.js"></script>
Now Firefox and Edge will be able to load the page with or without ES6 module support enabled via developer settings.
Oh hey, welcome back! I haven’t really delved in to ES6 as a standard in and of itself. I think the best thing when new stuff comes out is to show how it ultimately will better serve whoever is ultimately paying the developer to code in the first place. That detachment creates a lot of headaches in general.
I’m still an adamant supporter or the best framework/library is no framework/library. Using small highly reusable functions keeps code much easier to maintain in the long term. I can’t count how many times I’ve seen a feature break in a newer version of some third party code and almost always to do something fairly simple in pure JavaScript.
Hi John! I highly recommend looking into ES6 for two things to start. It’s really easy and most modern browsers that I know of support them: 1) const/let variables (never use var again) and 2) arrow functions (“this” is bound lexically where you expect it to be bound… no more .bind())
http://caniuse.com/#search=const
http://caniuse.com/#search=let (no Opera Mini support)
http://caniuse.com/#search=arrow (no IE11/Opera Mini support)
Of course if you’re using a transpiler then you don’t need to worry about browser support.