AceDevHub
Data & ObjectsFree

ES Modules: import and export

Split code into reusable files with ES modules — named and default exports, import syntax, and dynamic import for lazy loading.

IntermediateFreeModules

Before modules, scripts shared one global namespace — libraries overwrote each other's variables. ES modules (ESM) give each file its own scope and explicit import/export boundaries. Bundlers (Vite, webpack) and Node resolve file paths into a dependency graph. TypeScript, React, and Next.js all assume you understand import syntax and the difference between default and named exports.

Why modules exist

Modules solve three problems at once: encapsulation (private top-level variables), reuse (import the same util from many files), and dependency structure (tools can tree-shake unused exports). Each module runs once — the first import evaluates the file; later imports get cached exports. That singleton behavior matters for database connections and config loaders.

  • File scope — top-level let/const are not global
  • Strict mode by default in ES modules
  • Static import/export analyzed at build time
  • Browsers need type="module" on script tags; Node uses .mjs or "type":"module" in package.json

Named exports — multiple per file

Named exports bind a name you must import with the same name or rename with as. They encourage explicit public APIs — a utils.js file can export formatDate, parseQuery, and clamp without a single default grab-bag. IDEs autocomplete named imports better than default-only modules.

math-utils.js
Loading editor…
app-import-named.js
Loading editor…
Outputconsole
16
5
3.14159
25
3

Default export — one primary export

A module may have one default export — often a component, class, or main function. Import name is chosen by the importer (import App from './App'). Default exports are convenient for React pages but can hurt refactoring when every file picks a different name. Many teams prefer named exports for libraries and default only for app entry components.

logger.js
Loading editor…
Outputconsole
[LOG] Server started

Re-exports and barrel files

Barrel files (index.js) re-export from submodules so consumers import from a folder path. export { foo } from './foo.js' does not run extra code in the barrel — it forwards bindings. Overusing barrels can hurt tree-shaking and create circular dependency cycles; use them at package boundaries, not for every internal folder.

index.js
Loading editor…

Dynamic import() — load on demand

import() returns a Promise resolving to the module namespace — use it for code splitting, lazy routes, and loading heavy libraries only when needed. Next.js and React lazy(() => import('./Chart')) rely on this. Static import must be at top level; dynamic import can run inside if blocks and async functions.

dynamic-import.js
Loading editor…

Chapter 3 checkpoint

You can model data with arrays and objects, reshape it with destructuring and spread, understand prototype inheritance, and organize files with ES modules — the full vocabulary for reading real npm packages and React codebases. Chat 4 enters async JavaScript: callbacks, promises, async/await, and production error handling.

  1. 1Arrays: prefer map/filter/reduce over manual loops when transforming
  2. 2Objects: reference semantics — spread for shallow immutable updates
  3. 3Destructuring + rest power function APIs and PATCH handlers
  4. 4class extends prototypes; super calls parent implementation
  5. 5Next: callbacks, event loop, and promises