Skip to content
This repository has been archived by the owner on Feb 19, 2018. It is now read-only.

GeoffreyBooth’s proposal for the future of CoffeeScript #24

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions GeoffreyBooth-proposal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Proposal for the Future of CoffeeScript

Here’s my suggestion for the way forward for CoffeeScript.

## The Problem

It’s important to define what problem(s) we’re trying to solve. In my opinion, it boils down to one: CoffeeScript is losing marketshare. It becomes harder to choose CoffeeScript for a project when fewer people use it, and when there isn’t public support for the language and a community committed to supporting it as the JavaScript ecosystem evolves. Choosing CoffeeScript for a project can also be stymied if another essential piece of the project, especially its framework, is incompatible with CoffeeScript in some way.

Many people were drawn to CoffeeScript because it offered features that JavaScript once lacked: classes, destructuring, fat-arrow functions, etc. Once ES2015 arrived and JavaScript (mostly) caught up, those people abandoned CoffeeScript back for the JavaScript they were more familiar with. Those people aren’t coming back, nor should we pursue them. With ECMAScript proposals and development proceeding at a rapid pace, we stand no chance of out-innovating the JavaScript community in inventing new language features.

Many other people, however, came to CoffeeScript for the clean, readable syntax and the many ways that the language itself helps prevent bugs, such as significant whitespace and the existential operator. CoffeeScript still has these advantages over all versions of JavaScript, and will retain them so long as ECMAScript strives for backward compatibility. But for CoffeeScript to remain a viable choice for developers, it must keep pace with the JavaScript community. At the very least it must be compatible with most popular frameworks and build tools; ideally it will also be current with the latest approved standard. The mantra of CoffeeScript is that “It’s just JavaScript”—but right now, JavaScript is ES2015.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this block, however I want it to stress more of the importance of elegant and concise code. I think a core tenant of the language is really about reducing unnecessary syntax whenever possible. Making the code structure simple and powerful is a fundamental to the language. This is something that should be a core value moving forward.


## The Goals

**ES2015 features that modern frameworks require, like modules and classes, must be supported in CoffeeScript ASAP.** We can’t expect developers to continue using CoffeeScript if they must choose between CoffeeScript and whatever hot new framework they want to use for their project.

**CoffeeScript should support as many features of ES2015+ as possible.** There is very little that ES2015 offers that CoffeeScript lacks; but whatever can be supported in a reasonable way, like `const` or `async`/`await`, should be supported. We don’t want developers to feel like choosing CoffeeScript means they’re giving up features they had in ES2015.

**CoffeeScript should output as much ES2015+ syntax as possible, *as ES2015+*.** With the advent of Babel, there’s no need for CoffeeScript to reinvent the wheel in finding ways to convert ES2015 features into ES5 code. CoffeeScript should simply output modern ES2015+ JavaScript, and let downstream tools convert and polyfill for compatibility. The advantage of this is that CoffeeScript will always remain modern—as more and more runtimes support more and more ES2015+ features natively, and Babel adjusts to let more native code through to the final output, nothing is required on CoffeeScript’s part to take advantage of the shifting landscape. Debugging will also be easier, for example if a CoffeeScript fat arrow shows up in DevTools as an ES2015 fat arrow. And the CoffeeScript codebase itself will be simpler; compiling `class` to `class`, for example, will require far less code than the complicated constructs the compiler creates now. And of course, our mantra: “It’s just JavaScript.”

**While adding ES2015+ features, we should maintain as much backward compatibility as possible.** There’s a lot of code out there already written in CoffeeScript. We would do our community a disservice by introducing unnecessary breaking changes. New features that are so important that adoption is essential, like classes, may require a breaking change; but features that are optional, like `let`, should only be implemented if we can do so in a backward-compatible way. Whatever one may think of the CoffeeScript syntax for existing features, that ship has sailed; there are millions of lines of code written in that syntax, and we owe it to our users to force as little refactoring as possible.

## The Way Forward

Here are my proposals for how to solve these problems and achieve our goals:

### Public Roadmap

The [coffeescript6 repo](https://github.com/coffeescript6) is a big step in the right direction toward remedying the issue defining CoffeeScript’s currently unclear future. When we reach a consensus, our plan should be posted on [coffeescript.org](http://coffeescript.org/) and the [README for the coffee-script repo](https://github.com/jashkenas/coffeescript).

We also should come up with a defined leadership structure and formal process for approving features and syntax. As great as @jashkenas is, a language that so many people depend on should not be subject to the whims of one man. I’m going to leave for others the specific plans for how to address the leadership question.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"one person", perhaps.


### Framework Incompatibilities: Supporting Essential ES2015 Features

CoffeeScript is hemorrhaging marketshare the longer that incompatibilities with popular frameworks and build tools go unaddressed. We must support modules and classes ASAP, and that means building them in the current compiler. In the case of classes, that means a flag to opt-in to new ES2015 class syntax and output. Any other missing ES2015 features that preclude CoffeeScript’s selection for a project must also be addressed immediately, as patches to the current compiler.

### Developer Happiness: Supporting Optional ES2015+ Features

Features that developers enjoy in ES2015 that are appropriate to implement in CoffeeScript, like `const`, should be implemented as time permits. These features should be implemented in a new compiler, assuming we build one; and possibly also in the old compiler too if such an implementation is easy and doesn’t break backward compatibility. Any feature implemented in both compilers should have identical syntax.

### Modernizing Output

Lastly, CoffeeScript’s output should be modernized as much as possible. Fat arrows should output as fat arrows, destructuring should output as destructuring, etc. But I can’t emphasize enough that this should be the **last priority**—it makes our source code cleaner, and debugging eventually easier when ES2015 features are supported natively in runtimes, but otherwise ES2015 output has little benefit for developers. That said, *new* features, especially ES2015+ ones, should definitely be output as ES2015+ code.

## A New Compiler

The current CoffeeScript 1.x compiler is extremely well commented, but it really needs those comments. Understanding it will bend your brain into knots. The original goal of [CoffeeScript Redux](https://github.com/michaelficarra/CoffeeScriptRedux) was to refactor CoffeeScript’s codebase, not to add new features.

Don’t underestimate how hard it is to write your own language compiler. If it were easy, CoffeeScript Redux would have been finished; as it stands, that project was essentially abandoned a year ago.

Also don’t underestimate how hard it is to add new features to the CoffeeScript 1.x compiler. If that were easy, someone else would’ve added modules and classes to it by now.

The CoffeeScript community suffers from too many people with a lot of passion but little time to invest in development. For that reason, I consider a new-from-scratch compiler to be off the table. We’ll just end up with another Redux.

So we have only two options for starting points for our new compiler:

* The current CoffeeScript 1.x compiler.
* Pros: already supports all existing CoffeeScript code.
* Cons: complicated, difficult-to-understand codebase.
* The CoffeeScript Redux compiler, probably from [this PR](https://github.com/michaelficarra/CoffeeScriptRedux/pull/344).
* Pros: better codebase, and the PR already supports many ES2015 features.
* Cons: we inherit Redux’s issues and unfinished work, including any incompatibilities with existing CoffeeScript code.

I don’t have a recommendation as to one or the other. I invite contributors to both projects to chime in.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. This is a pretty important question. I'd feel more comfortable accepting this as a true "proposal" once it's resolved. Eg; we can't really create a coffeescript6/coffeescript repo until we have an answer (given that the repo will likely be a fork).

But, I like that you narrowed it down to these two specific options, and feel that you've summarized their pros/cons well. As long as you feel comfortable making a final call on the choice I'll merge this for now with the understanding that you make a choice soon.

Sound good?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don’t feel qualified to make a choice between them, since I’ve only just recently started contributing to the main repo and I’ve never worked in the Redux repo. Someone like @michaelficarra or @lydell needs to chime in with some more detail, and either tell us which way to go or give us enough detail that we can decide as a community.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also think there’s a lot to be gained by us agreeing as a community to what problem we’re trying to solve and what goals we hope to achieve. That’s way more important than whatever technical implementation we take to get there. We may very well start with the “finish Redux” approach and decide after some work that it’s actually harder than updating the old compiler, and then we backtrack; but that doesn’t really matter, as long as we have consensus as to what we’re working toward in the end.


## Workflow

As to where we should put our new compiler and develop it, I have two ideas:

**Inside the current main [coffee-script repo](https://github.com/jashkenas/coffeescript).** Currently the repo is structured such that the code in `src` is compiled and output into `lib/coffee-script`. If we want to avoid merge conflicts with any pending PRs against the repo, we should leave those folders as they are.
Copy link
Contributor

@rattrayalex rattrayalex Aug 11, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, you seem to have missed the possibility of a fork of michaelficarra/CoffeeScriptRedux#344 – was that intentional?

are you uninterested in coffeescript6/coffeescript? (fine if so, just want to be explicit)

Copy link
Collaborator Author

@GeoffreyBooth GeoffreyBooth Aug 11, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better to migrate CoffeeScript Redux rather than fork it, so that we preserve its GitHub issues and pull requests. If we go the Redux route we’re basically taking on the task of finishing that project, so we might as well inherit its history.

I don’t think we should make any new repos under coffeescript6, other than perhaps for discussion. There is already an official coffeescript organization, which @jashkenas controls, so the new compiler effort should go there (or in the main repo if it’s easier to leave it under jashkenas rather than move it under coffeescript).

The thing I really want to avoid is a splintering of resources, with teams pursuing competing efforts in separate repos. Our community suffers from a shortage of developers with time to donate, so whatever coding hours we can manage to organize need to be focused into one project.


But we could add new folders, for example `source` and `lib/coffeescript`, that contain the new compiler source code and compiled output. A flag like `output: 'modern'` would cause the new compiler (i.e. the code in `lib/coffeescript`) to be used instead of the old one. Both compilers, modern and legacy, would live on in the same repo. Bugfixes and improvements could be submitted against either.
Copy link
Contributor

@rattrayalex rattrayalex Aug 11, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these particular directory suggestions sound a little odd to me; perhaps an es6 directory with src and lib/coffeescript subdirs? or simply an es6 branch, as @jashkenas has suggested.

(this is just a suggestion, I will merge regardless)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also keep in mind that @jashkenas is generally strongly opposed to flags. perhaps he'll make an exception here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want to avoid both the name es6, which is obsolete, and the notion that we’re targeting a specific version of JavaScript/ECMAScript. The output of the new compiler will be whatever the latest ECMAScript standard is. If it’s built now, it will output ES2015. When ES2016 is finalized and we add support for any new features that ES2016 adds that we decide to adopt, then the compiler will output ES2016. It will not, however, have options for outputting ES5 or ES2015 or ES2016—developers’ only choices will be the old compiler, which will basically be ES5 plus generators and modules and maybe classes; or the new compiler, which would output whatever the latest JavaScript is that Babel can take as input.

There will be an overlap period where there’s some development on both the old ES5 compiler and the new ES-latest compiler. For that reason, we can’t just keep the coffee-script repo and bump to version 2 and the new compiler is 2.x.x. We need a way to opt into it, either with a flag on the same coffee-script repo/NPM module; or a new repo/module under the coffeescript name.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comments re; es6 make a lot of sense.

For that reason, we can’t just keep the coffee-script repo and bump to version 2 and the new compiler is 2.x.x.

I'm not sure about that. Some organizations simply have a 1.x-stable branch and a 2.x-stable branch and develop both in parallel. eg; koa, django.


**In a new “coffeescript” repo, inside the [coffeescript organization](https://github.com/coffeescript).** We should claim the `coffeescript` name on NPM, and point it to a new repo at [https://github.com/coffeescript/coffeescript](https://github.com/coffeescript/coffeescript). This new repo would either be a fork of the original CoffeeScript repo or a migration of the CoffeeScript Redux repo. No opt-in flag would be necessary; by doing `npm install coffeescript` instead of `npm install coffee-script`, developers would be choosing this compiler (though we would need some way to warn them in case they intended to choose `coffee-script`).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

while I think @jashkenas would be 👍 to letting you into the repo, I imagine that the npm rigamarole might not be to his liking, fwiw.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, this is one reason we need to have a formalized leadership structure. This shouldn’t be @jashkenas’ (or my) decision to make unilaterally.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, I personally think coffeescript/coffeescript would be an ideal place for this, assuming existing maintainers are 👍 . Will probably need a strong technical plan for the language in order to make that happen.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there are a couple mentions of the repo location in this doc, might be nice to clean that up / consolidate if possible. nbd.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Totally happy to let you into the repo and npm module, and to start playing around with a flag. Squatting on npm name variants is not a great idea.


## Name

There’s no need for something fancy or new. We already have considerable recognition under the name “CoffeeScript,” so we should keep it. Let’s refer to the soon-to-be-old compiler as the Legacy CoffeeScript compiler, and the new one—well, “it’s just CoffeeScript.”

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1
Coffeescript6 is really just CoffeeScript after all, just tracking the changes to Ecmascript.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1
This is a subtle but crucial distinction. Well articulated