The best example here doesn't work anymore with babel 6 https://github.com/airbnb/javascript/blob/master/README.md#10.
What is the proposed update?
Stop using default so you can keep using import the same way?
{ es6 } from './AirbnbStyleGuide';
export default es6;
Or just change your import method?
import AirbnbStyleGuide from './AirbnbStyleGuide';
export default es6;
Or something else?
Which point is causing troubles?
The only thing is that every exported variable/function should be explicitely named. But the good/best examples should work as expected I think.
https://github.com/airbnb/javascript/blob/master/README.md#10.1 works just fine if es6 is a named export - what isn't spec-compliant is destructuring inline off of a default-exported object.
Since ES6 modules don't exist yet (until the loader spec is finished) this isn't much of a concern just yet. If you run into a conflict with this in the wild, your best bet is to use two lines - one to import the default, and another to destructure it.
@tleunen In Babel 6 the problem is that you can't destructure inline from a default-export. The following example of trying to import from fileA.js to fileB.js works in babel 5 but not in babel 6.
fileA.js
export default { a : 1 }
fileB.js
import { a } from "./fileA.js"
@ljharb We are currently running into this problem because we're using the style guide with babel 6.
If the rule is to always use one export default at the end of a file like stated in https://github.com/airbnb/javascript/blob/master/README.md#10.2 then the best example from https://github.com/airbnb/javascript/blob/master/README.md#10.1 doesn't make sense....
The best bet of using two lines (one to import the default, and another to destructure it) seems a little hacky since it will add an extra line for each import at the top of every file.
Seems like there must be a better solution. Dropping the use of default as best practice in the style guide and only using named exports seems like a better option. At least the best options in 10.1 and 10.2 shouldn't clash for babel 6 like they do now (or the problem addressed at least).
Indeed. As I said, everything you import should be explicitely exported before. So yep it makes sense :)
The examples don't specify how things are exported in './AirbnbStyleGuide', so the examples are ok. Unless I'm still missing something.
Ideally, every module exports one thing - not a bag of things - so the need to destructure the default export should be minimal. If you do export default a bag of things (as opposed to the second-best choice, one thing as a default with a number of named exports, each exporting one thing), then you simply do need a second line to do the destructuring.
This seems resolved - please reopen if not.
Seems the best practices described here are actually an anti-pattern according to Axel Rauschmayer:
https://medium.com/@rauschma/note-that-default-exporting-objects-is-usually-an-anti-pattern-if-you-want-to-export-the-cf674423ac38
The better solution is to split things up into separate modules, each with only one default export.
What I'm struggling to figure out is the best way to export a small set of related functions/properties from a single es6 module, for example a log module.
// log.js
export default {
level
info,
warn,
error
};
// main.js
import log from "./log";
The above appears to satisfy Airbnb, but is an "anti-pattern" according to Axel Rauschmayer (e.g. tree-shaking).
// log.js
export {
level
info,
warn,
error
};
// main.js
import * as log from "./log";
The above seems to satisfy Axel and non-static concerns described here, but goes against Airbnb best practices #10.6 and #10.2.
So what should I do?
@billyzkid I'd either put each one in its own file all in the same directory (grouping them by directory, not by "in the same file"), or in your import in the second example, explicitly import { level, info, warn, error } from './log'.
You should export each function instead of exporting an object containing each function.
So, it sounds like using named exports (option 2) is the general consensus (thanks!) and avoiding the wildcard import if possible, although I don't really get why. Maintaining one file for each exported function seems a little extreme to me.
I would also notice that Axel's recommendation linked to above is not written as if it's an absolute thing.
... default-exporting objects is usually an anti-pattern
Emphasis on "usually". You should exercise caution in doing that, but it may still be acceptable in a few cases. Just think about the benefits he mentions would be lost, and compare that with what would be gained if you broke the rule in any particular case.
The part that I really didn't get from all this before, is why avoid the wildcard import. After thinking about it, I'd guess it's because you risk importing extra stuff added to that file afterwards, that you won't be really using.
There are only ever two reasons to use wildcard import:
If the former, toughen up and just type them out.
If the latter, seriously consider not doing that - but if you still insist on it, then that's what import * is for.
@ljharb If one should not use wildcard imports, then how would you solve:
@dolanmiu that SO question includes "But this is ugly and obscures code" which a) i don't agree with, and b) i'd say if you have three kind of "map" functions in the same file then your code is likely obscure already. The answer I'd go with (short of rearchitecting) is renaming each import to reflect more about what it does than "map".
Most helpful comment
There are only ever two reasons to use wildcard import:
If the former, toughen up and just type them out.
If the latter, seriously consider not doing that - but if you still insist on it, then that's what
import *is for.