9. ES modules & project structure
JavaScript · 56 pages source format
ES modules (import/export) replace script-tag soup. Named exports for utilities, default export for main component. Split by responsibility: api.js, render.js, main.js. Vite or native Node "type": "module" for local dev without bundler pain.
What you'll learn
- export / import
- Default vs named exports
- Module scope
- Vite setup
- Barrel files lite
Named exports
export function foo() {} and export const BAR = 1. Import with import { foo, BAR } from "./utils.js". Extensions required in browser and Node ESM.
// utils.js
export function titleCase(str) { /* ... */ }
export function slugify(str) { /* ... */ }
// main.js
import { titleCase, slugify } from "./utils.js"Do this now
Move your utility functions to utils.js. Import them in main.js.
Default export
One default per module: export default function App() {}. Import: import App from "./App.js". Use for main component; named exports for everything else.
Do this now
Create api.js with default export fetchPosts and named export getPost.
Vite project setup
npm create vite@latest my-app -- --template vanilla. npm install && npm run dev. Hot reload, native ESM, zero config for learning.
npm create vite@latest js-fetch-app -- --template vanilla
cd js-fetch-app
npm install
npm run devDo this now
Scaffold Vite vanilla project. Port your fetch app into src/ modules. Verify dev server runs.
Separation of concerns
api.js — fetch functions, no DOM. render.js — DOM updates, no fetch. main.js — wire events, call api, call render. Test api and utils without browser.
Do this now
Refactor post browser into api.js, render.js, main.js. main.js under 50 lines.
Environment variables (preview)
Vite exposes import.meta.env.VITE_* to client code. Never put secrets in frontend env vars — they ship to browsers.
Do this now
Add VITE_API_BASE to .env. Use it in api.js. Document in README.