Explain Codes LogoExplain Codes Logo

Is it possible to import modules from all files in a directory, using a wildcard?

javascript
import
module-management
babel-plugin-wildcard
Nikita BarsukovbyNikita Barsukov·Feb 24, 2025
TLDR

In JavaScript, wildcard imports aren't directly supported by ES6 import syntax. To import all modules from a directory, Node.js fs and path modules are used with import():

const fs = require('fs').promises; const path = require('path'); async function importModules(directory) { const files = await fs.readdir(directory); const modules = files.map(file => import(path.resolve(directory, file))); return Promise.all(modules); }

This approach enables dynamic, at runtime, loading of modules by reading the directory content and importing each file individually, returning a Promise for all these module imports.

Implement the index.js strategy

Let's use an index.js file for grouping up our exports:

// In your index.js export { default as ModuleA } from './ModuleA.js'; export { default as ModuleB } from './ModuleB.js'; // When the import grows, so do my legs

That way you offer a single-point import, thus cleaning your code from various import lines.

import { ModuleA, ModuleB } from './lib/things';

Empowering Babel with wildcards

For Babel users, the babel-plugin-wildcard plugin allows Nature documentary levels of wildcard imports.

  1. Install the plugin:

    npm install babel-plugin-wildcard --save-dev

    // New plugin, who dis?

  2. Configure it in your .babelrc:

    { "plugins": [ "wildcard" ] }

Afterwards, you're all set for some wild imports:

import * as Things from 'lib/things'; // May the wildcard be with you

Harness dynamic imports' potential

The dynamic import() function lets you import modules on the go:

for (const file of await fs.readdir(directory)) { import(`./${file}`).then(module => { module.doTheThing(); }); }

await import() offers a cleaner and shorter code:

const module = await import(`./${filename}`); module.doTheThing(); // This code is shorter than my attention span

Embrace the power of ES6 syntax

With ES6 you can use spread syntax and named exports to keep your modules clean and tidy:

// Instead of default, name your export export const ModuleA = ...;

This maintains your modules as separate, clear entities, leading to easier management on the import side.

Be aware when going global

Globals can free you from imports and exports if you use index.js:

// In your index.js global.ModuleA = require('./ModuleA'); // Watch out for duplicate names, or someone will lose an eye!

But remember, with great power comes great responsibility. Avoid potential namespace pollution.

Webpack's context to the rescue

Webpack's require.context() provides another way to import multiple files:

const req = require.context('./directory', false, /\.js$/); req.keys().forEach(key => { const module = req(key); // Use your module here. Remember: With great power comes great circular dependencies });