coffeescript6 / discuss

A place to discuss the future of CoffeeScript
162 stars 4 forks source link

CS2 Discussion: Features: import/export #7

Closed dadleyy closed 8 years ago

dadleyy commented 8 years ago

With the adoption of es6 by many, many, many popular javascript frameworks and libraries, supporting import/export has become very relevant to the adoption of coffescript in the codebases that use those frameworks. This issue has been brought up several times in the original coffeescript repository - see also #3162.

At the time of writing this, the import and export keywords are treated by the coffescript lexer as reserved words and throws a compile-time error when encountered.

original comment

carlmathisen commented 8 years ago

IMO, module syntax should be the import statement from ES6.

I totally agree that some of the features in import might feel a little dirty, but I don't think it's a good idea to skip such an important feature such as how you require code files. The define/require approach you outlined can in any case always be supported with a library required in rumtime.

By dropping the import statement, we are in the same pickle the original CoffeeScript is, where people feel like they can't use CS because it is lacking features ES6 has.

It made sense that CoffeeScript had its own class implementation or could have its own module implementation in the old days of ES5, because back then every library or toolset had to cater for themselves anyway. Currently, with ES6, a lot of these features are being consolidated, and it makes sense to support it.

rattrayalex commented 8 years ago

Welcome @dadleyy and @carlmathisen ! Very happy to have both of you here.

@dadleyy raises some interesting points and does so in a well-reasoned way. If nothing else, I certainly agree with this:

I think in order to move forward with the import/export we should first draw up a list of benefits we achieve by implementing that format over the require + destructure.

I also agree with this:

people feel like they can't use CS because it is lacking features ES6 has.

and expect to use it as a fall-back argument for other such features in the future. Given this effort is likely to result in a major-version-bump at the very least, folks uninterested in the new features are always welcome to use CS v1.

rattrayalex commented 8 years ago

I hope to respond with more depth later, but off the top of my head, the chief advantages of import/export include:

Considering a better alternative to import React, * as ReactStuff from 'react' might be worthwhile, though it doesn't bother me too much personally.

Thoughts?

rattrayalex commented 8 years ago

I would also like to throw out an additional proposal:

from 'react' import React

The primary motivation is situations when you have a long list of member imports, having the "from" at the end is a little weird:

import {
  MemberOne,
  MemberTwo,
  MemberThree,
} from 'my-module';

could instead be:

from 'my-module' import 
  MemberOne
  MemberTwo
  MemberThree

though we'd need to think about what to do when you import React, { PropTypes } from 'react' if going without {}.

I'm not convinced this proposal would be worth the departure from ES6 but wanted to share it. Thoughts?

GeoffreyBooth commented 8 years ago

Full ES2015 module support is, in my mind, the top-priority most-pressing issue facing CoffeeScript today, and the No. 1 reason that people are abandoning it in favor of ES6. I’ve written documentation explaining how to use CommonJS require to work with modules in CoffeeScript in Meteor, but I recognize that at best it is a workaround. You can see in some of the issues in the Meteor repo places where require is no substitute for import, even though at present that’s what require is compiled into.

I consider module support to be so urgent that I think it should be built into the current CoffeeScript 1.x, not put off until whenever this new project gets off the ground. The consensus from the various issues in the main repo is that we want to essentially support ES2015 syntax as is, seeing as it’s so coffee-like already; and we would output import and export statements, leaving the conversion to CommonJS for other tools like Babel further down the chain. Adding this support would not be a breaking change, since import, export and default are reserved words in CoffeeScript already; the only caveat would be a warning in the docs that it would be the developer’s responsibility to pass CoffeeScript’s output through Babel if the developer was using modules.

Someone made a slapdash attempt at implementation in this pull request; I’ve continued a conversation on that thread to try to scope out what a proper implementation would be. I haven’t had much time to work on it, but I’m hoping to get at least a rough draft up on GitHub for others to poke holes in and gradually get polished, and get merged into CoffeeScript 1.x. I wholeheartedly support the idea of CoffeeScript6 and revamping the language for ES2015+ more broadly, but I think module support is so important and so urgently needed that we should make the effort to implement it now in the CoffeeScript we have, even if it means reimplementing it in a new architecture later.

rattrayalex commented 8 years ago

I agree 100% with @GeoffreyBooth .

While I'd love to see from ... import as described above, my guess is that'd have too much friction relative to the minor benefit.

@GeoffreyBooth I hope you share your forthcoming PR here at an early stage so that members of this community can contribute. Personally I'd love to take part.

GeoffreyBooth commented 8 years ago

I’ve been working here. It’s in the very, very early stages: I have failing tests, and I can handle import 'module-name', but that’s it. Struggling to figure out how to parse import foo from 'lib' within grammar.coffee. Any and all help most appreciated! I’m happy to add contributors to this repo, or we can move the work to somewhere else if there’s someplace more appropriate.

JimPanic commented 8 years ago

This is awesome, @GeoffreyBooth and I can only second what @rattrayalex said. I'll have a look at it as well sometime this week.

Side note: with working on this PR, we're basically agreeing to do initial work on the original coffeescript codebase and not redux or decaf. Is that correct?

GeoffreyBooth commented 8 years ago

@JimPanic yes, that’s what I meant about potentially reimplementing this later. I have a hunch that the Redux codebase would likely make a better starting point for the CS6 effort (this is a topic for an entirely separate thread, so let’s please not get into it here) so this PR will likely be the last major new feature in CoffeeScript 1.x, and we’ll have to redo it in CS6. But I think the potential duplication of effort is worth it, to stanch the bleeding of developers abandoning CoffeeScript in the meantime until CS6 can get anywhere close to beta.

JimPanic commented 8 years ago

Understood and I agree. :+1:

JimPanic commented 8 years ago

@GeoffreyBooth Oh man, this is kind of a mess. I have the same problem as you: I don't understand how those three files play together. Maybe this is also what the redux codebase was trying to fix. :)

I'll continue to try to wrap my head around how all this works…

JimPanic commented 8 years ago

I managed to get the first two test cases working:

The rest and especially the next one (import { foo } from 'module-name') are not yet working. I'll push if I find some time this evening or tomorrow during the day.

JimPanic commented 8 years ago

See https://github.com/GeoffreyBooth/coffeescript/pull/2/files

mrmowgli commented 8 years ago

I would also like to mention that currently Coffeescript/CommonJS and ES6 handle namespaces differently. There needs to be a common way of making sure that both require environments co-exist correctly.

In addition to that, and something I've run into a lot with CommonJS loading, is how to handle circular references with require statements. See this issue in Meteor for a good breakdown of this problem: https://github.com/meteor/meteor/issues/6381

GeoffreyBooth commented 8 years ago

@mrmowgli, the plan at least for the PR I'm working on is for CoffeeScript to leave the module handling to downstream tools, just as it does now with require. So just as:

_ = require 'lodash'

gets output as

var _;
_ = require('lodash');

An import statement like:

import _ from 'lodash'

would get output as

import _ from 'lodash';

In other words, just as CoffeeScript relies on other tools to process the require statements and wire the modules together today, CoffeeScript would still rely on other tools to process import and export statements. I don’t see the need to add module resolving to CoffeeScript’s scope.

dadleyy commented 8 years ago

Just updated my original comment on this issue. I'd say its pretty clear we're going to have import and export and I'm very much okay with that.

GeoffreyBooth commented 8 years ago

Now that https://github.com/jashkenas/coffeescript/commit/7667cb2370c1ebd1f61061d71b117be5ede78ecb has happened, I think we can cross this one off the list. One down!

carlmathisen commented 8 years ago

Thank you all for your hard work on getting import/export support into CoffeeScript!

coffeescriptbot commented 6 years ago

This issue was moved to jashkenas/coffeescript#4905