I've already used this for a couple of projects, and works exactly like advertised: blazing fast.
Also, it's from the guy behind Rollup, Ractive, Gobble, all tools that I use and love.
Agreed. I do love Babel, but the move from 5 -> 6 was annoying, given the number of dependencies and configuration files I now have to deal with. I understand why they did it, but Bublé is still the sweet spot for me.
> Rather than manipulating the AST, Bublé manipulates the source code directly, using the AST as a guide – so there's no costly code generation step at the end.
Is that really good idea when looking at the possibility of introducing bugs in the transpiler?
it sounds like they're still generating an AST, but replacing AST nodes directly through the code string.
It's definitely trickier but I think it's possible to do this in a clean way if the changes are just "replace this AST node with this other AST node". You know the text boundaries, and the output is context free so...
Hey Rich, I wish some time you would write more about magic-string and what makes it special. You say "no costly code generation step", but what makes codegen costly compared to what you're doing in magic-string?
I plan to write about this in the near future (in fact I'm writing slides for a talk on it this week) – essentially, codegen is more costly because a) you have to generate the entire program, rather than just modifying the nodes that have changed, b) your code generator needs to know about every single node type, and c) you have to keep track of state (e.g indentation levels).
Your goals are worthwhile. I recently built a tool not unlike yours, sharing many of the same goals vis-à-vis ease of use. Unfortunately it's currently closed source, but hopefully it'll be opened up soon and we can compare notes. There is definitely space for tooling which trade flexibility for ease of use. I wouldn't worry too much about Domenic's flame bait anyway, he has a habit of missing the point. (I mean, he did champion JS promises after all..)
"Bublé is so funny. Remember Babel started out as "Traceur output is too complex!" Over time they learned that being spec-compliant matters." — Domenic Denicola (@dominic, Editor of the @htmlstandard and @streamstandard. Works on @googlechrome.)
That seems like a biased description. Being lightweight doesn't seem to be a goal. The goal is having a very clear function with no configuration, and being simpler is just for brownie points.
Then it's worthless to say "Babel is spec compliant" when it is just compiler infrastructure and not a compiler. It can be as spec compliant (or not) as you want.
Why would it.. babel doesn't do any actual import/export modification. It doesn't have a module/bundler built in... that's what webpack, browserify and the like are for.. and no, they don't require the .js, but you can still use it.
Right, but the argument for being spec compliant is that some day you can simply stop using the transpiler and your code should not break.
So, the correct spec-compliant thing to do would be for the ES2015 preset not to touch import/export and let the bundler handle that (hopefully correct). Compiling to CommonJS, which doesn't care about `.js` or not, is the wrong choice.
I don't see any mention about async functions, are they supported? It's the single most important reason why I prefer to go with transpiling from es7 rather than es6.
Or maybe it's now part of ES2016? I get quite lost in those sliding features...
It certainly takes its time :) Well, Bublé sound cool for projects where feature stability over time is critical (like huge codebases), but I will still prefer to go with babel to select which stage I want.
EDIT : just to be clear, I won't advice any sized team to go with staged features. It works for me because I do a lot a small sized project working alone on them and I'm ok refactoring their codebase if a feature implementation change.
I didn't know it was still in progress... really hope async/await makes it in. I'm betting on that pattern to make JavaScript much more pleasant to write!
It'll probably make it into ES2017, given that Edge, Chrome and maybe FF will have it in their browsers by the end of next year, official spec or not. It's a popular feature, and with Promises and generators in place, easy enough to support.
It really does cleanup a lot of code, but getting people to understand that an Async function returns a promise isn't always the easiest thing to convey until after it's been used. I resisted Promises for a while, once it became a part of ES6, and with async/await in Babel, I started using it... the cleaner code is worth the minor bit of overhead.
Honestly, why invest time re-writing an ES2015 transpiler? Hasn't this area already been sufficiently covered by existing tools (especially since the author explicitly "limits [Buble} to ES2015")?
Because it's many times faster (~4x faster with small files, ~20x faster with large files), very easy to set up, and tiny (which has a significant impact on CI – it's very quick to install). It also generates leaner code, and doesn't rewrite the parts that don't need to be transpiled, so your style/formatting is preserved. We need to update the docs – it actually supports ES2016 (only one new language feature – the exponentiation operator) and may support JSX in future.
This look really great, thanks!
Any ideas how to connect it with JSX code? Is it possible to use it with the JSXTransform from React v0.13 or is there any other alternative (and preferably lightweight) JSX transformer that is not Babel?
There's an issue open for JSX: https://gitlab.com/Rich-Harris/buble/issues/26. The short answer is it's definitely on the TODO list, either as a separate preprocessing step that uses the same techniques (buble-jsx), or in the tool itself. Just haven't got round to it yet :)
I continue to use babel 5.x which is much easier to use than babel 6.x which cannot be globally installed. Babel 5.x supports jsx by default. Would be great if buble would have feature parity with babel 5.x to ease the switch over.
you mean transpilers like this, and Babel, in general?
You want to write ES6 code today, but your clients (= browsers) don't support it yet. So you use the transpiler: write ES6, compile to ES5, serve that.
It's the opposite of what Python did with the 2to3 tool, where you wrote Python 2, and converted it to Python 3 before running.
Why do you want to write ES6? Well, hopefully, every change ES6 introduces to ES5 is an improvement. I'd hope. So every different thing between them, you'd want to use, sort of by definition. That's the idea, at least :)
For me, the biggest changes are the syntax sugar... rest, spread, fat-arrow syntax, destructured assignment, etc. The vnext bits I'm most using are async/await, and some of the class/property extensions, and more rest/spread/destructuring extensions. A lot of the other stuff is of less interest to me in writing code, but I can see how they would appeal to others.
Really cool project. I haven't had the opportunity to use things like Buble or Babel on a project yet but would certainly like to.
I don't quite follow why plugins are discouraged in your FAQ section. I was looking at this Gulp plugin (it's very new, but looks straightforward/is idiomatic gulp): https://github.com/TrySound/gulp-buble -- I'm not following why that would be an anti-pattern.
Ah, I should clarify the readme. What that refers to is plugins that add additional functionality to Bublé, such as compiling features that aren't yet in the spec (class decorators and so on). Plugins like gulp-buble, which allow other tools to work smoothly with Bublé, are warmly encouraged!
> I'm still unsure what they offer over a simple object with property key values.
They offer a particular abstraction, that gives a certain automatic conceptual clarity for free. Personally, I'm a massive fan of prototype-based object systems, but having the class syntax sugar on top of it has made certain patterns clearer to express even if it's semantically equivalent.
My main issue with ES2015 classes, is that I've seen some projects use it for everything including things that it's really not required for; really putting the _Java_ back in Javascript, so to speak. But that can be said for a lot of language features, really.
Most of the time simple objects/collections work... separating data from utility is often cleaner and easier to reason about.
That said, when you need encapsulation and instance isolation classes provide a nice sugar around prototyping. They tend to work very well for components that have visual interactions/events that are tethered to instance/scope state. I tend to prefer the React+Redux model myself, but there are times when you need more than render-only components, and in those cases the class syntax means cleaner source code imho. These cases are also very limited imho, and about the only place I use class syntax.
There are several technical differences between classes (or functions) and simple objects. Namely - presence of "constructor", ability to have static and non-static methods and overall the fact that class can be instantiated. It is easy to reason about.
I'm sure there could be listed some additional features, but those are first things that pop into my mind.
However, I'd say one of the primary reasons for existence of classes would be familiarity. A lot of developers would have experience with classes in other languages so it is useful to have similar entity in JS.
Hey Rich, Bublé looks interesting! Ever going to move onto ES2016/17/etc features? Can't imagine myself just being satisfied with ES2015 for years to come.
ES2016 is already supported, in fact – it only adds one new language feature, the exponentiation operator. (It also adds Array.prototype.includes, but that's an environment feature rather than a language feature, i.e. it needs to be supported via a polyfill rather than a transpiler).
The idea is for Bublé to eventually become irrelevant (planned obsolescence) – but as new language features do arrive it will be fairly straightforward to add them. I'm just not sure if there'll be that many more language features after ES2017, at least of the transpilable sort – I'd be surprised if we ever have another big bang like ES2015 was.
Cool features, but they don't transpile very well (the output is much larger than the input), and require a non-trivial runtime component. Unless you're aware of the tradeoffs and have determined that the cost to your users is genuinely worth the nicer coding experience, I'd argue that it qualifies as a footgun.
I absolutely understand that the transpile is kind of weird and requires tooling... the regenerator output isn't too hard to follow, but probably the farthest from the input.
All of that said, I think it's definitely worth it, and the extra size is less of a difference for larger projects. For server-side code, the size is less of a difference since it isn't downloaded, and the performance impact has been negligible in terms of noticeable, real-world performance.
Of coure by the end of 2017 I expect most browsers to have implemented async/await natively... so by 2019 won't be an issue... that said, it's still 2016, so I'll keep using Babel.
Yes, Babel by default does nothing, but I meant, does it not have a quick route to ES 2015-to-ES5 transpilation without having to perform the standard installation and setup procedure? (I’m asking from the perspective of someone who hasn’t started using Babel yet.) Something like “install this one thing and you’re done”?
Interesting, but not sure why you'd ever use this instead of TypeScript. TS has most everything this has - including real ease-of-use compared to Babel - plus a lot of additional stuff that's critical for large code bases. And its semantics are very clearly defined.
I love TypeScript, but one thing that I find increasingly irksome is the phenomenon of TypeScript advocates who present a dismissive attitude towards workflows that don't include TypeScript.
Why would I ever use this instead of TypeScript? A totally reasonable answer to this question is that I don't want my JavaScript sources to require transpilation before they will run in a modern browser.
> I don't want my JavaScript sources to require transpilation before they will run in a modern browser.
Exactly this. Bublé is designed to become increasingly redundant as node and browsers progress, until one day you can just remove it from your stack altogether. Planned obsolescence is an underrated feature in software
Actually now that I read both definitions, neither is quite right. Perhaps a better metaphor would be dissolvable stitches – you need them when your wound is open, but once it heals the stitches vanish.
If anyone can help me out with a less gross version of the same metaphor I'd be grateful!
TypeScript was announced exactly like this - being "Future JavaScript, now" and the promise that in an ideal world it would disappear.
(It has since grown a lot and added a lot of modern features that are not guaranteed to be in JavaScript in the future, but I think the point still stands.)
ease of use is not something I'd say of TS... especially when mixing in JS.. there's what 2-3 options for how to handle your type mapping to JS libraries? I tried to use TS to create a simple ng2 app, as I wanted to understand the configuration, I looked at multiple boilerplate examples and it was all a mess imho.
Even then, I don't blame TS for most of it... but the typedef tooling really should be in the box, and have a standard construct for usage. In the end, for my example above, I used babel with some flow plugins, and it worked well enough.
Replying to myself because it is too late to edit: thinscript isn't exactly typescript, it has some extra features and doesn't attempt full js compatibility, but they are very similar.