Skip to content

Instantly share code, notes, and snippets.

@sfletche
Last active June 14, 2017 01:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sfletche/9b53668a2489a6885d0031062e769c7e to your computer and use it in GitHub Desktop.
Save sfletche/9b53668a2489a6885d0031062e769c7e to your computer and use it in GitHub Desktop.
Module import and export cheatsheet

JS Modules are file-based, meaning one module per file.

Modules are singletons, meaning there's always only one instance of the module (and it's state).

Named Exports

export function foo() { ... }
export let bar = 23;
const baz = [1, 2, 3];
export { baz };

// aliased exports
function foo() { ... }
export { foo as bar };

Named exports are actual bindings (kind of like pointers) to the exported thing (variable, function, etc). For example:

// File #1
let awesome = 23;
function update() { awesome = 100; }
export { awesome, update };
// File #2
import { awesome, update } from './file-1';
console.log(awesome); // 23
update();
console.log(awesome); // 100

Even though awesome holds a primitive value (and primitive values are immutable), because the awesome export is a binding to the variable (not to the value), the second output is 100.

Take-away: named exports are bindings to the variable, not just references to the value.

Default Exports

Only one default export per file

function foo() { ... }
export default foo;
export default function bar() { ... }
function baz() { ... }
export { baz as default };
let me = 23;
export default me; 
// NOTE: combining these two lines into one is not valid.  
// export default let me = 23; // would result in a syntax error

Standard default exports export a binding, but default is not a legal identifier, so that binding is not actually accessible.

// File #1
let awesome = 23;
function update() { awesome = 100; }
export default { awesome, update };
// File #2
import stuff from './file-1';
console.log(stuff.awesome); // 23
stuff.update();
console.log(stuff.awesome); // 23

Take-away: default exports are bindings to the value, not the variable.

Combining named exports with default exports

When using both named exports and a default export, make sure you are importing what you want (use default import syntax when importing default exports, use named import syntax when importing named exports)

Review: Named Exports / Imports

// File #1
export let awesome = 23;
// File #2
import { awesome } from './file-1';  

Review: Default Exports / Import

// File #1
let awesome = 23;
export default awesome; 
// File #2
import stuff from './file-1';  
console.log(stuff.awesome); // 23

Combining Named and Default Exports / Imports

// File #1
export let awesome = 23;
export function update() { awesome = 100; }
export default { awesome, update };
// File #2
import stuff, { awesome, update } from './file-1';  // stuff is imported with default import syntax
console.log(awesome); // 23
update();
console.log(awesome); // 100
...
console.log(stuff.awesome); // 23
stuff.update();
console.log(stuff.awesome); // 23

NOTE: importing members that are not exported will result in undefined imports

// File #1
let awesome = 23; // not exported as named export
export function update() { awesome = 100; } // exported as named export
export default { awesome }; // update is not exported as part of the default export object
// File #2
import stuff, { awesome, update } from './file-1'; 
console.log(awesome); // undefined (`awesome` was not a named export)
update();
console.log(awesome); // undefined (still not a named export)
...
console.log(stuff.awesome); // 23
stuff.update(); // TypeError (update was not part of the default export object (and so is not a function))

Also Noteworthy

Either webpack or babel has been letting some bad syntax linger / accumulate in our react code...

The following import is not syntactically correct (it's only by chance that it's working with our setup)...

// File #1
let awesome = 23;
function update() { awesome = 100; }
export default { awesome, update };
// File #2
import { awesome, update } from './file-1'; // Using named import syntax for default exports!!!

The correct import syntax for a default export would be

// File #2
import foo from './file-1';

Related SO question/answer: http://stackoverflow.com/a/43987935/379512

I've created a ticket (FE-916) to correct this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment