loading...

JavaScript debate : named imports VS default imports

mindsers profile image Nathanaël CHERRIER Originally published at blog.nathanaelcherrier.com on ・3 min read

JavaScript debate : named imports VS default imports

A debate on the type of import we use in JavaScript has recently appeared. Same kind of debate than the one with semicolon. It works whichever you choose but each developer has its opinion on the matter and nobody agree. I also have an opinion!

To make it short : I prefer named imports. Long answer is below though.

What is the difference between default imports and name imports?

It is a very subtil detail as it often is in this kind of debate.

import detectRotation from 'rotate'
Default import

This first example consists in trying to import the default symbol of a JavaScript module and store it in a variable that is named detectRotation.

import { detectRotation } from 'rotate'
Named import

Named imports look less simple. In fact, we are destructuring the module to only import the symbols we need in it.

Meaning, tools and clean code

If developers argue about import methods, it is because there are more than just syntax differences.

First, default imports are nameless. Or rather : it looses its name during exportation. Be it variables, constants, objects, classes, etc : they all have a name in their module. They are exported as default and it becomes their new name sort of.

So when we write :

import detectRotation from 'rotate'

we are not importing detectRotation inside of rotate module but rather we import default symbol of the rotate module that we rename detectRotation in the current module.

And this is one of the main reason why I prefer named imports. Because nothing indicates that it is thedetectRotation function that is exported as default in this module.

Whereas, when we write :

import { detectRotation } from 'rotate'

it is the detectRotation function that I import from the rotate module. If this function doesn't exist, my development tools (editor, linter, language services, etc) will let me know in a more or less direct way. Worse case scenario : my import will fail during execution in the JS engine.

Some will say that you just have to read the documentation of the module to know how to use it but I really don't want to research in the documentation each time I come back to the code, like 2 weeks after writing it.

I think code must be as clear and understandable as possible on its own and named imports are great for that.

Communities standards

In several posts about best practices, linting (fr) and other methodologies, I advise to copy what the community is already doing.

One of the goal of this advice is to simplify team work and better the maintenance of a project. There are a lot more chance that a new dev knows "standard" choice of a community instead of your personal preference...

You could translate this advice in :

Do what is best for your team, not what is best for you

So what about the "named import vs default import" debate? Same old thing here, communities have their own opinion on the matter.

For example, in Angular named imports are widely used. You can see that is the Angular doc. There are (almost) no default import or export.

import { ProductAlertsComponent } from './product-alerts.component.ts'
a Team Angular import

In the React community, default imports might be used depending on the situation. The thinking behind is a little more complex than just "we're only doing named import" or "we're only doing default import". I think this logic is really interesting so I'll detail just below.

First, the file that contains a component must have the same name as the component. This component is exported as default.

Then you can export other useful things to the files of your components. Like hooks, utils, test version of your component...Etc.

import ProductAlerts, { useProducts } from 'ProductAlerts.ts'
a Team React import

There are, of course, a few exceptions but that is the majority. Even though I prefer named imports for reasons I listed above in the post, I think this is a very logical way to do things.

Once again, each community works with its preferences and you better make it yours to ease your team working and other aspects of your dev life (code review...etc).

Posted on by:

mindsers profile

Nathanaël CHERRIER

@mindsers

Swift and JS developper. In love w/ open source. Passionate, trying to get better everyday while training my little girl to be a coder.

Discussion

pic
Editor guide
 

Great article! I agree that different situations may call for different techniques.

If I expect the functions in the module to be used often and holistically, I may use default export at the end of my file instead of defining exports on each function:

// Math.js
function add(x, y) {
// ...
}

export default {
  add,
  subtract,
  multiply
}

import Math from './Math.js';

const result = Math.add(x, y);

...and I'll name my module something generic like Math. Or in the example you showed above, Rotate instead of detectRotation.

Named exports may be more readable to some, but sometimes it may be preferable to see the function and the module in which it came from.

import { detect as detectRotation } from './Rotate.js';
detectionRotation();
// vs.
import Rotate from './Rotate.js';
Rotate.detect();
 

Thanks!

And yes, I agree that is a great way to export utils functions. 👍🏽

 

I'm starting to prefer named imports. Defaults seem to create inconsistentcy for me so I have been trying to avoid them lately.

 

Same feeling. I think a team must define some rules to be able to use default imports efficiently : what can we expect to have from a default import, etc. But the rules will change from a project to another.
Named imports allow to avoid having to defines those rules. It's easier to integrate a new dev on your team.