ModuleImport

Karolis Narkevičius karolis.n at gmail.com
Tue Jun 24 03:07:05 PDT 2014


Ron Buckton's suggestion above makes the most sense to me personally. And I
saw many people arrive to a very similar idea a few times in these recent
module threads - but it kind of always gets rejected with no substantial
reasoning.

Please don't dismiss his suggestion super quickly with "es6 already has
that" - because I don't think it does.

Specifically Ron's suggestion

1. unifies the syntax for importing a default export, a named export and
the module (which is what this thread is about)
2. makes destructuring optional, which is *very* important in my opinion.
Module consumers can choose to keep the module namespaced (i.e. when.all,
when.map) instead of importing the names into the local scope. (es6 without
the module import syntax doesn't have that)
3. considers a fairly popular and a very interesting use case of exporting
a function as the default export, but attaching named exports to it (es6
only supports that if named exports feature is bypassed). Examples of
libraries that export a function with things attached are: underscore,
when, request, moment, numeral, express, jquery. It's a pity this form of
exporting won't be naturally supported in es6.

Having said all that, David's suggestion of `import * as fs from "fs"`
helps with points 1 and 2 which is great!

My only feedback there is that I personally don't see much value in
destructuring imports, e.g. I like to be able to easily see in the
JavaScript code what module does each function belong to in each call site.
So I can see myself using the module import syntax most of the time. Making
that the same as as default import syntax as Ron suggested would therefore
be nicer.


On Sat, Jun 21, 2014 at 12:51 AM, John Barton <johnjbarton at google.com>
wrote:

>
>
>
> On Fri, Jun 20, 2014 at 4:17 PM, Ron Buckton <rbuckton at chronicles.org>
> wrote:
>
>> > From: John Barton [mailto:johnjbarton at google.com]
>> > Sent: Friday, June 20, 2014 3:48 PM
>> >
>> > ES6 already has what you want:
>> >
>> > _Named Exports_:
>> >
>> > export var foo = 1;
>> >
>> > _Single Export Object_:
>> >
>> > export var moduleName = {
>> >   foo: 1,
>> >   bar: function() {}
>> > };
>> >
>> > _Single Export Function_:
>> >
>> > export function fName() { }
>> >
>> >
>> > And even cooler, the syntax for import is uniform,
>> >
>> > import {foo} from './namedExport';
>> >
>> > import {moduleName} from './singleExportObject';
>> >
>> > import {fName} from './singleExportFunction';
>> >
>>
>> I'm not stating that I specifically "want" anything here, but was rather
>> recommending an alternative approach to the single export vs named export
>> debate and the removal of the ModuleImport production.
>
>
> Sorry, I did understand that. I was (cryptically) recommending that
> removing ModuleImport and `export default` until a later date gives us a
> good-enough solution to the cases you outline. These features can be added
> at a later very easily and since they would be based on real users asking
> for more features we could move on them quickly.
>
>
>
>> David's mail was proposing the addition of the following syntax:
>>
>> ```
>> import * as fs from "fs"
>> ```
>>
>> This is designed to work around the fact that without ModuleImport,
>> there's no simple way to get the module object for the named exports. What
>> you really want to write is:
>>
>> ```
>> import fs from "fs";
>> ```
>>
>> However, the current semantics don't allow this.  David proposed the new
>> syntax as a replacement for ModuleImport. My only issue is that for the end
>> user this could be confusing, and its possibly future-hostile for
>> refactoring.
>>
>
> So let's just remove it and export default and go. No confusion. We make
> progress. We study real feedback. We reconsider.
>
>
>>
>> If I have a library today that uses an object literal as a default export
>> in Node, and I want to migrate to ES6, the easiest approach is to just
>> replace `module.exports =` with `export default`.
>
>
> Easing migration is a great goal for the next release.  We can refine
> ModuleImport between now and then.
>
>
>> My consumers would happy use `import foo from "foo"`. If I later want to
>> move to named exports, I would break my consumers as they would have to
>> change this to `import * as foo from "foo"`.  The whole reason for this is
>> that there is a semantic distinction with how a default export is handled
>> vs. how named exports are handled.
>>
>
> Exactly. So don't allow default export. Presto, problem solved.
>
>
>>
>> If I were to use TypeScript's syntax for exports and imports, changing
>> from a default export to named exports results in no change for the
>> consumer:
>>
>> [before.ts]
>> ```
>> export = {
>>   foo: 1,
>>   bar() {}
>> }
>> ```
>>
>> [after.ts]
>> ```
>> export var foo = 1;
>> export function bar() {}
>> ```
>>
>> [consumer.ts]
>> ```
>> import before = require("before");
>> import after = require("after");
>> before.foo; // 1
>> before.bar; // function bar() {}
>> after.foo // 1
>> after.bar; // function bar() {}
>> ```
>>
>> Albeit, TypeScript does not have a Module exotic object, nor does it have
>> mutable bindings, nor an ImportList in its import clause. That said, as far
>> as the consumer is concerned there's no real distinction between the
>> "default export" approach in before.ts and the "named export" approach in
>> after.ts.  We have this distinction in ES6 because it was designed that way
>> to support mutable bindings and cyclic dependencies. I'm proposing that we
>> come up with alternative semantics that preserve that approach while
>> keeping the import syntax simple.
>>
>
> I think both export default/module import and cyclic dependency support
> are marginal features that cause as many wacky problems as the solve. They
> just don't matter one way or another.  The export default/module-import are
> easy to add later: removing them now is simple. Changing the semantics
> means redesigning modules.
>
>
>> As a module consumer, I would constantly need to be aware of whether I
>> need to use the `import * as foo from "foo"` syntax or the `import foo from
>> "foo"` syntax. Where in Node I would use `require("foo")` for both cases.
>> By changing the semantics of ImportDeclaration in ES6 and using a simpler
>> syntax, we could would save developers the cognitive cost of determining
>> which import syntax to among two very similar forms, as well as supporting
>> the ability for a module author to refactor their module from a default
>> export to named exports for the single-export-as-object case without
>> affecting their consumers.
>>
>
> Omitting export default and module-import achieves the same cognitive
> savings.
>
> jjb
>
>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140624/f44ca8a6/attachment-0001.html>


More information about the es-discuss mailing list