Namespace imports are designed to help with this, but they have several disadvantages when compared with named imports. This article introduces named namespace imports, a technique which we’ve adopted at Unsplash to combine (as the name suggests) the best of both namespace imports and named imports.
Imagine we have a module for our API which exports some functions corresponding to API endpoints:
We love namespace imports because they provide context. For example, instead of
getUser(), which is ambiguous ("where are we getting a user from?"), we will see
(The alternative would be to prefix the name of each named export, but that’s tedious.)
We were initially worried about whether tree shaking would still work with namespace imports, but it does!
We hate namespace imports because, when compared to named imports, the developer UX suffers:
- VS Code’s import suggestions only currently work with named and default exports. So if you type
Apiin a file where there is no import for it yet, you will have to write that import out by hand. That said, we remain hopeful that VS Code will improve on this.
- Similarly to default imports, each instance of a namespace import must have its own name—unlike named imports, these imports do not share a common name. This makes it difficult to enforce consistent naming. If we use VS Code's rename functionality on a namespace import, it will only update the imported name in the current module.
Let’s eat our cake and have it
We can combine the best of namespace imports and named imports using a technique called named namespace imports.
- Import as namespace
- Re-export the namespace as a named export
- Everywhere else, import the named namespace
If you want to take this one step further, you can remove the intermediary file by using a circular import to import the current module:
Can we do better?
The downside to named namespace imports is that you have to define an intermediary module to import and then re-export the namespace.
I wish ES modules had a way to say “export this whole module as a named export”. Something like:
Update: there is some new syntax which brings us closer to this: