Add support for ES6 default imports/exports

Description

ES6 has special syntax for using "default" imports and there is currently no equivalent for CLJS when using imported ES6 code.

I'm proposing to add a :default to the ns :require.

This makes it much more convenient to use rewritten ES6 code from CLJS. If "module-name" has a default export you currently have to write mod/default everywhere since they is no easy way to alias the default.

Internally the Closure compiler (and ES6 code rewritten by babel) will rewrite default exports to a .default property, so :default really is just a convenient way to access it.

The long version that already works is

When ES6 becomes more widespread we should have convenient way to correctly refer to "default" exports.

[1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import

Environment

None

Activity

Show:
David Nolen
April 25, 2020, 3:41 PM

Addressed more generally by CLJS-3235

David Nolen
April 24, 2020, 8:30 PM

After some further discussion I understand the problem of trying to do anything automatically. So we can ignore the effort involved there. We have some prior art with ClojureScript bootstrap `foo$macros` and Foo$Bar Clojure inner class import. foo$defaultor ”foo$default” could get at the default export and let the user use that as the namespace.

Thomas Heller
April 24, 2020, 2:13 PM

I would strongly veto anything that would try to index node_modules or otherwise “detect” modules.

This is not always easily possible (eg. react-native packages containing uncompiled flow/ts/jsx code) and would limit the whole thing to something actually using node_modules. There might be cases where this doesn’t even exist (eg. yarn2 PnP).

The user should be in control of this and the compiler should NOT make any special adjustments based on the presence of certain fails with certain syntax (or lack thereof). More often than not (eg. :bundle-cmd, react-native metro) CLJS will not even be looking at these files otherwise anyways.

I’d rather see this rejected entirely than see this implemented based on any kind of magic detection. I’m still completely against allowing (:require [anything-in-node-modules-as-a-symbol :as x]) as well but I guess that ship has sailed.

 

David Nolen
April 24, 2020, 12:49 PM
Edited

I agree this is an issue, but so far not interested in the proposed solutions. I think the better way is to detect when the JavaScript module module uses export default. We could pick up this information with our node module processing code (we use a JavaScript library for this). I think this should be pretty easy to do with JS tools (i.e. like Rollup approach which is quite old now). Then once we have that information included in our Node Module index we can easily handle this in our ns form processing where we generate the sugar used by Paulus.

Paulus Esterhazy
September 17, 2018, 2:46 PM

I ran into ES6 default exports, which are common these days. Folks stumble over `default` in the code, e.g.: https://github.com/pesterhazy/cljs-spa-example/issues/13. I wanted to report my findings.

As explained in the description of this issue, you can use a combination of `:refer` and `:rename` to get rid of the references to `:default` in the code, moving it into the NS declaration. It's not the most elegant solution but gets the job done and works with global exports: https://github.com/pesterhazy/cljs-spa-example/pull/14/files

Note that AIUI because `default` is a strict keyword in ES3, you need to set the following compiler option for this to work:

```
:language-out :ecmascript5
```

Otherwise `default` gets munged to `default$`

Won't Fix

Assignee

Unassigned

Reporter

Thomas Heller

Labels