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

FAQs: es6 roadmap, choosing an implementation, tooling #4078

Closed
SonOfLilit opened this issue Sep 3, 2015 · 40 comments
Closed

FAQs: es6 roadmap, choosing an implementation, tooling #4078

SonOfLilit opened this issue Sep 3, 2015 · 40 comments
Labels

Comments

@SonOfLilit
Copy link

I'm doing research prior to adopting Coffeescript for a young startup's codebase. After intensive googling, I found no clear answers but many people asking themselves the same questions, so it may be a good idea to amend the FAQ with answers to these:

  • What is the roadmap for ES6 support? When will features be supported? (When ES6 is standard? When it is supported? Never? Per-feature? How is it decided?) What kind of support can be expected? Will it break backwards-compatibility?
  • I understand that this implementation is considered best practice and Redux is dead code? Is this correct?
  • What is considered best practice tooling for working with Coffeescript? jslint? coffeelint? Anything else different from what you'd use with vanilla JS?

Thanks.


A discussion we had today on IRC:

<sonoflilit> Hi
<sonoflilit> I'm considering moving our young startup's codebase from js to CS, and am concerned about future ES6 support
<sonoflilit> Is there a roadmap somewhere that I'm missing?
<sonoflilit> also, is best practice to use CS or CSR?
<apanek> sonoflilit: Regarding ES6, I would say: unconclusive :) https://github.com/jashkenas/coffeescript/issues/3698
<apanek> sonoflilit: Personally, I find CS without classes a lot more comfortable to work with than plain JS in any way. I'm not sure porting all the codebase is necessary though.
<apanek> I'd go with writing new modules in CS as you see fit and porting old modules when you change them - given you want to use CS. It also makes for an easier way back if you plan to not use CS anymore.
<sonoflilit> we're still a small enough codebase that it makes sense to use js2coffee once and get done with it
<sonoflilit> but I'm afraid of the community dying
<sonoflilit> and translating back from CS to js isn't as trivial, because you get code with so many insurance clauses that it's unreadable
<apanek> I can't tell. Since I started my devops job, I didn't really do any client-side work.
<sonoflilit> so this is a one-way decision
<apanek> If you look at the issues of jashkenas/coffeescript, the discussions seem alive.
<sonoflilit> it does indeed
<sonoflilit> is tooling around CS going to remain alive?
<sonoflilit> is it even meaningful, or do you all use exactly the same tools js programmers use?
<sonoflilit> apart from `coffee`, of course
<apanek> I never used special tools.
<apanek> I don't know whether there are any :)
<sonoflilit> e.g. a linter
<apanek> There was a coffee --lint but it was removed in favour of JSHint according to the changelogs.
<apanek> The old coffee --lint command has been removed. It was useful while originally working on the compiler, but has been surpassed by JSHint. You may now use -l to pass literate files in over stdio.
<apanek> ""
<sonoflilit> so this is not best practice? http://www.coffeelint.org/
<apanek> Oh cool :)
* apanek is not up to date
<sonoflilit> gotta say, an almost empty IRC channel is quite concerning
<sonoflilit> or is it me living in the wrong side of the world?
<sonoflilit> 6:32AM in the valley, yup
<apanek> I can't tell. There's not too much going here, but people stop by every now and then to discuss things or ask questions. Most of the project communication is probably on Github.
<apanek> I'd suggest asking those questions on Github as well, you might get more up to date answers and probably also an answer from jashkenas.
@jashkenas
Copy link
Owner

  • ES6 features, just like ES5 features, and ES3 features, are supported on a case-by-case basis. Ideally, they should be added as soon as they're widely supported in shipping JavaScript implementations.
  • I don't believe that Redux ever quite reached full compatibility with CoffeeScript, but it's quite close. Both projects are pretty stable, and don't change much.
  • Ideally, you don't need any linter to work with CoffeeScript.

Cheers.

@SonOfLilit
Copy link
Author

Thanks.

If you can clarify a bit, I'll submit a PR for the FAQ page. Feel free to ignore one or more of the points if you don't have time for this.

Specifically:

  • Of course we need a linter, to catch when one of our developers uses an unconventional name, or the wrong amount of whitespace, etc'. Which is recommended by the community? (everyone, feel free to pitch in)
  • I understand that Redux is unmaintained right now? Did anyone take over?
  • A non-binding statement of intentions re: support of different ES6 features (probably as a table) will be very helpful in convincing CTOs to adopt Coffeescript. I know generators are already supported, and I see binary literals are too, but what's the latest word about...
    • ES6 classes (is there a use case for this? "Not needed, because CS classes are fine for all uses" could be a good answer if that's correct)
    • modules
    • let, const (I assume the answer would be "no, never"?)
    • an ES6 emitter for features that seem to already have syntax support, just for performance reasons (I can't see why this is needed, but an official position is useful when making the case to your CTO, or in my case, to myself as CTO): default parameters, fat arrows, etc'
    • tail-call safety, i.e. emit JS that would get tail-call optimized wherever applicable

@jashkenas
Copy link
Owner

  • If you want one, CoffeeLint is the only CoffeeScript linter that I'm aware of.
  • Your Redux question can be answered by looking at the commiters: https://github.com/michaelficarra/CoffeeScriptRedux/graphs/contributors It looks like your answer is: "no".
  • Classes: CS classes are staying the same for the moment, to preserve compatibility. We might want to switch to compile to native classes in the future, but there are problems with differences in semantics. Executable class bodies is just one example of a huge feature that might be lost. In short — not changing soon.
  • Modules don't yet exist in JS implementations, as far as I'm aware.
  • Const, never. Let, maybe someday, but there's not much (anything?) to be gained. Remember, CoffeeScript doesn't even have var.
  • Emit ES6 -- yes, once it's supported across the board. Arrow function don't exist in IE11, for example. Destructuring doesn't even exist in IE edge.
  • Tail-call optimization doesn't yet exist in shipping JS engines.

@GeoffreyBooth
Copy link
Collaborator

I’m tired of reading how CoffeeScript is obsolete now that ES2015 is here to save us. I use CoffeeScript for the syntax, not the features that ES2015 has been busy catching up to, and the day I stop using CoffeeScript will be the day it’s pried out of my cold dead curly braces.

I am worried, though, that as time goes on and more people learn ES2015, I’ll have a harder time convincing teams and bosses to use CoffeeScript. There’s currently barely a mention of ES2015 in the readme or on coffeescript.org, and too many people assume that the project is dead and will slip into obsolescence as ES2015 gets more widely adopted. At the very least, there needs to be a prominent section in the readme and at coffeescript.org explaining CoffeeScript’s relation to ES2015, especially why CoffeeScript is still relevant today and will continue to be relevant when ES2016 and ES2017 and so on arrive. What I tell skeptics is that I expect CoffeeScript to continue to mature along with JavaScript, and when new versions of JavaScript reach wide adoption CoffeeScript will simply compile down to whatever the new target is, when there is a performance or readability benefit to doing so. I tell people that they should think of CoffeeScript as primarily an alternate syntax for JavaScript, one that prevents stupid bugs through things like significant whitespace and the ? operator, and that this much-improved syntax will never get obsolete so long as ES* maintains backward compatibility.

I see defenses of CoffeeScript in this new ES2015 era that go along the lines of, well currently both ES2015 and CoffeeScript need to be transpiled down to ES5 or ES3, and that will be the case for many years, so what’s the difference? And by the time Microsoft Edge is the oldest IE we need to support, CoffeeScript will (presumably) compile down to ES2015, so there’s nothing to worry about. But this neglects two moderately large use cases where big chunks of ES2015 are usable today, without transpiling, thanks to the growing support already present in Chrome:

I don’t know what, if any, performance benefits anyone gets from letting Node 4 use native ES2015 features rather than the compiled-to-ES5 replacements, but presumably someone somewhere will claim that they must have ES2015-native code running in their Node app, or their app will suffer mightily, and therefore the app can’t be coded in CoffeeScript. Or ditto for a private Chrome-only app. And the thing is, they might be right. At the very least, it will be easier to debug such apps if the fat arrow compiles to a fat arrow, etc.

So besides updating the docs, which I feel like is the bare minimum response that ES2015 requires, we should perhaps discuss some future CoffeeScript that compiles at least some features to ES2015. Perhaps this could be a non-default feature enabled by argument, e.g. --target=es2015 say for when we’re compiling server-side code. A lot of work has been done in this pull request for CoffeeScriptRedux; maybe it can serve as a starting point? And as for updating the docs, I second @SonOfLilit and would be happy to start or contribute to a pull request explaining CoffeeScript’s post-ES2015 roadmap, if @jashkenas or another project maintainer would be so kind as to share some thoughts as to where they generally see CoffeeScript’s way forward.

@carlsmith
Copy link
Contributor

I just started work on a site generator type thing. The tool is V8 only, so thought I'd be lazy and give ES6 a go. I had about 30 lines of JS written when I switched to CoffeeScript. It was like switching from Klingon to French.

@vendethiel
Copy link
Collaborator

(as a french one, I can guarantee we still have some pretty weird rules :P)

@carlmathisen
Copy link

Looks like ES6 support might be happening, jashkenas has offered commit access to Decaf author (Decaf is CoffeeScript that transpiles to ES6).

https://github.com/juliankrispel/decaf/issues/14

@jashkenas
Copy link
Owner

Hey folks, @juliankrispel.

Julian emailed me back, but I'll respond here, so as to leave it in public. I just thought that since there's rightly a lot of interest in having CoffeeScript target ES6 instead of ES3, and Julian was actually doing something about it, and he attracted the interest of known solid contributors like @lydell and @eventualbuddha, it might have a higher chance of success getting done in a branch over here with a little more attention available to it.

That said, if anyone — new contributors or old — wants to experiment or play around in an "es6" branch, go nuts. I'd imagine you'd start behind a coffee --compile --es6 flag, and see how things shake out.

@juliankrispel
Copy link

That'd be a huge boost to the project @jashkenaz!

Thanks!

What do I do now? :)

Julian Krispel-Samsel
rainforestqa.com
goodafternoon.co

On Jan 31, 2016, at 12:13, Jeremy Ashkenas [email protected] wrote:

Hey folks, @juliankrispel.

Julian emailed me back, but I'll respond here, so as to leave it in public. I just thought that since there's rightly a lot of interest in having CoffeeScript target ES6 instead of ES3, and Julian was actually doing something about it, and he attracted the interest of known solid contributors like @lydell and @eventualbuddha, it might have a higher chance of success getting done in a branch over here with a little more attention available to it.

That said, if anyone — new contributors or old — wants to experiment or play around in an "es6" branch, go nuts. I'd imagine you'd start behind a coffee --compile --es6 flag, and see how things shake out.


Reply to this email directly or view it on GitHub.

@flying-sheep
Copy link

What do I do now? :)

hmm, i’d say:

  1. get @eventualbuddha’s expertise on board.

    decaffeinate is more mature than decaf, so i bet he’s learned some lessions that could be beneficial to know.

  2. change the lexer/grammar so that e.g. template literals are first class literals in the AST

  3. make the output configurable. current design is based on the node method Base::compile() which means: “render me to ES3”. the node classes need to be decoupled from the output format.

    dunno how to do backwards compat here though. most Base methods are coupled with the ES3 output. we need to know how much we can throw out of the node classes. ideally we remove everything that varies with output and the helpers built to do the ES3 output, and keep the node manipulating functions (e.g. to find and traverse children). finally we add a renderer optional argument to compile that handles all the compiling/rendering. the default (ES3)-renderer contains all the code currently in each node’s compileNode method.

    then it’s just a matter of adding a second renderer which can be passed to some node’s compile method and handles conversion to ES6.

@GeoffreyBooth
Copy link
Collaborator

If I could just offer one suggestion: keep in mind the destinations for this generated code. In broad terms, they are:

  1. Frameworks like Meteor and Ember that require you to use ES2015 modules.
  2. Server-side code running in Node 5+, which natively supports most of ES2015’s features.
  3. Client-side code running in Chrome-latest or other very modern browsers, which natively support many of ES2015’s features.

I suppose the easiest approach for now is to set a target of ES2015, and let Babel handle converting that down to ES5 for all three destinations. It would be nice, though, if we could somehow get ES2015 or mostly-ES2015 code for cases 2 and 3, so that the code we debug with is closer to the original CoffeeScript (i.e. with fat arrows preserved, etc.). Maybe that’s a challenge for Babel rather than CoffeeScript, assuming that Babel will need to be part of the pipeline until ES2015 support is complete in Node and in whatever browsers your app is designed to support.

At the very least we should probably call the flag --es2015 or --target=es2015 so that when ES2016 is finalized and we eventually support compiling to ES2016, it’s possible to control whether we’re compiling to ES2015 or ES2016 (and beyond). If we want to go all out, we could provide a way to set a configuration, telling the compiler exactly which features to compile in the ES2015 way and which ones to not—for example, to configure fat arrows to stay fat arrows, ES2015-style, while everything else gets converted down to ES5. Such granular configuration would mean that we wouldn’t need Babel in the pipeline for server-side code or for Chrome-only apps, as we could configure the CoffeeScript compiler to generate code that uses only the ES2015 features that Node or Chrome support while compiling down to ES5 for the rest.

@bjmiller
Copy link

I would actually prefer not to compile to ES6 syntax where we have an ES3 syntax that works as well or better. For example, there's no reason to compile to let to enforce scope where closures are being used for the same thing. The effect is identical, and probably more likely to outperform native. As another example, we shouldn't touch how functions compile at all. It works better the way CS does it.

What I'd like to focus on is only those cases where we can't compile to something usable in the three cases that @GeoffreyBooth listed above, and to cases where the ES6 equivalent really is incompatible with features included today.

At the end of this road, it should be easy to write canonical code using pretty much every currently-popular framework/environment, while being better and more fun to use than vanilla JS.

If the focus is on the differences, rather than trying to create a complete target to ES6, then I would hope that it would be less total work to do.

@flying-sheep
Copy link

no matter what route we take, in the end there should be an ES2015 (which is as close to idiomatic, hand-written JS as possible) and an ES3 output (with the same semantics as the current output)

@lydell
Copy link
Collaborator

lydell commented Jan 31, 2016

It’s easy to get carried away when thinking about what to compile CoffeeScript to (at least that’s my experience) :)

I’d say that we do things in small steps. Let’s start with the most important one: import and export. The good thing in that case is that we don’t need to think about compile targets: We can do it like we handle yield.

I also agree with @bjmiller that I see no point in compiling to let “just because,” or "a #{b} c" to a #{b} c “just because”. That’s just extra work for no gain. I suggest that we start by focusing on real problems instead. For example, somebody might want to compile class to an ES2015 class so that they can extend natives. Or compile destructuring to ES2015 destructuring so that they can work with generators.

@flying-sheep
Copy link

you’re already talking about which features the ES2015 compile target should be implemented first.

i talked about how we have to change the current code to have a second compile target at all.

if we simply say “we don’t introduce a second compile target and selectively start compiling some features to their ES2015 equivalents”, i think this will go down in flames. people will be annoyed that their mobile phone from 2008 can’t handle those features and say that it’s mission critical for their job to have for x in y to compile to for (var i=0; i<y.length; ++i) and not for (const x of y)

another way would be a babel-preset-coffeescript which compiles the ES2015 versions of our features to the old ES3 versions. then we’d have for x in y –(CS)→ for (const x of y) –(Babel)→ for (var i=0; ...)

@GeoffreyBooth
Copy link
Collaborator

As for things like compiling "a #{b} c" to a #{b} c, or => to =>, there is a reason other than “just because”—the closer the JavaScript output is to the original CoffeeScript, the easier the JavaScript is to debug. And presumably some JavaScript engines will parse => and similar things faster than their ES3 equivalents, so there might be a performance gain e.g. for Node 5 to use the ES2015 syntax. I agree that features with perfectly usable ES3/ES5 equivalents should be last on our list of priorities, but I think such features should at least be on the to-do list.

@juliankrispel
Copy link

Actually I'd just like to talk about putting decaf into coffeescript first.

For any who don't know:
Decaf isn't a fork of coffeescript. It's simply a program that takes the coffeescript syntax tree compiled by the coffeescript parser and converts it to an esprima-based syntax tree built with ast-types to ensure we're outputting valid js. Decaf has no knowledge of coffeescript internals and coffeescript doesn't have to know about decaf internals to use it for es6 compilation.

This decoupled relationship is possible because coffeescript, like any great modular program, exposes functionality that can be used outside of itself (lexer, parser and compiler).

Modularity is a good thing for so many reasons that I'm not going to elaborate on right now but for that reason I'd prefer decaf to maintain a separate repo, possibly inside a 'coffeescript' github organisation.

Anybody with me here? @jashkenas would be great to get an answer from you on that.

@lydell
Copy link
Collaborator

lydell commented Feb 1, 2016

Oh, I didn't realize that was your approach @juliankrispel! Awesome! Now all I can say is: Continue on that path! 👍

@flying-sheep
Copy link

@juliankrispel sure, and this fits well with my idea here:

decaf would be an alternative renderer to the default one, and the default one would be included in CS. and to use decaf, you’d do:

import decaf from 'decafjs'
import {parse} from 'coffee-script'

const es3    = parse('a -> b').convert()
const es2015 = parse('a -> b').convert(decaf)

@juliankrispel
Copy link

@flying-sheep I'm 100% with you on that one. I've started to implement this, will be sharing it soon :)

@michaelficarra
Copy link
Collaborator

@juliankrispel If you would like to move the juliankrispel/decaf repo to the coffeescript organisation, I can help you with that. We should have moved this repo (jashkenas/coffeescript) there long ago.

@backspaces
Copy link

As folks may know, Modules have two parts: the ECMA import/export es6 syntax/semantics, and the WHATWG browser module loading. This has created a mess in the current es6 world with webpack, browserify, common vs amd, bundling, and way, way more. It makes it a bit hard to use our modules, and babel can only do half the job because of the ECMA/WHATWG split.

There are two ways to minimize the hassle for using/testing Modules ourselves:

@GeoffreyBooth
Copy link
Collaborator

Hi @backspaces, I think your comment points to a big design decision that needs to be made: when CoffeeScript supports ES2015 modules, is that support limited to simply outputting ES2015 JavaScript (and then Babel or <script type="module"> or something else in the build chain would be responsible for actually doing the importing and exporting) or will CoffeeScript support not just some equivalent module syntax but also resolving all the modules to output ES3 JavaScript?

I was assuming with my --target=es2015 suggestion that CoffeeScript would simply output ES2015-compliant JavaScript, and that’s where CoffeeScript’s responsibility would end. Babel and other tools already do a good job of taking ES2015 JavaScript and transpiling it down to ES5 or ES3, and I don’t see why CoffeeScript needs to duplicate all that effort. If CoffeeScript “is just JavaScript” and ES2015 is JavaScript now, we should be able to just output ES2015 and leave it at that (at least when we’re in --target=es2015 or later mode).

Though without --target=es2015, modules wouldn’t be supported; so there would have to be a big warning in the docs that if people want to use modules, they need to pass this flag. The more ambitious approach, which I think your comment is suggesting, is that modules would be supported whether CoffeeScript is outputting either ES2015 or ES3, in which case the --target=es2015 flag would be unnecessary (at least for module support, leaving aside the cases when you might really want ES2015 code as your final output). I suppose if we want to go this far, we could include Babel as a dependency; CoffeeScript would always output ES2015, and unless --target=es2015 was set, CoffeeScript would pass its output onward to Babel to generate the final ES3 or ES5.

@backspaces
Copy link

Sorry to be late.

Yes: modules are somewhat independent of the JS version in that
import/export are defined in es6 but module loading is defined by the DOM
spec .. whatwg in this case.

So I see no harm in allowing JS5 or JS3 code using the DOM loading spec,
which is mainly about System.js or similar.

I ran a simple experiment for the simplest possible use of System.js, see a
rough talk here:
http://backspaces.net/temp/Modules.pdf
I ran babel 6's fine-grain transpiler only for module transpilation
(Canary supports > 90% es6), then used System.js.

I believe it is possible to have System.js do this for you w/o any
transpilation, at least the github page sez so. I'd ask Guy Bedford.

Even this will go away as soon as <script type="module" ...> is completed
which should be relatively soon for modern browsers.

-- Owen

On Fri, Feb 5, 2016 at 11:24 PM, Geoffrey Booth [email protected]
wrote:

Hi @backspaces https://github.com/backspaces, I think your comment
points to a big design decision that needs to be made: when CoffeeScript
supports ES2015 modules, is that support limited to simply outputting
ES2015 JavaScript (and then Babel or <script type="module"> or something
else in the build chain would be responsible for actually doing the
importing and exporting) or will CoffeeScript support not just some
equivalent module syntax but also resolving all the modules to output
ES3 JavaScript?

I was assuming with my --target=es2015 suggestion that CoffeeScript would
simply output ES2015-compliant JavaScript, and that’s where CoffeeScript’s
responsibility would end. Babel and other tools already do a good job of
taking ES2015 JavaScript and transpiling it down to ES5 or ES3, and I don’t
see why CoffeeScript needs to duplicate all that effort. If CoffeeScript
“is just JavaScript” and ES2015 is JavaScript now, we should be able to
just output ES2015 and leave it at that (at least when we’re in
--target=es2015 or later mode).

Though without --target=es2015, modules wouldn’t be supported; so there
would have to be a big warning in the docs that if people want to use
modules, they need to pass this flag. The more ambitious approach, which I
think your comment is suggesting, is that modules would be supported
whether CoffeeScript is outputting either ES2015 or ES3, in which case
the --target=es2015 flag would be unnecessary (at least for module
support, leaving aside the cases when you might really want ES2015 code as
your final output). I suppose if we want to go this far, we could include
Babel as a dependency; CoffeeScript would always output ES2015, and unless
--target=es2015 was set, CoffeeScript would pass its output onward to
Babel to generate the final ES3 or ES5.


Reply to this email directly or view it on GitHub
#4078 (comment)
.

@coderofsalvation
Copy link

@GeoffreyBooth agreed. I would just leave coffeescript simply as an producer of (a) javascript (version). So why not just decouple the ES3 output and module-loaders into a separate modules?
That way the size of an coffeescript environment is kept to a minimum, and allows people to extend coffeescript using modules (instead of forking coffeescript).

$ npm install coffee-script
$ npm install coffee-script-es3
$ npm install coffee-script-es2015              
$ npm install coffee-script-es7              
$ npm install coffee-script-systemjs            # hasslefree cross-moduleversion loading

Not sure if the modularity/size-topic has been touched yet, but how about versioning the 'coffee-script' package which depends on the current lowest denominator (es3? es2015?)

I’m tired of reading how CoffeeScript is obsolete now that ES2015 is here to save us

Same will happen with ES6/ES7/ESwhatever. It's about time @jashkenas is going to publish a manifesto article to tell people on how coffeescript does not focus on compatibility with any idea out there.
The fact that @jashkenas is still replying here shows he doesn't want to step down as an maintainer.
Therefore, I sincerely believe @jashkenas wants the best for coffeescript.
However, (and this is some healthy critique):

  • stability of a project can easily be confused with stagnation to the public.
  • a passive maintainer can be confused with a passive aggressive maintainer

Without an manifesto, people are more likely to not adopt coffeescript because it seems nothing more than just a little language (README.md).

@GeoffreyBooth
Copy link
Collaborator

I think splitting out CoffeeScript into multiple npm packages will be a nightmare to manage. The same can be achieved by passing options to the CoffeeScript compiler. There's already a bunch of options defined, we would just be adding more (one more, if my suggestion is adopted: target: es2015 or --target=es2015 on the command line).

There seems to be a lot of confusion about whether CoffeeScript module support means that CoffeeScript is resolving all the modules itself the way Babel does, and still outputting ES5; or if the intent is for CoffeeScript to simply output ES2015-standard import and export statements. I favor the latter: server-side code processed by Node can parse such statements now, and someday soon browsers will be able to as well. For CoffeeScript code intended for browsers, this ES2015 output could be further compiled by Babel to generate ES5. Having CoffeeScript optionally output ES2015 also provides a good pattern for how CoffeeScript can produce less-obfuscated JavaScript in the future, for example by outputting fat arrows for fat arrows. The target concept provides a framework for CoffeeScript to grow and adopt new must-have ES20xx features in the future. There will always be some tool like Babel to compile down ES20xx into ES5, so there’s no need for CoffeeScript to reinvent that wheel.

Some discussion of CoffeeScript's future, posted prominently on coffeescript.org, is long overdue. I feel like “manifesto” might be a bit strong, but the website should have some statement acknowledging ES2015 and JavaScript’s continued development and CoffeeScript’s place alongside it.

@coderofsalvation
Copy link

I guess a good question might be: till which degree is coffeescript a serverside runtime (RT) and/or a code generation tool (CG). Personally my RT/CG ratio is 70/30.

multiple npm packages will be a nightmare to manage

Could you elaborate on that? Because I agree with you from the point of one maintainer, but not from the point of an opensource community.
I definately like the commandline flag approach, but supporting various outputs along the way will turn coffeescript in a monolythic multiversion nightmare imho (=RT overhead).
For multi-output javascript (CG) I don't see any problem to get the commandline flag to work based on optional installed modules.
If you want to go the monolythic road, why not version coffeescript (1.1 being ES3, 1.2 being ES2015) ?
In that case it would make sense from a RT point of view imho.

@GeoffreyBooth
Copy link
Collaborator

@coderofsalvation, I think multiple NPM packages will be an issue for frameworks and plugins that incorporate CoffeeScript downstream. Think of Meteor and its coffeescript package, that it uses to compile CoffeeScript as part of its build process, or ember-cli-coffeescript. Also think about Gulp and Grunt and all such build tools, and things like the Coffeeify plugin for Browserify—they all include coffee-script as a dependency. It adds a burden to all these tools if suddenly they need to let the developer specify coffee-script-es2015 or coffee-script at a particular version number. Many of these tools are stagnant or abandoned, so we don’t want to force them to update in order for developers to use the latest CoffeeScript. All that said, though, I’m not opposed to separate NPM packages if we have a strong reason for it—for example, if the core package has a breaking change that affects all these downstream tools. Outputting ES2015 by default, for example, would be such a change. But let’s try to avoid such issues, hopefully?

Is this where we’re going to discuss the plans for how CoffeeScript should support modules? Perhaps that discussion should get its own room somewhere? #3162 seems a bit full. @michaelficarra and @backspaces, I welcome suggestions. @juliankrispel, I’d love to hear how Decaf fits into modules and ES2015 (perhaps in a new room as well).

To hopefully start to wrap up the broader “how to handle ES2015” discussion, though, here’s my proposal:

  1. We keep CoffeeScript in just one coffee-script NPM package, and don’t introduce breaking changes except behind flags. We should move the repo to the coffeescript organization.
  2. Once we have a new module syntax published, presumably using the currently-reserved import and export keywords, if CoffeeScript code uses those keywords the CoffeeScript compiler would output import and export lines as ES2015 but other code would remain the current ES5. In other words, developers could “opt in” to ES2015 modules by writing import or export, without needing a flag; but nothing else in the output would change.
  3. If we want to build Babel-like module resolving support, where we don’t just output a line with an import keyword but we actually go and put the module code there like Babel does, this would be enabled by a flag like --resolve-modules. This will never be the default behavior, if we bother building it at all, as pretty soon native support will be widespread.
  4. We add a new flag target, which tells CoffeeScript what the desired output version is: --target es5 (the default), --target es2015, or eventually --target es2016 and so on. For --target es2015 mode, we would make an effort to output JavaScript that is as similar to its CoffeeScript source as ES2015 allows: fat arrows remain fat arrows, destructuring is unchanged, etc. Classes would follow the ES2015 syntax. This would mean breaking changes for CoffeeScript written under the target: es2015 flag, in that the generated JavaScript wouldn’t behave exactly the same as before (significantly so in the case of classes) but this is necessary if we want to preserve CoffeeScript as “just JavaScript.”

@samuelhorwitz
Copy link

samuelhorwitz commented May 17, 2016

I don't like the idea of Coffeescript being multiple packages or becoming yet another transpiler. In my opinion, the best possible route (aka what I wish existed today) was CoffeeScript 2.0, a breaking version that targets ES6 and relies on proper build chains or browser support. Meanwhile, CoffeeScript 1.x can remain stable and occasionally updated as needed as the ES3/compat version.

Modern tooling is already enough of a mess. CoffeeScript should continue to be a very straightforward tool. You use CoffeeScript 2.0 if you are looking towards the future and let current build systems sort out the resulting JS dreaming of the day when you don't actually need Babel or Traceur or whatever because browser support finally arrives. You use CoffeeScript 1.x if you don't want to deal with that mess and just target ES3 with the limitations that brings.

CS2 would (in my opinion) output ES6 code whenever possible vs CS1 shims. Classes would also now compile to ES6 classes and not CS classes (breaking change, but major version increment).

99% of the stuff would stay the same and people who wanted could spend some time porting what needs to be ported if they feel like the upgrade benefits their project.

As the years go by and more breaking features require implementation, you just release new major versions. No one has to use them and the old ones will exist forever.

@anodynos
Copy link

anodynos commented Jul 7, 2016

I totally agree with @samuelhorwitz - we need a new, shiny, breaking, ES6-only version 2 of the beloved Coffeescript.

Or maybe version 3, since coffeescript 2 just makes people weep or laugh... And since we're climbing versions, I would actually really suggest to go bold and let VERSION = 'coffee-script@6';})

The Brave New World

CoffeScript Version 6, should have initially these 3 main Goals :

  • A) Aim to support all the ES6 (& ES7) features. let and const included. Cause we, the community, require("let there = 'be ES6 and beyond uniformity'"). No broken promises, proxies, or let downs.
  • B) Target only to a native ES6 compilation. No ES3/ES5 shims, even if they are trivial. And of course limited & breaking compatibility with [email protected].
  • C) Finally let and mandate that the ES6 runtime (eg transpile to ES5 or ES3) is someone else's problem. The tools are there, they work great, let people use them! I am sure it's as trivial in gulp & grunt & webpack etc to compile throught in multiple steps (as it is in http://urequire.org who's I am the author :). This is already the case for generator functions.

The Bad News

Unfortunately, the word in town as of mid-2016 is assert coffeescript is dead. And it pretty much is, no doubt about it:

image

And talking about about coffeescript 2 / redux, makes old coffeescript enthousiasts like me wanna weep.
image

From CTOs, to senior developers and juniors, they all think aloud the same:

   Yeah sure, CoffeeScript gave many good ideas to ES6, yeah it looks pretty neat, 
   yeah less typing and shit, but you know, we need ES6 for so many X and Y and Z reasons.

And I can't blame them. I can't really convince anyone to pick coffeescript, not even myself. Unfortunately, I use it only for small non-persistent experiments these days... and I really miss it. Cause at work, like many people reading this, I have to deal with the ugliness of

    ]});
  });
});

I would absolutely adore to be able to use ALL of the ES6 features that are available now or in the future (transpiler or native), but using the beloved syntax.

I strongly believe its the only way forwards, to keep coffeescript alive, relevant & thriving!

PS: Maybe @jashkenas, or someone else nominated, should start & lead a Kickstarter / IndyGoGo / etc campaign to fund really well the project, and work on it full time. I 'm sure the project will attract loads of support, 10x or 100x more that what redux did.

Best regards.

@carlsmith
Copy link
Contributor

Yeah, that's all true, but we're really just talking about creating a new language based on CoffeeScript. That's been done loads of times. If you want to take another run at it, great, but to be honest, just explaining how you think someone else should proceed isn't that helpful. You make a lot of intelligent points, but if anyone was up for creating a new CoffeeScript based language with ES6 features, they would've already done it. It's fairly easy to write a parser, and the language design, the JS code generators with source mapping, the users, the libraries and the docs already exist for the most part. We only need a working prototype on GitHub, and people can start contributing...

@anodynos
Copy link

anodynos commented Jul 8, 2016

That's what I am calling for :-)

Sure, the technical capacity exists, but my point is to give this idea some momentum and make it a cause!

I dream of motivating the community, to collectivelly make a kickstarter or something and get this baby going.

Of course the best that can call for this cause (not necessarily implement it all) is @jashkenas and other main contributors like @michaelficarra and others.

@rattrayalex
Copy link

@samuelhorwitz @anodynos @carlsmith Let's make this happen.

I've created a "CoffeeScript6" org on github with a "discuss" repo: https://github.com/coffeescript6/discuss

I propose we move the conversation to issues & PR's there and start sketching out how this can work.

@carlmathisen
Copy link

@juliankrispel has come far with https://github.com/rainforestapp/decaf. Same goes for @eventualbuddha's https://github.com/decaffeinate/decaffeinate

@anodynos
Copy link

anodynos commented Jul 8, 2016

Thanks @carlmathisen - both decaf & decaffeinate are very useful to start with.

Lets ignore they both make mistakes, they are both at infancy i.e in decaffeinate, this valid coffeescript :

class Animal extends Lifeform  
  #varLocalToClass = 1            # fails to transpile 
  aPrototypeProperty: 'value'    # wrong intepretation
  instanceMethod: (arg1, @storeInThis, splat...) -> 'returnValue' # OK

becomes

class Animal extends Lifeform {  
  //varLocalToClass = 1              // fails to transpile with 
            // "expected a colon between the key and expression of a class property"
  aPrototypeProperty = 'value';   // wrong intepretation, 
           // Its not a local variable but a prototype property. 
           // Also it isn't actually valid ES6, local variables inside a class aren't allowed. 
  instanceMethod(arg1, storeInThis, ...splat) { this.storeInThis = storeInThis; return 'returnValue'; } // OK
}

If I am not wrong, both don't aim to become transpilers of all existing of CoffeeScript@1 for production ES6 code, but instead as a tool to one-off migrate from coffeescript -> ES6, with some (or a lot of) manual intervention.

We actually aim to keep people using CoffeeScript! And plain existing CoffeeScript should transpile OK to ES6 97% of the time, using the new shiny CoffeeScript6 transpiler.

But enough with the existing coffeescript. The most important objective for us now should be to create the new language, namely CoffeeScript@6, a new near-superset of CoffeeScript@1, but with enabling all the nice ES6 features and not caring anymore about targeting ES3!.

The last part is partially done by /decaf.*/. Creating a new coffeescript@6, we have a long way to go!

@dux
Copy link

dux commented Jul 20, 2016

I would like to see Coffee ES6 happen. As I see it, once you go Coffee it is hard to go back. Similar to HAML, once you start to code in HAML, HTML looks soo ugly and bloated, you will never choose it unless you have to.

Of all developers I learned/forced to use HAML or Coffee, all use HAML today for server side rendering and all that must to use JS syntax in bigger teams, usually do it with sadness in their eyes.

If new Coffee parser happens, I it is possible that it could catch old steam and became popular again.

@hoIIer
Copy link

hoIIer commented Aug 11, 2016

+1 can we pleaseee make this happen! as @dux said once you go Coffee it is hard to go back

@Tatsh
Copy link

Tatsh commented Aug 27, 2016

And the point of let and const in generated output is? Right now we do not have to type var and this is considered good. Scope automatically set. I do not want to type let or const either as I find it unnecessary stuff that JS has that provide very little benefit (other scripting languages rarely have these kinds of things for variables). I sort of thought maybe it would be decent to optimise let into things like loops and if statements, but this would also mean lame things like:

x = undefined # set here so `let` does not occur in the loop
for y in z
  x = y if someCondition()
  break

It also is more work to try and find these optimisations.

Right now the first line is not required as var declarations are never made inside of control structures.

The only thing I want to see is maybe generated ESwhatever classes for native extension. I would support having a separate keyword for exactly that. The way 'classes' are built in a traditional manner now works fine for everyone.

We are missing a few keywords, but this breaks compatibility, so I see a need for command line flags (or first/last comment in the file that specifies that flags like a modeline). Other than that, what are we really missing? Maybe I am a little old school, but I am just not seeing how compiling to ES* as much as possible is going to provide any benefit, especially in the browser world. And if you have to transpile with Babel, what is the point? We already have valid ES3 code and some new features like generators (without silly function *... declaration).

@carlsmith
Copy link
Contributor

carlsmith commented Aug 27, 2016

When CoffeeScript was created, we wrote cross-browser programs, so it made sense for the language to compile to cross-browser JavaScript. Today, JavaScript is used more widely, and often in projects that only need support for the latest version of V8 or some other modern engine, so it makes sense to compile to ES6, and use tools like Babel to support older browsers. That just fits into what everybody does these days, and it separates concerns.

The existing compiler compiles ES6 features to ES6, so for example, you need Babel to use CoffeeScript generators on older browsers already. The direction seems to have naturally shifted implicitly towards a compiler that only outputs ES6, that uses Babel to convert it to ES5 or ES3 if you need to.

CoffeeScript classes are not fully compatible with ES6 classes, so we no longer have complete interop with JavaScript libraries. Fixing that will break a lot of existing CoffeeScript code.

CoffeeScript may slowly evolve to emit modern JS, with compiler flags for breaking changes like classes, or someone may write a new ES6 focussed compiler from scratch, and drop backwards compatibility entirely, but something has to happen, as always compiling CoffeeScript directly to ES3 has become a bad idea.

@backspaces
Copy link

backspaces commented Aug 27, 2016 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests