Note: This article was originally written for my personal blog. I am republishing it here for the DEV community.
Maintaining medium to large projects is a pain. Even if you try to split things up into multiple files, you start to realize that managing imports starts getting ugly. I'd be lying if I said my files never looked like this:
// Holy imports Batman! 😲
import Grid from './components/Grid';
import Title from './components/Title';
import Text from './components/Text';
import Button from './components/Button';
import Alert from './components/Alert';
Since we're importing these components all from the same folder, wouldn't it be nice to just do something like this?
// Much better 😌
import { Grid, Title, Text, Button, Alert } from './components';
Unfortunately, the import statement does not allow importing a folder. However, I've come up with a solution that allows this anyway. Hold your money, let me know show you how first.
The index re-export pattern
I'm not really sure if there is a proper name for this, so I'm calling it the "index re-export" pattern. This is because we are going to create an index.js
file where all of the files in our folder will be imported and exported again.
Using the example of our components
folder, let's create a file in components/index.js
.
Next, we will use an uncommon feature of the export statement to be able to export from another file:
export { default as Grid } from './Grid';
export { default as Title } from './Title';
export { default as Text } from './Text';
export { default as Button } from './Button';
export { default as Alert } from './Alert';
This not only allows you to import all of your components from the components
folder, but it also creates what is essentially your own library of UI components.
There is also a huge benefit from this in being able to see exactly what you are able to import, especially if not all of your exports are default exports. For example, let's say that inside of components/Button.js
you have both a default and named export:
export default Button; // default export of Button component
export BigButton; // named export of a Button variant
So now inside of components/index.js
, we can add BigButton
:
export { default as Button, BigButton } from './Button';
It's as simple as that.
With great power comes great responsibility
There is such a thing as overarchitecting your projects, so I'd exercise caution before deciding to use this pattern for every single folder. While it's convenient for importing multiple components, it may be become annoying when importing smaller things like utility/helper functions. You'll know while coding when the pain point is so high that you'll reach for it, but otherwise I wouldn't do it prematurely.
Top comments (2)
Did you get this to work properly with webpack 4 and production build mode? When i tried this recently webpack failed to notice that these imports were in use and removed them from the production build.
That is a really weird case scenario. I didn't have any issues with the latest version of Next.js, which should be using latest Webpack as well. Are you using
babel-preset-env
and Node v8 or newer?