Hacker News new | past | comments | ask | show | jobs | submit login
ECMAScript 2016+ in Firefox (blog.mozilla.org)
260 points by robin_reala on Feb 22, 2017 | hide | past | favorite | 91 comments



Realistically, when are we going to see the modules situation resolved?

ES2017?

ES2018?

I know, I know, just use a transpiler and emit a bundle... but really?

It's been a draft since 2015, and no browsers have any support for it yet, despite full support for the rest of the standard?

Are modules really that controversial?

I'm kind of disappointed, honestly, that despite all the progress in the ecosystem, this long standing issue still remains mysteriously unsolved, by anyone.

If you're using a transpiler anyway, who really cares if you have native support for the language features?


Note to people reading this: module support in this post seems to mostly refer to the loading of modules. The spec is pretty clear about the syntax and semantics of modules, except when it comes to loading which it more or less says is "up to the runtime" to figure out.

There's some interesting (or not, depending on your POV) conversation/debate going on between the nodejs world and the browser world, which are – I suppose – the only two "real" runtime environments where JS is widely used.

There's a lot of effort going into figuring this out, but from a lowly developer point of view it's increasingly frustrating to see that two years on from when the module standard was ratified, we still have to resort to compiling modules to a yesteryear solution such as AMD, CJS, or even globals – or, if you're so inclined, all at once via UMD.

One big issue in figuring this out, as far as I understand it, is determining whether some JS code is ES2015+ or not, since the semantics of loading such a module changes. It may sound simple, but there's plenty of situations where the answer is ambiguous, but picking the wrong answer will result in a change of behavior for older code. Since TC39 is very wary of not breaking backwards compatibility (and kudos to them for it!) simply saying something like "assume ES2015" just won't do.

There was a proposal to change the module semantics to require ES2015 modules to include at least one import or export statement, since these would break in pre-ES2015 runtimes, removing any ambiguity in the syntax. Unfortunately, it seems this proposal is all but dead at this point. (And probably for good reasons I simply don't know about.)

DISCLAIMER: I may well be incorrect about the details in the above, but I think the overall picture is more or less correct.


From what I have been told, this proposal is likely to win out: https://github.com/tc39/proposal-dynamic-import


Looks to be a stage 3 proposal[1] so that seems likely. Had a quick read through, looks like a pretty solid proposal. If I read it correctly, it means `import()` will only load ES2015 modules. (I.e. the result of HostResolveImportedModule is a Module Record. That's a good thing as far as I'm concerned.

Given the history of discussion around this, this seems surprisingly low key and reasonable. (The System.loader stuff was gnarly!)

But what does this mean for nodejs? I don't see how this rhymes with current proposals re `require.import` and the likes. If the above proposal wins out it becomes a language spec, so presumably will also become available in nodejs, and if they go ahead with the ideas mentioned in another comment here, we'd have both `import(specifier)` and `require.import(specifier)` – seems pretty confusing, but maybe I'm getting it all wrong?

[1]: https://github.com/tc39/proposals


The purpose of Babel/transpilers is to eventually allow users to use the native versions of language features. Native support will eventually be faster (not at first), will result in less code sent to users (compiled code is larger), and easier to debug (don't need sourcemaps).

https://v8project.blogspot.com/2017/02/high-performance-es20...

I made https://github.com/babel/babel-preset-env to make it easier to transition. Hoping that Babel makes it easier to not have to think about whether you are using native or not, so we'll work on that workflow.


Thanks for your excellent efforts hzoo, and of course everyone else involved! The new env preset really makes it much easier to maintain a forward looking code base.


Thanks! Will be working torward making the preset-env + babel-minify combo work much better soon.


Preliminary modules supports can be enabled in Firefox Nightly by changing dom.moduleScripts.enabled to true in about:config. There are still some bugs (https://bugzilla.mozilla.org/show_bug.cgi?id=568953) to fix before we can ship this.


What does that flag actually enable? I can't seem to get it to load any modules (even with type="module") - there hasn't been any movement on that bug for a while, and the last comment says "looks like it is only supported for chrome documents"... I know I'm just being impatient, but I'd love to ditch Babel for my own projects and this is my last "must have" ;)


It was only supported for chrome documents until https://bugzilla.mozilla.org/show_bug.cgi?id=1330657 landed in Firefox Nightly two weeks ago. So if you have a current nightly and set the "dom.moduleScripts.enabled" preference to true in about:config, <script type="module"> should work.


> If you're using a transpiler anyway, who really cares if you have native support for the language features?

Looking forward to the day alternative languages start targeting WebAssembly instead of JavaScript.


You mean "the day WebAssembly gets out of preview/alpha/worse status in all major browsers".. yeah, don't we all --- wouldn't hold my breath. Once there, give it another 2 years to actually mature in the wild.


I agree, after all we still have some customers on IE 8, but one can wish for it.


Forget about browsers, have you read the clusterfuck that Node.js is aiming for with ES6 Modules?

https://medium.com/the-node-js-collection/an-update-on-es6-m...


It really is a shame isn't it? I'm not sure why the unambiguous syntax proposal was shot down – there were good reasons I'm sure – but I thought it was a pretty solid idea.


Oh goodie another file extension.


JS modules are working in Safari Technology Preview today - so it should be available to everyone soon enough. Pretty simple too, you load your entry point like this -

<script type="module" src="main.js">

And then main.js runs in strict mode, can use "import", etc.


Even if the browsers support modules, you still will want to generate a bundle, because loading modules on the fly would require lots of tertiary HTTP requests.


I was under the impression HTTP/2 would make this concern irrelevant... but I'm no expert on the subject. I suppose its a valid point.

I just don't see what the point in having support for additional js language features natively is if you're forced to use a tranpiler regardless.

If you supported only, say, 50% of ES2016, and modules you could plausibly deliver unbundled native ES6; it'd be pretty cool; but modules aren't just a random feature from the pot; there is literally no serious modern web application that doesn't use them.

So... I'm struggling to see the ES2016 feature complete map (without modules) as really meaningful for anyone, practically.


HTTP/2 won't make a serious difference in regards to that, bundling will always be required. Also minifying will always be required, so there's always going to be a build step anyway.


Minifying yes but why bundling?

https://hpbn.co/http2/#request-and-response-multiplexing

HTTP2 takes care of loading files via multiplexing, and ES6 modules take care of loading JS in proper order, no need to bundle AFAIU.


Sorry for the late reply. Multiplexing is not a panacea, there's still some overhead, and even if there wasn't there's still a point where you start to lose lot of performance by limiting gzip compression (the smaller the file the less efficient the compression is).

You can read more about why we'll always need a bundling step at the following links:

http://engineering.khanacademy.org/posts/js-packaging-http2....

https://medium.com/@asyncmax/the-right-way-to-bundle-your-as...

https://medium.com/webpack/webpack-http-2-7083ec3f3ce6#.74q6...


Transpiling also drastically increases the size of code. Having these features natively could significantly reduce bundle size.


If you're using a transpiler anyway, who really cares if you have native support for the language features?

I've been wondering the same thing. Surely the only exciting new language features are the ones that can't be polyfilled?

Native support means it can be smaller and faster, sure. But I don't think you can blame web bloat on Javascript's lack of built-in modules. Web bloat is caused by an arms race of advertising and tracking plugins. I don't care much about making those more efficient, I just want the advertising and tracking stripped out.


Native async functions are nice for the better debugging support (chrome will give you full stack traces that are as nice as ones from synchronous code).


I wouldn't be surprised if a lot of the major players are holding back on JS modules until after WASM gets farther along.

It could seem like a waste of effort to standardize and implement JS modules (which "everyone already has" via transpilers) when they expect people to move quickly to language agnostic WASM modules once they become available.


With native support you can debug in a current web browser. Also, native support means that you can ditch the compiler / transpiler earlier.


es6 modules are basically sugars for async loading (AMD) with some limitatons/restrictions.


I can see that strict mode inside a function using default parameters should throw according to the spec ( https://tc39.github.io/ecma262/#sec-function-definitions-sta...) but does anyone know why? Is strict mode something we should now be avoiding?



my guess: to not complicate parsing complex expressions in default parameters

  // non-strict mode top-level code
  
  function foo (complex = eval("1+1"), moreComplex = (function(){ with (this) { return bar; } }())) {
      
	  "use strict"; // go back and parse the parameters again but this time with strict mode semantics
      
	  // ...
	  
  }


See here [1], under "Why make this change?".

[1] https://www.nczonline.net/blog/2016/10/the-ecmascript-2016-c...


Ah that makes sense - by the time the parser sees a 'use strict' it's too late to apply strict mode to the default arguments. Thanks!


"use strict" has to be outside of the function in this case.


According to the documentation on MDN[0], it's a part of "early errors" and you should rather but the "use strict" outside the function instead of on the inside. I'm not entirely sure of why the spec wants it to be outside rather than inside though...

- [0] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...


> you should rather [put] the "use strict" outside the function instead of on the inside.

Modules and classes are always in strict mode. In practice, it really isn't an issue.


If you're using a bundler and transpiler, ES modules are already in strict mode.


Like most folk I don't use TC39 modules, just npm/commonjs modules. I guess when/if npm and node (and all the frontend tooling that uses npm and node) starts using TC39 modules they'll get popular.


Es6 modules suck because they will litter the global scope, while commonjs/nodejs modules can be required locally.


ES6 modules are great because they're statically analysable, whilst CommonJS modules aren't.


You can statically analyze CommonJS modules (and they are most often used in a statically optimizable way), they just aren't statically optimizable in the general case.


just parse it like any other js code


Declarations can be analyzed statically. Declarative stuff is convenient that way.

If you have to execute code, things get messy.


By that do you mean you can 'just parse' CommonJS modules?

(If so) CommonJS allows you to dynamically alter module.exports anywhere within your module. You can't determine what those exports are just by parsing, you'd need to execute the code.


> CommonJS allows you to dynamically alter module.exports anywhere within your module

It's certainly a risk, but that isn't a common practice.


There's also ...

  if(Math.round(Math.random()) === 1) {
    export let foo = bar; // have fun debugging!
  }
I think it would also be fine to execute modules to see what's in module.exports, while some modules might have side effects like writing to /etc/passwd without calling any method, it's not the norm.


> There's also ... [...]

(I assume you meant to write your example in CommonJS style, because that's not valid a ES6 export, they must be top-level).

Doesn't your example highlight exactly why even executing the code wouldn't even help you there?


Didn't know you could only export at the global scope. Wanted to show that you could do stupid, hard to analyze things in ES6 modules too. But maybe you can't !? Although I don't want a committee to not only decide what is stupid or not, but also hard code it into the spec so I can't do some things even if I have very good reasons to. Like being able to require modules locally to make the code easier to reason about, and easier to delete, copy, share, reuse and manage. It's what made NodeJS so popular, because it's so easy to use, reuse and share modules.


> Wanted to show that you could do stupid, hard to analyze things in ES6 modules too. But maybe you can't !?

You can't, at least not in this way. A module's imported and exported names are statically determined. Of course, you can just export a single object, and then make that object arbitrarily complex depending on runtime behavior.

> Like being able to require modules locally

Not sure what this means.


locally: inside functions


The fact it's allowed at all is the problem though, and precisely why ES6 modules are superior.


Async Functions Status: Available from Firefox 52 (now Beta, will ship in March 2017).


Good to see such quick progress in this area in major browsers. It's worth noting that WebKit also has 100% support for ES 2016+. So now only Edge is lagging in this regard.

[0] http://kangax.github.io/compat-table/es2016plus/#webkit


And yet WebKit has 99% on ES5, while Edge and Firefox have 100% (and Chrome has 98%).

http://kangax.github.io/compat-table/es5/


But webkit has 100% support for ES6 (according to kangex) while nobody else does...


Yeah, and it's great. It's just that WebKit's (and Apple's) efforts are sometimes.. lopsided.


On the one hand, the deficiencies in that table don't look all too serious. Maybe Date.toJSON missing is the worst.

On the other hand, that's a poor excuse - why the heck haven't they fixed these issues? Cross browser compat is annoying enough as it is.


It doesn't help when one needs to target enterprise markets or devices that only have their factory provided browser.


That's what Babel[0] is for. Realistically you can't rely on native ES2016 for any target audience yet, but with Babel you can blissfully live in the future, today :)

Also, thrown in core-js[1] while you're at it.

[0] https://babeljs.io/

[1] https://github.com/zloirock/core-js


Babel is only part of the history, then there is HTML and CSS support levels.

Some of our projects are with customers that still rely on XP with IE 8, require using the "Internet Browser" for pre-Android 4.4 or Windows Safari (!) or IoT devices without updatable browsers.


Your customers are lucky to have you. I imagine they will rely on XP and IE8 as long as you are around.


Not me personally, my employer is quite big, and any consulting company will happily sell such services.


Yep and with Babel we recommend using https://github.com/babel/babel-preset-env to compile only what's missing in the targets you support.

Hopefully we have a better solution about making multiple bundles (separate one for IE) soon


I'm currently experimenting with if-no-window.Promise-then-polyfill via polyfill.io (I dont quite trust synchronous dynamic script loading yet, but we'll see if that's robust enough on old browsers). Sure, old browsers need an extra roundtrip, and it's an additional point of failure - but it simplifies dev tooling, and if your users actually cared about perf, they wouldn't be using ancient browsers.

It won't fix many issues (e.g. CSS), but at least some, and without making your build complicated, and without performance sacrifices for the majority of devices.


> if your users actually cared about perf, they wouldn't be using ancient browsers.

Many of them do care, but not the IT department that vets their machines.


There are pros and cons there. The overhead isn't huge; if you use any ads whatsoever those likely swamp this effect anyhow. And dev time is limited - how much time is it worth shaving at best 100ms off for a small and shrinking group of clients? It's cacheable, so it's a not a commonly recurring delay, and it's likely to be a lot smaller on decent networks. (https://tools.keycdn.com/ping puts the worst ping as being from tokyo at 84ms; many are sub-ms as you might expect from a cdn).

I think it's (potentially) a better tradeoff than making most clients pay for larger bundle sizes even though they don't need it.

But well: tradeoffs.


A pedantic correction: web extension and add-on authors mostly can in browsers that auto-update.


Babel has it's own set of flaws like causing a performance hit.


Nope, not everything is for everyone.


Of course it helps, only there is a bit of a lag. How many 'enterprise markets' run <IE9 nowadays?


I know of eight products, compulsory for school's to use, such as OnDemand [0], put out by the Australian government, that only run under IE7/8. (Though the published specs say it runs on IE9+ for admin, and IE10+ for students, but I've never got admin to run under anything but IE7, and students on anything more than IE8.)

I'd imagine that enterprises are still running many products with similar insane requirements, because they never get updates.

[0] http://www.vcaa.vic.edu.au/Pages/prep10/ondemand/index.aspx


Have you tried IE11 Enterprise (IE8) mode?

https://www.howtogeek.com/184634/how-to-enable-and-use-inter...


Unfortunately there are some minute differences in the way headers get passed to the server, and the user-agent string is slightly different as well.

Badly made software doesn't play ball.

Though it is theoretically possible to force it to work under IE8 mode, its simpler to supply real IE8 over a remote login.


Pharma industry, labs with XP machines doing robot automation with IE 8 installed.


But who needs to access your web app from a dedicated special purpose lab equipment control workstation?


Chrome has 85% in the above table (up from 80% from previous version), so why you are saying 100%?

Maybe the above table doesn't include beta releases of Chrome?


Chrome uses Blink (not WebKit), I beleive the parent was referring to Safari only.


It's true, I forgot to mention Chrome which no longer uses WebKit.


Ah, I'm still forgetting that Chrome is no longer WebKit.


Do any of these changes make the language objectively better? All I see are nice-to-haves that aren't really required.


I've always had a soft-spot for JavaScript, and have written a tonne of it over the years - all these "nice-to-haves" are really nice to have. I find it a lot more fun to write and, more importantly, easier to read six months later (assuming people don't try to be overly tricky with it: I'm looking at you, nested-destructed function parameters!)


Well, realistically, if you want an objectively better JS, use TS. It's completely opt-in, transpiles/compiles to JS, and you can finally maintain projects with more than 1 JS file in them, and no longer have to rage-delete the whole scripts.js file when - after adding the 66th god forsaken jQuery lib - something blows up the whole damn thing and all you're left with is a ridiculous error deep from within an unrelated library.


I think the Array.includes makes the language better as it standardizes how to check for array membership. I've encountered more than one bug as a result of the "!== -1" check not working correctly/as expected.


`Object.entries` and `Object.values` are huge wins in my book. Makes common looping operations less obtuse and obfuscated.


I like how they added (what is essentially) left pad. Hah!


I'm unreasonably happy about Async Iterators being on the roadmap. Makes it much easier to write imperative asynchronous streaming code.


I wonder does ECMAScript 2017 has optional name ES8?


Not really, but there's certainly an off-by-one joke in there somewhere.

Since ES2015 the official nomenclature is ES<year>, to convey that a new version of the standard is cut yearly. While this may result in somewhat underwhelming releases, like ES2016, at least it's much easier to reason about and target than previously. Case in point, it took ten years or so to get from ES3 to ES5, and another five-six years I believe to get to ES2015.

These were substantial releases to be sure, but for a long time the uncertainty about when a spec draft was considered done was anything but fun, and I for one applaud the new nomenclature and process for being much, much easier to reason about and target.


We must stop using names like ES8 etc. right now, otherwise there'll be a lot of confusion in 4024 about which version of ES your customers' IE supports.


Surely we'll get there in 2020 or 2021, is that ES10, ES11 or ES20, ES21?

Edit: and yes I know you were joking :)


Async iteration is already at Stage 3? Nice.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: