Avoid using default exports (2024)

Phuoc Nguyen

Posted on • Originally published at phuoc.ng

Avoid using default exports (3) Avoid using default exports (4) Avoid using default exports (5) Avoid using default exports (6) Avoid using default exports (7)

#webdev #javascript #typescript

As you may already know, there are two different ways to share functions in JavaScript: default exports and named exports. Default exports are used to export a single value from a module, while named exports allow you to export multiple values from a module.

Default exports are great when you want to export something specific from a module, like a function or a class. Named exports, on the other hand, are perfect for when you want to export multiple things from a module at once.

In this post, we'll explore why using default exports isn't recommended and should be avoided. To get started, let's take a look at some examples of both.

Named exports

An example of a named export is as follows:

// add.tsexport const add = (a, b) => a + b;

In this example, we've exported a function called add from the add.ts module. You can easily import this function into another module using its name:

// app.tsimport { add } from './add';console.log(add(2, 3)); // 5

Default exports

Let's rewrite the example above with using a default export :

// add.tsconst add = (a, b) => a + b;export default add;

In this example, we have exported the add function as the default export. This function can then be imported in another module using any name of our choice.

// app.tsimport add from './add';console.log(add(2, 3)); // 5

Now that you have a good understanding of named and default exports, let's dive into the next section to explore the disadvantages of using default exports.

Poor discovery

Default exports can be confusing in complex modules. Developers may not know which export is the default or even be aware of its existence. This can cause delays as engineers must spend more time looking at documentation or even the source code to find the functions they need.

On the other hand, using named exports makes discovery much simpler. With named exports, developers can easily see the exported members of a module and their corresponding names. This is especially helpful when using an IDE, as popular IDEs allow you to use a shortcut (such as cmd + space) to suggest available functions from a given file. Unfortunately, this shortcut doesn't work when using default exports.

Refactoring

If you decide to rename a named export in a module, for example, changing the name of the add function to sum, most IDEs can automatically update all usages. This makes the refactoring process much easier.

However, with default exports, this isn't possible.

Auto-complete

As we discussed earlier, when a module provides named exports, we can easily select a specific function from the module by using a shortcut provided by the IDE. This feature not only saves time, but also helps the IDE suggest and auto-import the necessary functions as we type.

For example, if you start typing add, the IDE will display a list of available packages that provide the add function. All you have to do is choose the right package from the list, and the editor will automatically insert the import for you. It's that simple!

Inconsistent codebases

Default exports can be imported using any name you choose. This can lead to inconsistencies when multiple engineers are working on the same codebase and using different import names.

import add from './add';// Other engineer could use another nameimport sum from './add';

Re-exporting

When developing an npm package, it's common practice to export the package functions in its entry point, which is typically named index.js or index.ts if the package is implemented in TypeScript.

To keep things organized, we often create separate files for different functions and then re-export them in the entry point file. For example, we might have files named add.ts and multiply.ts, each containing a function to add or multiply two numbers.

If we use default exports for those files, we need to specify the names of the functions that will be available in the final package.

// index.tsexport { default as add } from './add';export { default as multiply } from './multiply';

Using named exports is more convenient:

// index.tsexport { add } from './add';export { multiply } from './multiply';

What if you want to export everything? That's where wildcard exports come in – they make it even easier.

// index.tsexport * from './add';export * from './multiply';

Conclusion

Using default exports can make it harder to find things in your code and lead to inconsistencies. Instead, named exports make it easier to discover which members are being exported and what their corresponding names are, especially when using an IDE.

It's recommended to avoid using default exports and instead opt for named exports whenever possible. By doing so, you'll have a more organized and maintainable codebase that's easier to work with in the long run.

If you found this series helpful, please consider giving the repository a star on GitHub or sharing the post on your favorite social networks 😍. Your support would mean a lot to me!

If you want more helpful content like this, feel free to follow me:

Top comments (27)

Subscribe

Rense Bakker

Rense Bakker

I am a fullstack developer with experience designing and building responsive web apps. Proficient with ReactJS, Typescript, Javascript, HTML and CSS.

  • Joined

Jan 11

  • Copy link

Actually IDEs should not have any problem finding your default exports aslong as they are not anonymous functions or objects. If you use recommended eslint rules, it will tell you not to export anonymous functions and objects.

// Editor has no idea what to doexport default function(){}// Editor will be able to auto import doSomething export default function doSomething(){}

Amin

Amin

  • Education

    École Supérieure de Génie Informatique

  • Work

    Teacher, Freelance Developer & Chief Technical Officer @ Doc2wheels

  • Joined

Jan 12 • Edited on Jan 12 • Edited

  • Copy link

There is a clear difference between function expression and function declaration and they both serve a purpose.

This can't be a viable solution since imposing function declaration would mean losing the benefits of arrow functions that grab the outer context instead of creating a context. This can be destructive for some project relying on this mecanism.

Also, you can't use that reliably on scalar data types that uses default exports, it simply fails short on your text editor and its completion system (which comes most of the time from the language server). TypeScript/JavaScript language servers do not work well on default exporting scalar data types. So using a default export is very much problematic for a lot of things.

Instead, named exports are harmless in the sense that you can either named export a function expression as well as a function declaration, it does not impose on your team a way of doing things, plus the benefits mentioned above in this article. And it provides the best completions and auto-import capabilities from your language server when used in your text editor (and many editor benefit from that such as Emacs, Neovim, IntelliJ, VSCode, etc...).

Rense Bakker

Rense Bakker

I am a fullstack developer with experience designing and building responsive web apps. Proficient with ReactJS, Typescript, Javascript, HTML and CSS.

  • Joined

Jan 14

  • Copy link

You can do this with arrow functions as well:

// Editor has no idea what to do and you should never do this.export default () => {}// Editor has no problem auto importing non-anonymous arrow functionconst someArrowFunction = () => {}export default someArrowFunction

José María CL

José María CL

Hi there! I'm a web front-end web developer. I also do back-end, desktop and mobile stuff. I like to help people and solve problems.

Jan 15

  • Copy link

Yeah but that's a "if you setup that stuff correctly" 😕

Using named exports doesn't depend on ideal circ*mstances

Rense Bakker

Rense Bakker

I am a fullstack developer with experience designing and building responsive web apps. Proficient with ReactJS, Typescript, Javascript, HTML and CSS.

  • Joined

Jan 15

  • Copy link

This works in vscode without any additional configuration and I'm pretty confident it works in most other editors as well, if they understand named exports they also understand default exports as long as your default exports are not anonymous functions.

𒎏Wii 🏳️‍⚧️

𒎏Wii 🏳️‍⚧️

Blog: https://blog.but.gayMastodon: @[email protected]: en.pronouns.page/@darkwiiplayer

  • Pronouns

    she/her;q=1, they/them;q=0.8, */*;q=0.2

  • Joined

Jan 11

  • Copy link

Default exports can be confusing in complex modules. Developers may not know which export is the default or even be aware of its existence. This can cause delays as engineers must spend more time looking at documentation or even the source code to find the functions they need.

I've read this paragraph several times now and I still think it makes no sense whatsoever. Can you explain what you mean by this?

If you decide to rename a named export in a module, for example, changing the name of the add function to sum, most IDEs can automatically update all usages. This makes the refactoring process much easier.
However, with default exports, this isn't possible.

Again, this doesn't make any sense to me whatsoever; what is the problem here? Default exports have no name, so what would you want to happen here?

As we discussed earlier, when a module provides named exports, we can easily select a specific function from the module by using a shortcut provided by the IDE. This feature not only saves time, but also helps the IDE suggest and auto-import the necessary functions as we type.

This one makes more sense, but it's not really an argument against default imports. As long as your default export is also available as a named export (which is probably a good idea regardless), this still works 100%.

Default exports can be imported using any name you choose. This can lead to inconsistencies when multiple engineers are working on the same codebase and using different import names.

Again, this is a good reason to also have a named export for your default export, but it doesn't speak against having a default export in any way.

Setting that aside, regardless of consistency or not, if I look at a source file and see import add from "sum" I will probably scratch my head multiple times and tell whomever wrote that to fix it (or just not interact with the project if it's OSS)

Conclusion

Just provide named alternatives for your default export and everyone will be happy. We can have both.

wakywayne

wakywayne

  • Location

    New York

  • Work

    Managing Director of WAR Zone

  • Joined

Jan 11 • Edited on Jan 11 • Edited

  • Copy link

Isn't that a bit repetitive though? Regarding both default and named exporting.

𒎏Wii 🏳️‍⚧️

𒎏Wii 🏳️‍⚧️

Blog: https://blog.but.gayMastodon: @[email protected]: en.pronouns.page/@darkwiiplayer

  • Pronouns

    she/her;q=1, they/them;q=0.8, */*;q=0.2

  • Joined

Jan 13

  • Copy link

it's three keywords per file, I don't think that's the kind of thing to seriously be worried about.

Anass Boutaline

Anass Boutaline

Full-stack Web Developer, Software engineer

  • Location

    Morocco

  • Work

    Full-stack Web Developer

  • Joined

Jan 12

  • Copy link

This could be a discussion rather than a judgement, this way you're misleading others, named export or default export each export type has a purpose, some times you need to export a single function from a file to serve specific purpose, as you can use named export when you wants to group multiple functions in a single file etc

Hauke T.

Hauke T.

Usabilty Engineer and JavaScript/TypeScript Developer.On the path to become a Clean Code Developer.Also rediscovering OOP-Principals and Design-Patterns.

Jan 12

  • Copy link

You had me at "Refactoring" - very true.

Eric B

Eric B

Hello! Professional programmer since 2010, hobbyist since 1982.

  • Joined

Jan 12

  • Copy link

Most of these aren't real problems, and many people use default exports just fine.

Sean Dinan

Sean Dinan

Web developer based in Belgium

  • Location

    Gent, BE

  • Pronouns

    he/him

  • Work

    Fullstack Developer

  • Joined

Jan 11 • Edited on Jan 11 • Edited

  • Copy link

Yep, spot on. Especially the Inconsistent Codebases section.

In the rare instances where a named export does need to be renamed, it can always be done with as:

import { Provider as RollbarProvider, ErrorBoundary } from '@rollbar/react';

wakywayne

wakywayne

  • Location

    New York

  • Work

    Managing Director of WAR Zone

  • Joined

Jan 11

  • Copy link

I'd say what the OP is suggesting is probably the safer bet, but this really is only an issue in really big code bases with lots of people working on it. Also in frameworks like React that have strict file naming conventions as long as you follow those conventions, you should just use the previous standards not make up your own. Another situation where default exports are better is when you are making a npm package, in this use case it only makes things worse for the user if they have to remember the name of the export.

José Pablo Ramírez Vargas

José Pablo Ramírez Vargas

  • Location

    Heredia, Costa Rica

  • Work

    Senior software developer @ Intel

  • Joined

Jan 11

  • Copy link

The IDE has no issues finding default exports while typing. It is a matter of providing proper information. Someone already said that if you export a nameless something, then that's a problem, but if you export something with a name, that name shows up in autocomplete.

Furthermore, NPM packages should provide proper d.ts files. Using my vite-plugin-single-spa package as example, you just install, then open vite.config.ts and you start typing "import vitep". At this point you should see autocomplete showing you the right option (vitePluginSingleSpa).

Drew Killeen

Drew Killeen

Crafting digital experiences, one line of code at a time

  • Location

    Pittsburgh, PA

  • Education

    BA in Computer Science

  • Joined

Jan 20

  • Copy link

Good thoughts, I like that you're challenging convention and asking us to think through things rather than just following the norms.

In my opinion, all of what you're saying is true when a file has multiple exports. I do find it confusing to have a default export mixed with named exports. But typically when a default export is used, I only see a single export from that file. I haven't run into any problems with that, especially since the file, function, and import almost always share the same name.

But at the same time, I also see no argument against using only named exports, so maybe you're on to something.

Jack

Jack

Typescript and React nerd. I have a soft spot for architecture and unit testing

  • Location

    United Kingdom

  • Joined

Jan 16

  • Copy link

This is the developer-equivalence of first world problems.

IDEs have no problem discovering default exports in my experience. And I frequently rename default exports and vscode is smart enough to rename imports automatically.

I also have absolutely no issue with somebody deciding to only use named exports in their codebases, go for it. But here we're dressing personal preference as best practice which is incorrect.

Shawn P

Shawn P

Senior software engineer

  • Joined

Jan 12 • Edited on Jan 12 • Edited

  • Copy link

The reason we have so many different tools at our disposal is so that we can use the best tool for a given context, and contexts vary greatly in this field. It is disappointing to see so much of these “never use X conventional method ever again” articles and videos which usually fail to sufficiently acknowledge the optimal use cases for the thing they are bashing on and seem aimed at being provocative and generating clicks more than offering genuine educational content. This article starts by acknowledging the correct use cases but then proceeds to suggest never using them ever again.

Default exports are absolutely the right choice when there’s only one thing to be exported, and there are plenty of architectural nuances from project-to-project that could warrant their use in other contexts. This point-blank statement of “default exports are bad and you shouldn’t use them” comes across as biased and imho could be potentially misleading to beginners.

Матвей Т

Матвей Т

  • Location

    Embedded Systems

  • Joined

Jan 13

  • Copy link

A thing I tend to do, when I am working on a module where it makes sense to have multiple exports, but also one main default export is this:

export function add(x: number, y: number): number { return x + y;}export default add;

Joao Sumbo (J.P)

Joao Sumbo (J.P)

  • Joined

Jan 13 • Edited on Jan 13 • Edited

  • Copy link

To me , it seems like this articles seems like a personal issue l.
I use Vue , and Typescript , on top of that I apply OOP , which means there are a lot Class files that it makes sense that one File holds 1 default class and maybe some types. I use default export often an I have never any of the problems you mentioned my IDE (Webstorm, intelij) knows exactly where are they. On top of that I use the default export in conjunction with "named export" andy IDE k ow exactly how to import them . import A, {b}.

Paul Fox

Paul Fox

  • Joined

Mar 1

  • Copy link

I have worked on code bases with default exports where casing and typos have caused discoverability issues.

import Buton from 'Button'

If it can break "find in files" that's a good enough reason for me to not use it. IDEs make our lives easier in a lot of ways, but at the end of the day an IDE is just a tool. If you need it to understand your code, there's a problem. Anything that makes the code easier to understand without tooling is best practice in my book.

Default exports are not needed. Exporting a single named function from a module is completely unrestricted. If you need to rename a module, use the as directive.

import { module as betterNamedModule } from 'module';

Then grepping the codebase will at least see the import reference. You won't even need it if you take your time namig things and refactor when things become so similar that their names overlap. So why use default exports?

Alois Sečkár

Alois Sečkár

I am from Czechia, born in 1988. Studied computer science at KIT VŠE, Prague. Currently working as senior Java & JS developer for Eviden.

  • Email

  • Location

    Prague, Czechia

  • Education

    KIT VŠE, Prague

  • Pronouns

    He

  • Work

    Senior application developer @ Eviden

  • Joined

Jan 11

  • Copy link

Good summary.

I especially dont like when I am forced to mix named and default imports from 3rd party libraries. (yes, I know I can make a custom reexport somewhere in codebase).

Dimitar

Dimitar

high perf cpp turned full stack + devops

  • Joined

Jan 13

  • Copy link

If you're getting confused by exports then I'd recommend investing a few minutes in getting a free IDE.

As a newcommer to the JS env from cpp/python I don't really see the need of default exports. Everyone else has managed without them.

View full discussion (27 comments)

For further actions, you may consider blocking this person and/or reporting abuse

Avoid using default exports (2024)
Top Articles
How to Use Field Test Mode: For iPhone and Android
How Do You Build Credit History More Quickly? | Chase
Kansas City Kansas Public Schools Educational Audiology Externship in Kansas City, KS for KCK public Schools
The Daily News Leader from Staunton, Virginia
Ashlyn Peaks Bio
J Prince Steps Over Takeoff
Bustle Daily Horoscope
Imbigswoo
Planets Visible Tonight Virginia
Skylar Vox Bra Size
454 Cu In Liters
Valentina Gonzalez Leak
Walthampatch
House Of Budz Michigan
The Largest Banks - ​​How to Transfer Money With Only Card Number and CVV (2024)
1-833-955-4522
Watch The Lovely Bones Online Free 123Movies
Music Go Round Music Store
Accident On 215
Governor Brown Signs Legislation Supporting California Legislative Women's Caucus Priorities
Dewalt vs Milwaukee: Comparing Top Power Tool Brands - EXTOL
The Listings Project New York
Living Shard Calamity
Lines Ac And Rs Can Best Be Described As
4 Methods to Fix “Vortex Mods Cannot Be Deployed” Issue - MiniTool Partition Wizard
Smartfind Express Login Broward
Cfv Mychart
Dell 22 FHD-Computermonitor – E2222H | Dell Deutschland
My Reading Manga Gay
Happy Shuttle Cancun Review
Elanco Rebates.com 2022
Fastpitch Softball Pitching Tips for Beginners Part 1 | STACK
Egg Crutch Glove Envelope
How to Use Craigslist (with Pictures) - wikiHow
123Moviestvme
Workboy Kennel
LEGO Star Wars: Rebuild the Galaxy Review - Latest Animated Special Brings Loads of Fun With An Emotional Twist
A Man Called Otto Showtimes Near Carolina Mall Cinema
Indiana Immediate Care.webpay.md
Waffle House Gift Card Cvs
Nobodyhome.tv Reddit
Andrew Lee Torres
Linkbuilding uitbesteden
Craigslist/Nashville
Best Conjuration Spell In Skyrim
Craigslist Woodward
Arcanis Secret Santa
Learn4Good Job Posting
Windy Bee Favor
Rétrospective 2023 : une année culturelle de renaissances et de mutations
Att Corporate Store Location
Latest Posts
Article information

Author: Rueben Jacobs

Last Updated:

Views: 5946

Rating: 4.7 / 5 (57 voted)

Reviews: 88% of readers found this page helpful

Author information

Name: Rueben Jacobs

Birthday: 1999-03-14

Address: 951 Caterina Walk, Schambergerside, CA 67667-0896

Phone: +6881806848632

Job: Internal Education Planner

Hobby: Candle making, Cabaret, Poi, Gambling, Rock climbing, Wood carving, Computer programming

Introduction: My name is Rueben Jacobs, I am a cooperative, beautiful, kind, comfortable, glamorous, open, magnificent person who loves writing and wants to share my knowledge and understanding with you.