Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support ES6 in JS optimization (Babel? Acorn?) #6000

Closed
saschanaz opened this issue Dec 29, 2017 · 10 comments
Closed

Support ES6 in JS optimization (Babel? Acorn?) #6000

saschanaz opened this issue Dec 29, 2017 · 10 comments
Assignees

Comments

@saschanaz
Copy link
Collaborator

With Babel, we can:

@curiousdannii
Copy link
Contributor

Can also replace a lot of custom minification (including DCE) with babel-minify.

@kripken
Copy link
Member

kripken commented Dec 29, 2017

We would need to migrate the few JS optimizer passes that run on general JS, which includes JSDCE. But that shouldn't be too hard. (The great majority of JS optimizer passes only run on asm.js, so they aren't blocking us from using ES6 etc.)

How good is babel-minify? I assume we'd still need closure compiler in this case? How do those integrate?

Also, is babel the best tool in this space these days? A few years ago there were a bunch of JS ASTs and optimizers, I haven't followed this space closely for a while.

@curiousdannii
Copy link
Contributor

curiousdannii commented Dec 30, 2017

Babel has almost all the market share in transpiling/polyfilling. It shouldn't be too hard to add an emcc option to take a list of browsers, pass that to Babel, and then have it automatically transform any unsupported syntax.

Babel-minify is pretty good, but it's not that stable. But it is implemented just as a bunch of babel plugins, so that problematic ones can be easily disabled. It doesn't support asm.js. Probably it could be supported, but I haven't determined yet which plugin(s) are the problematic ones.

uglify is used way more, but IMO has toxic development practices.

If you want to output ES6, then (I think) Closure Compiler isn't an option. If you like saschanaz's idea about conditional compilation, then Babel would probably be an excellent choice.

@rongjiecomputer
Copy link
Contributor

No objection with using Babel for conditional compilation, but please make sure it is possible to disable transpiling/polyfilling/minifying. I hope Babel does not strip comments as I need some type annotations in comments for Closure Compiler.

Closure Compiler can already output ES6 code, though less optimizations are available in ES6 mode and async function is not yet supported. Commit history shows that Closure Compiler team is actively working on ES6 mode to enable more optimizations. Not sure if they are working on async function.

@saschanaz
Copy link
Collaborator Author

Closure Compiler can already output ES6 code

Its wiki says no:

You cannot use it as an output language yet; for now you need to transpile down to ES5 or ES3.

But anyway I think the purpose here is to input ES2015+, not output.

@kripken
Copy link
Member

kripken commented May 15, 2018

We should remember to look into source map support when investigating Babel (see #4224, currently our source maps break when the JS optimizer is run - hopefully with Babel there's a good way to avoid that).

@kripken kripken changed the title Use Babel Use Babel to support ES6 in JS optimization May 31, 2018
@kripken kripken changed the title Use Babel to support ES6 in JS optimization Support ES6 in JS optimization (Babel? Acorn?) Jun 29, 2018
@kripken
Copy link
Member

kripken commented Jun 29, 2018

Talking to @yurydelendik today, we had some thoughts on this topic:

  • As a high-level goal, we want emscripten to both emit something that fits well into web bundler build systems - for the library use case - but also can emit a fully optimized output by itself - for the application use case.
  • It would be nice to use DCE from Babel etc., so we don't do it ourselves, but that is somewhat at odds with the application use case of emitting a fully optimized output by ourselves. On the other hand, that's why we support closure advanced (which is especially good for the application use case, where nothing else is being built but what closure sees when called by emcc). But still, we need some amount of JS opt passes for our metadce and other specific optimizations. That's pretty minimal, though, and we probably just want to keep doing what we are, and not invest in new big things there.
  • To replace our current JS optimization which uses Uglify1, another option is Acorn (used by webpack and others). It provides an AST and is fast, and supports ES6 - so it should be possible to migrate the JS opt passes we need to there. It's also probably easy to include in emscripten (whereas I think Babel is larger and has more dependencies, but I'm not sure).

@curiousdannii
Copy link
Contributor

curiousdannii commented Jun 29, 2018

I know hardly anything about this all, but it looks like many JS projects use related but slightly different parsers. Babel for example uses its own parser, but it is based on Acorn, and it outputs its own AST format, which in turn is based on ESTree (which Acorn uses).

I don't know how much these all overlap, but I'd expect a large extent. There's probably only a few cases where the differences are relevant to Emscripten, and as most of these tools do let you change parser, I'd expect they also expose the parser to each traversal/transformation function so the differences could be handled.

If the Emscripten passes could be ported to use the Acorn/ESTree APIs, then that should give lots of flexibility for the future.

One step in preparation would be for someone to do an audit of all the current passes to write up a list and give a brief explanation. Then we could more easily see what was essential vs optional, what needs to be handled in Emscripten (METADCE) vs what could be handed off to an independent tool, etc.

@kripken
Copy link
Member

kripken commented Feb 1, 2019

PR up: #7973

kripken added a commit that referenced this issue Feb 8, 2019
…#7973)

Fixes #6000

The key change here is to rewrite the JS optimizer passes that run in a normal `-O3` etc. build from the Uglify1 AST to ESTree. With ESTree we can use modern parsers etc. so that we support ES6+ inputs to js libraries, pre-jses, EM_ASM, etc.

Aside from that rewrite, the other changes are less critical and can be altered later. Specifically, this uses acorn for parsing and terser for outputting, but we could switch to anything using ESTree very easily. Acorn is nice for parsing since it's small and standalone. For outputting I experimented with astring, which is small and nice, and escodegen, which looks very robust, but neither could output compact-enough JS to not regress our JS code sizes. This is not truly critical since for minimal code size people should use closure anyhow, however, it's nice for default builds to be small (and we don't run closure by default), and I didn't want to regress anything. Using the terser outputter achieves that. (Since it uses the Uglify2 AST internally, this means using their tool to convert ESTree to Uglify2.) They may be some minor code size changes with this PR, just because we use a different outputter now, but nothing major in either direction. Most changes seem positive actually. Sizes after closure are unchanged.

This uses almost unmodified versions of acorn and terser, but they are stripped down to what we need, and I had to make two modifications, see these PRs: [acornjs/acorn#793](acornjs/acorn#793) (quote the error on parse exceptions) and [mishoo/UglifyJS#3323](mishoo/UglifyJS#3323) (preserve quoted properties).

This may very slightly regress compile times when using those passes, as Uglify1 was just very fast. However, the change should be very small.

This does _not_ rewrite every single JS optimizer pass. In particular the asm.js passes don't need to support ES6, and so don't need to be rewritten. There are also optional passes that do not run by default, that we can convert later depending on priority.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants