ES Modules & the Fetch API
18 min read
ES ModulesCommonJSDynamic ImportFetch APIAbortControllerStreamingTree Shaking
ES Modules vs CommonJS
| Feature | ES Modules | CommonJS |
|---|---|---|
| Syntax | import/export | require/module.exports |
| Loading | Static (at parse time) | Dynamic (at runtime) |
| Tree Shaking | ✅ Yes | ❌ No |
| Top-level await | ✅ Yes | ❌ No |
| Browser Support | ✅ Native | ❌ Needs bundler |
| Binding | Live bindings | Value copies |
// Named exports
export const PI = 3.14159;
export function add(a, b) { return a + b; }
// Default export
export default class Calculator { ... }
// Import
import Calculator, { PI, add } from "./math.js";
// Dynamic import (code splitting)
const module = await import("./heavy-module.js");
// Re-export
export { default as Button } from "./Button.js";
export * from "./utils.js";The Fetch API
// Basic GET
const response = await fetch("https://api.example.com/users");
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const data = await response.json();
// POST with JSON body
const result = await fetch("/api/users", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name: "Alice", email: "alice@example.com" }),
});
// AbortController (cancel requests)
const controller = new AbortController();
setTimeout(() => controller.abort(), 5000); // 5s timeout
try {
const response = await fetch("/api/slow", {
signal: controller.signal,
});
} catch (err) {
if (err.name === "AbortError") {
console.log("Request was cancelled");
}
}
// Streaming response
const response = await fetch("/api/large-file");
const reader = response.body.getReader();
while (true) {
const { done, value } = await reader.read();
if (done) break;
processChunk(value);
}Fetch Gotchas
fetchdoes NOT reject on HTTP errors (404, 500). Only network failures cause rejection.response.json()can only be called once (the body is consumed).- Cookies require
credentials: "include"for cross-origin requests.