Understanding Javascript modules. Default vs Named exports

In ES6 (ECMAScript 6) JavaScript modules, you can export values from a module and import them into another module. This is great because it allows you to organize, modularize and reuse code in a very efficient way.

There are two possible approaches: Default and Named exports. But what’s the difference between them, and which is better? Let us see.

In This Article:

Default Exports

The default export approach allows you to export a single value from a module as a default. The value can be a constant, a variable, a function or a class. All values that are not exported are private and not accessible by other modules.

// product.ts
const _productName = 'Cowboy hat';
function _getProductPrice() {
  return '12€'
}
export default `in your cart there is a ${_productName} worth ${_getProductPrice()}`;

// cart.ts
import productData from './product.ts';
console.log(productData)
// in your cart there is a Cowboy hat worth 12€

The name of the imported value (in the example above productData) is arbitrary.

Named Exports

With named exports you can export multiple values from a module and import them by name.

// product.ts
export const productName = 'Cowboy hat';
export function getProductPrice() {
  return '12€'
}

// cart.ts
import { productName, getProductPrice } from './product.ts';
console.log(`in your cart there is a ${productName} worth ${getProductPrice()}`)
// in your cart there is a Cowboy hat worth 12€

Mixed approach

It is also possible to use both approaches within the same code if needed.

// product.ts
export const productName = 'Cowboy hat';
export default function getProductPrice() {
  return '12€'
}

// cart.ts
import productPrice, { productName } from './product.ts';
console.log(`in your cart there is a ${productName} worth ${productPrice()}`)
// in your cart there is a Cowboy hat worth 12€

What is the best way?

Of course there is no single answer. It depends on the needs of the project. But I would say that in most cases the named approach offers greater advantages in terms of readability and maintainability of the code except when a module has a single exported value.

In fact in the case of the default approach, the name of the imported values can change and this can lead to many side effects such as multiple imports or inconsistent names. Furthermore, debugging the dependency chain will be more difficult.

With named exports you always have the possibility to set the name of the imported value if it is necessary to avoid conflicts. And it will still be readable because the reference to the original name of the value will remain.

import { productName as name } from './product.ts';
console.log(`in your cart there is a ${name}`)
// in your cart there is a Cowboy hat

Or, If you need to import everything from a module, you can use the wildcard

// cart.ts
import * as productData from './product.ts';
console.log(`in your cart there is a ${productData.productName} worth ${productData.getProductPrice()}`)
// in your cart there is a Cowboy hat worth 12€

Architectural tip

As you may have understood, JavaScript modules are very useful for organizing code in an orderly and readable way. Let me share with you a very common method for “bundling” similar modules and making them available to the whole application without messing with multiple imports.

Let’s say we have an application with several payment methods, we could include them all in one folder and export them all from the index.ts file

// payments/index.ts
export { payPal } from './paypal';
export { amazonPay } from './amazon';
export { creditCard } from './creditCard';
export { bankTransfer } from './bankTransfer';

Now they can all be imported in a rather concise and elegant way

import * as payment from './payments';
console.log(`Hi! I'm using ${payment.payPal}`)

cry-Macho.jpg “Cry Macho” Clint Eastwood, 2021

Irene Iaccio

Freelance web developer

Subscribe to the monthly digest!

I'll use your email only to send you the latest posts once a month.