DEV Community

Cover image for JavaScript Module Cheatsheet ๐Ÿ“„โ€ฌ
Samantha Ming
Samantha Ming

Posted on • Originally published at samanthaming.com

JavaScript Module Cheatsheet ๐Ÿ“„โ€ฌ

CodeTidbit by SamanthaMing.com

Here's a cheat sheet to show you the different ways of exporting and the corresponding way to import it. It really distills to 3 types: name, default, and list. Just make sure your export matches your import way and you will have no problem ๐Ÿ‘

// Name Export | Name Import
export const name = 'value'
import { name } from '...'

// Default Export | Default Import
export default 'value'
import anyName from '...'

// Rename Export | NameImport
export { name as newName }
import { newName } from '...'

// Name + Default | Import All
export const name = 'value'
export default 'value'
import * as anyName from '...'

// Export List + Rename | Import List + Rename
export {
  name1,
  name2 as newName2
}
import {
  name1 as newName1,
  newName2
} from '...'

Now let's look at each of them and see how they work ๐Ÿค“

a. Name

The key here is having a name. Hence a "named" export lol ๐Ÿ˜‚

export const name = 'value';
import { name } from '...';

console.log(name); // 'value'

โŒ What did I say, no name, no export!

export 'value'

import { } // ๐Ÿ‘ˆ see I don't even know what to put here...give me a name!

b. Default

With a default export, you don't need any name. Because you can name it whatever you want ๐Ÿ‘

export default 'value'
import anyName from '...';

console.log(anyName); // 'value'

โŒ No Variable Declaration with Default

export default const name = 'value'; // don't try to give me a name!

Mixing Default + Name

You can absolutely combine default and name export in one file ๐Ÿค

export const name = 'value';
export default 'value'
import anyName, { name } from '...';

c. Export List

The third style is Export List.

const name1 = 'value1';
const name2 = 'value2';

export {
  name1,
  name2
}
import {
  name1,
  name2
} from '...'

console.log(
  name1, // 'value1'
  name2, // 'value2'
)

One important thing to note is that these lists are NOT objects. Yes, I know it looks like it. But it isn't. I made this confusion when I first learned modules. It's not an object, it's an export list!

// โŒ Export list โ‰  Object
export {
  name: 'name'
}

Renaming Export

Not happy with the export name. No problem, you can rename it using the as keyword.

const name = 'value'

export {
  name as newName
}
import { newName } from '...'

console.log(newName); // 'value'

// Original name is not accessible
console.log(name); // โŒ undefined

โŒ Can not combine inline export with export list

export const name = 'value';

// You're already exporting name โ˜๏ธ, don't export me again
export {
  name
}

Renaming Import

The same rule applies to import. We can rename it using the as keyword.

const name1 = 'value1';
const name2 = 'value2';

export {
  name1,
  name2 as newName2
}
import {
  name1 as newName1,
  newName2
} from '...'

console.log(newName1); // 'value1'
console.log(newName2); // 'value2'

โŒ
name1; // undefined
name2; // undefined

Import All

export const name = 'value';

export default 'defaultValue';
import * as anyName from '...';

console.log(anyName.name); // 'value'
console.log(anyName.default); // 'defaultValue'

Name vs Default

There's been a lot of debate whether one should use default export at all. Check out these 2 articles.

Like with anything, there is no right or wrong answer. The right way is always what's best for you and your team. But here's how I can think of this debate. Samantha's Story Time ...

Name vs Default Export in Non-Dev Terms

Let's say you owe your friend some money. Your friend says you can pay them back with cash or e-transfer. Paying through e-transfer is like a named export because your name is attached to the transaction. So if your friend is forgetful and starts chasing you down claiming that you still owe them money. You can simply show them the proof of transfer because your name is on the payment. However, if you had paid your friend back with cash, which is like a default export, you have no proof. They can say the $50 is from Susan and NOT you. The cash has no name attached to it so they could say it's from you or whoever it is ๐Ÿ˜ต

So is it better to go with e-transfer (named export) or cash (default export)? Well that depends, do you trust your friend or not ๐Ÿค” Actually, that's not the right way to frame this dilemma. A better solution is to NOT put your relationship in that position. It's better to be explicit so you don't risk jeopardizing your friendship. And yes, this idea also applies to whether you pick named or default export. I prefer to be more explicit, so your code is crystal clear. But of course, your code is your code. And you can do whatever works for you and your team ๐Ÿ˜„

Community Input

  • @kyleshevlin: Maybe there's a way you could add the asterisk import, too, where you import all exports from a module. import * as myModule from '/modules/my-module.js';. The key with that one is that on the import side when using the module, the default is there as myModule.default and the rest are as they are named, myModule.nameOfSomething. CodeSandbox Example

  • @erikayabar: ๐Ÿ‘ the emphasis on anyName here for default exports! *This is why I prefer named exports, but it seems community is set on default export all the things (especially React components) so it's good to understand the difference! Also seen confused: named imports != destructuring

Resources


Thanks for reading โค
Say Hello! Instagram | Twitter | Facebook | Blog | SamanthaMing.com

Top comments (31)

Collapse
 
pavelloz profile image
Paweล‚ Kowalski

There is also good old import * from 'x' ;)

Collapse
 
mburszley profile image
Maximilian Burszley

import * is a terrible practice and pollutes the namespace.

Collapse
 
pavelloz profile image
Paweล‚ Kowalski

I dont think so.

Thread Thread
 
mburszley profile image
Maximilian Burszley

Many best practices from many programming languages disagree with you.

Thread Thread
 
pavelloz profile image
Paweล‚ Kowalski

Good to know. Cheers.

Collapse
 
oanouman profile image
Martial Anouman

Totally agree.

For me it's quite annoying to use imported func or var with unknown/unpredictable origin.

Collapse
 
samanthaming profile image
Samantha Ming

Yup! I realize I missed that one so I included it in my notes ๐Ÿ‘ The tidbit will also be updated, I donโ€™t want to ruin the surprise...but I maybe have a new series coming up ๐Ÿ˜

Collapse
 
carlosnufe_97 profile image
Carlos Nรบรฑez

Perhaps you could add the use case for export/import at the same time.

i.e export { named } from 'path/module'

Collapse
 
wh0am1 profile image
Carlos Aguilar

You can also re-export a default import.
It's already implicit, given the list already points the imported.default thing, but I think it's special enough to be included:

export { default as anyName } from 'path/module'
Collapse
 
samanthaming profile image
Samantha Ming

Oh! Like including the actual path...yes! I had an earlier comment on this. Totally see how thatโ€™s way better...Iโ€™ve made a note to update this code note. Thank you for pointing it out! I like it, cause it helps me
Improve my code notes ๐Ÿ˜Š๐Ÿ‘

Collapse
 
kevinhch profile image
Kevin

Hi, this only works in node or something like that? When I tried to reproduce the first example in Vanilla JS, always say the same error: SyntaxError: Cannot use import statement outside a module

Collapse
 
samanthaming profile image
Samantha Ming

To add to it ...the goal of import/export is to allow you to split your JS into separate files. To bring it back together, you need a module bundler (ie. Webpack or gulp) to join all the files together. The end result is one giant JS file. And that's the file you can use in your HTML.

In non dev terms, think of it as a kitchen. It's split into different workstations (why? because everyone can focus on what they're good it and is more efficient). And then there's the chef that puts everything together (think Gordon Ramsay lol). That chef is the module bundler. And she/he makes sure the dish is all combined so the customer can eat it. Hope this makes sense ๐Ÿ˜„

Collapse
 
brianwfl88 profile image
brianwfl88

ES6 import module only works in transpiler like webpack. The support for node is currently in experimental stage.

Collapse
 
jefferyhus profile image
El Housseine Jaafari

You meant to say 'like babel', because webpack is a bundler.

Thread Thread
 
samanthaming profile image
Samantha Ming

In this instance because the files are all in modules, you will need a bundler like webpack or even gulp to join them all together ๐Ÿ™‚

i explain it here a bit more > dev.to/samanthaming/comment/i48b

Thread Thread
 
jefferyhus profile image
El Housseine Jaafari

Thanks, but I just corrected what he said ๐Ÿ˜….

Thread Thread
 
samanthaming profile image
Samantha Ming

Ah got it! Iโ€™ll also adjust my notes, thanks for the clarification ๐Ÿ™‚

Collapse
 
samanthaming profile image
Samantha Ming

Yup you got it! Thanks for chiming and helping with the answer @brianwfl88 ๐Ÿ‘

Collapse
 
samanthaming profile image
Samantha Ming

Great question! (i think i should of talked about in the post! will make a note of it)...let me paste my answer to another response...hope this clears it up ๐Ÿ˜„

To add to it ...the goal of import/export is to allow you to split your JS into separate files. To bring it back together, you need a module bundler (ie. Webpack or gulp) to join all the files together. The end result is one giant JS file. And that's the file you can use in your HTML.

In non dev terms, think of it as a kitchen. It's split into different workstations (why? because everyone can focus on what they're good it and is more efficient). And then there's the chef that puts everything together (think Gordon Ramsay lol). That chef is the module bundler. And she/he makes sure the dish is all combined so the customer can eat it ๐Ÿฅ—

Collapse
 
ethubert profile image
Hubert Hilczer

Thank you, it's always great to see articles that go a bit more in depth over what implications such seemingly trivial decisions might have for the project.

Collapse
 
samanthaming profile image
Samantha Ming

Thank you! That article I linked up really changed my perspective. Youโ€™re absolutely right, little things have big effects...I can see how an architecture job is so difficult...got to plan all those little details, cause they know what they create will have long term impact ๐Ÿ˜ฒ

Collapse
 
daveu1983 profile image
Daveu1983

Great article. Thanks Samantha. Can I just check the '...' is the path/file that you are exporting from? And not some other "spread like" syntax I am not aware of?

Collapse
 
samanthaming profile image
Samantha Ming

Yes it is! Great point! Totally can see how thatโ€™s confusing...let me make a note to update the code notes to show path ๐Ÿ‘ thank you for pointing that source of confusion! Itโ€™s comments like yours that help improve the notes ๐Ÿ‘๐Ÿ‘๐Ÿ‘

Collapse
 
boristechnotronics profile image
BorisTechnotronics

totally helpful

Collapse
 
samanthaming profile image
Samantha Ming

Awesome! thank you for reading the article ๐Ÿ‘

Collapse
 
mfarajewicz profile image
Mirosล‚aw Farajewicz

Great content. Thank you Samantha.

Your article touches of what I think is one of the hardest things in modern JS programming: Stuff related to exporting and module loading patterns.

Collapse
 
samanthaming profile image
Samantha Ming

Thank you! I was confused for a long time with this modules...hopefully I was able to clarify it a bit for folks trying to learn this topic ๐Ÿ™‚๐Ÿคž

Collapse
 
rshmangit profile image
RshmanGit

Really helpful

Collapse
 
samanthaming profile image
Samantha Ming

Thank you! Glad you found it helpful ๐Ÿ˜„

Collapse
 
alin11 profile image
Ali Nazari

Wow thanks. Very useful!

Collapse
 
oanouman profile image
Martial Anouman

Good article. Congrats.
I remember years ago when a started ES5+ JS that import/export was a bit confusing.

Your article will surely help newcomers. ๐Ÿ™‚