export Keyword

Description

Every module can have two different types of export, named export and default export. You can have multiple named exports per module but only one default export. Each type corresponds to one of the above syntax.

Named exports:

// export features declared elsewhere
export { myFunction2, myVariable2 };

// export individual features (can export var, let,
// const, function, class)
export let myVariable = Math.sqrt(2);
export function myFunction() { /* ... */ };

After the export keyword, you can use let, const, and var declarations, as well as function or class declarations. You can also use the export { name1, name2 } syntax to export a list of names declared elsewhere. Note that export {} does not export an empty object - it's a no-op declaration that exports nothing (an empty name list).

Export declarations are not subject to temporal dead zone rules. You can declare that the module exports X before the name X itself is declared.

export { x };
const x = 1;
// This works, because `export` is only a declaration, but doesn't
// utilize the value of `x`.

Default exports:

// export feature declared elsewhere as default
export { myFunction as default };
// This is equivalent to:
export default myFunction;

// export individual features as default
export default function () { /* … */ }
export default class { /* … */ }

// each export overwrites the previous one

The export default syntax allows any expression.

export default 1 + 1;

As a special case, functions and classes are exported as declarations, not expressions, and these declarations can be anonymous. This means functions will be hoisted.

// Works because `foo` is a function declaration,
// not a function expression
foo();

export default function foo() {
  console.log("Hi");
}

// It's still technically a declaration, but it's allowed
// to be anonymous
export default function () {
  console.log("Hi");
}

Named exports are useful when you need to export several values. When importing this module, named exports must be referred to by the exact same name (optionally renaming it with as), but the default export can be imported with any name. For example:

// file test.js
const k = 12;
export default k;
// some other file
import m from './test'; // note that we have the freedom to use import m instead of import k, because k was default export
console.log(m);        // will log 12

You can also rename named exports to avoid naming conflicts:

export {
  myFunction as function1,
  myVariable as variable,
};

You can rename a name to something that's not a valid identifier by using a string literal. For example:

export { myFunction as "my-function" };


Re-exporting / Aggregating

A module can also "relay" values exported from other modules without the hassle of writing two separate import/export statements. This is often useful when creating a single module concentrating various exports from various modules (usually called a "barrel module").

This can be achieved with the "export from" syntax:

export {
  default as function1,
  function2,
} from 'bar.js';

Which is comparable to a combination of import and export, except that function1 and function2 do not become available inside the current module:

import { default as function1, function2 } from 'bar.js';
export { function1, function2 };

Most of the "import from" syntaxes have "export from" counterparts.

export { x } from "mod";
export { x as v } from "mod";
export * as ns from "mod";

There is also export * from "mod", although there's no import * from "mod". This re-exports all named exports from mod as the named exports of the current module, but the default export of mod is not re-exported. If there are two wildcard exports statements that implicitly re-export the same name, neither one is re-exported.

// -- mod1.js --
export const a = 1;

// -- mod2.js --
export const a = 3;

// -- barrel.js --
export * from "./mod1.js";
export * from "./mod2.js";

// -- main.js --
import * as ns from "./barrel.js";
console.log(ns.a); // undefined

Attempting to import the duplicate name directly will throw an error.

import { a } from "./barrel.js";
// SyntaxError: The requested module './barrel.js' contains conflicting star exports for name 'a'

The following is syntactically invalid despite its import equivalent:

export DefaultExport from 'bar.js'; // Invalid

The correct way of doing this is to rename the export:

export { default as DefaultExport } from 'bar.js';

The "export from" syntax allows the as token to be omitted, which makes the default export still re-exported as default export.

export { default, function2 } from 'bar.js';