|$ curl https://forge-ai.dev/api/markdown?path=docs/build-tools/parcel
$cat docs/parcel-bundler.md
updated Recently·25 min read·published
Parcel Bundler
Introduction
Parcel is a zero-configuration web bundler that requires no setup. It automatically detects and configures transforms, bundling, dev server, and production optimizations based on your project files. Parcel v2 is written in Rust for native performance.
Getting Started
getting-started.sh
Bash
| 1 | # Install Parcel |
| 2 | npm install --save-dev parcel |
| 3 | |
| 4 | # Add scripts to package.json |
| 5 | # "scripts": { |
| 6 | # "dev": "parcel src/index.html", |
| 7 | # "build": "parcel build src/index.html", |
| 8 | # "preview": "parcel dist/index.html" |
| 9 | # } |
| 10 | |
| 11 | # Start dev server (zero config!) |
| 12 | npm run dev |
| 13 | |
| 14 | # Production build |
| 15 | npm run build |
| 16 | |
| 17 | # Parcel auto-detects: |
| 18 | # - TypeScript (transpiles) |
| 19 | # - JSX/TSX (transpiles) |
| 20 | # - CSS/SCSS/Less (processes) |
| 21 | # - Images (optimizes, generates hashes) |
| 22 | # - JSON imports (parses) |
| 23 | # - HTML (processes references) |
Targets
Targets tell Parcel where to output bundles and what browsers/environments to support. Parcel v2 uses browserslist for browser targeting.
package.json
JSON
| 1 | // package.json — configure targets |
| 2 | { |
| 3 | "targets": { |
| 4 | "main": { |
| 5 | "context": "browser", |
| 6 | "outputFormat": "global", |
| 7 | "distDir": "dist" |
| 8 | }, |
| 9 | "module": { |
| 10 | "context": "browser", |
| 11 | "outputFormat": "esmodule", |
| 12 | "distDir": "dist/esm", |
| 13 | "isLibrary": true, |
| 14 | "sourceMap": true |
| 15 | }, |
| 16 | "node": { |
| 17 | "context": "node", |
| 18 | "outputFormat": "commonjs", |
| 19 | "distDir": "dist/node", |
| 20 | "isLibrary": true, |
| 21 | "engines": { "node": ">=18" } |
| 22 | } |
| 23 | }, |
| 24 | "browserslist": ">= 0.5%, last 2 versions, not dead" |
| 25 | } |
Code Splitting
code-splitting.ts
TypeScript
| 1 | // Parcel automatically code-splits on dynamic imports |
| 2 | // No configuration needed! |
| 3 | |
| 4 | // Route-based splitting |
| 5 | const Dashboard = React.lazy(() => import("./pages/Dashboard")); |
| 6 | const Settings = React.lazy(() => import("./pages/Settings")); |
| 7 | |
| 8 | // Conditional imports |
| 9 | async function loadPlugin(name: string) { |
| 10 | const plugin = await import(`./plugins/${name}`); |
| 11 | return plugin.default; |
| 12 | } |
| 13 | |
| 14 | // CSS splitting — each component's CSS is a separate chunk |
| 15 | import "./Button.css"; // Automatically split per import |
| 16 | |
| 17 | // Shared chunks — Parcel deduplicates shared modules |
| 18 | // between routes automatically |
| 19 | |
| 20 | // Named exports with dynamic import |
| 21 | const { formatDate, parseDate } = await import("./date-utils"); |
| 22 | // Only the used exports are bundled (tree-shaking) |
Monorepo Support
monorepo-package.json
JSON
| 1 | // package.json — workspace configuration |
| 2 | { |
| 3 | "workspaces": ["packages/*"], |
| 4 | "targets": { |
| 5 | "default": { |
| 6 | "distDir": "dist" |
| 7 | } |
| 8 | } |
| 9 | } |
| 10 | |
| 11 | // Parcel resolves imports across workspaces |
| 12 | // If package-a imports from package-b, Parcel |
| 13 | // uses the source directly (no build step needed) |
| 14 | // This enables instant HMR across packages |
ℹ
info
Parcel's workspace support means you can develop across packages with instant HMR. No need to build packages before importing them — Parcel resolves source files directly during development.
$Blueprint — Engineering Documentation·Section ID: BT-PC-01·Revision: 1.0