JavaScriptIntermediate4h

ES modules.

import/export, side effects, tree-shaking — how code links.

What is it?

ES modules (ESM) are the standard way JavaScript files reference each other. You export values from one file and import them into another. The browser, Node, Deno, and Bun all run ESM natively — bundlers (Vite, esbuild, Turbopack) just stitch many modules into fewer files for production.

Why it matters

Modules shape how code is organized and how much ships to the user. Knowing the difference between a default and named export, or how tree-shaking works, is the difference between a 50KB bundle and a 500KB one. Hiring teams check for this in pull-request comments.

What to learn

  • Named exports vs default exports — and when each is right
  • import { x } from './foo' vs import x from './foo'
  • Side-effect imports: import './styles.css'
  • Re-exports: export * from './module'
  • Static vs dynamic imports (import() returns a promise)
  • Tree-shaking: how bundlers drop unused exports

Common pitfall

Default-exporting everything. A default export is renameable on import, which means consumers can call your Button Btn in their file and the codebase loses searchability. Named exports are searchable, refactorable, and play better with tooling.

Resources

Primary (free):

Practice

Take a single-file vanilla JS project (50+ lines). Split it into modules by responsibility — utilities, DOM helpers, the main entry. Use named exports. Check the bundle size with vite build before and after. Done when the file structure tells someone what each piece does.

Outcomes

  • Choose named over default exports by default, with a real reason.
  • Split a single-file project into modules without circular imports.
  • Use dynamic import() to lazy-load a non-critical chunk.
  • Check whether tree-shaking actually dropped a function (build size diff).
Back to Frontend roadmap