JavaScript Modules - Exercise 3
Move shared values or operations into a third module so the original modules no longer import each other directly.
// shared.js
export const roles = { admin: 'Admin' };
// user.js and format.js can both import roles.js.Each module may be evaluated before the other has finished initializing its exports. Move work behind a function or remove the cycle.
// Prefer calling after initialization:
export function getLabel() {
return formatUser(user);
}Use the module system required by the runtime and project configuration. ESM uses static import/export; CommonJS uses require/module.exports.
// ESM
export { add };
import { add } from './math.js';
// CommonJS
module.exports = { add };
const { add } = require('./math');Use a dynamic import inside the event or condition that needs the feature.
button.addEventListener('click', async () => {
const { openEditor } = await import('./editor.js');
openEditor();
});Dynamic imports return Promises, so handle failures with try...catch.
try {
const feature = await import('./optional-feature.js');
feature.start();
} catch (error) {
showUnavailableMessage(error);
}A regular top-level import has a literal module path, allowing tools to build the dependency graph before execution.
import { format } from './format.js';
// The path is known during build analysis.Re-export only the public API from an entry module and keep internal files private to the feature.
// users/index.js
export { createUser } from './create-user.js';
export { findUser } from './find-user.js';Keep modules focused, export pure functions where possible, and inject external dependencies instead of hiding them in module-level state.
export function total(items, taxRate) {
return items.reduce((sum, item) => sum + item.price, 0) * (1 + taxRate);
}