ES Modules Logo ESModules.com

Common Patterns

Best practices and design patterns for ES Modules.

Singleton Pattern

ES Modules are singletons by default - they're only executed once:

// database.js
const connection = await connectToDatabase();
export { connection };

// Multiple imports get the same instance
import { connection } from './database.js'; // Same connection

Feature Flags

// features.js
export const ENABLE_DARK_MODE = true;
export const ENABLE_ANALYTICS = false;

// app.js
import { ENABLE_ANALYTICS } from './features.js';
if (ENABLE_ANALYTICS) {
  await import('./analytics.js');
}

Plugin System

// plugin-manager.js
const plugins = [];
export function registerPlugin(plugin) {
  plugins.push(plugin);
}
export function getPlugins() {
  return plugins;
}

// plugins/logger.js
import { registerPlugin } from '../plugin-manager.js';
registerPlugin({ name: 'logger', init() { /* ... */ } });

Code Splitting by Route

// router.js
const routes = {
  '/': () => import('./pages/home.js'),
  '/about': () => import('./pages/about.js'),
  '/contact': () => import('./pages/contact.js')
};

async function navigate(path) {
  const module = await routes[path]();
  module.render();
}

Re-exports Pattern

Create a barrel file to simplify imports:

// utils/index.js
export { add, subtract } from './math.js';
export { formatDate } from './date.js';
export { validateEmail } from './validation.js';

// Now consumers can import everything from one place
import { add, formatDate } from './utils/index.js';
Try It Live

Continue Learning