Claude Code के साथ Tree Shaking: bundle size घटाने की व्यावहारिक गाइड
Claude Code से tree shaking सुधारें: ESM, sideEffects, measurement, pitfalls और runnable examples.
Tree Shaking को आसान भाषा में समझें
Tree shaking production build में वह प्रक्रिया है जो final JavaScript या TypeScript bundle से unused exports हटाती है. सरल शब्दों में, जिस page को कोई code नहीं चाहिए, वह code browser तक नहीं भेजना है. इससे download, parse और execution का बोझ कम हो सकता है.
Bundler आपके मन की बात नहीं समझता.
वह import, export, package.json में sideEffects, CommonJS transform और module के top level पर चलने वाले code को देखकर फैसला करता है.
इसीलिए कई projects में unused helper bundle में रह जाता है, या sideEffects: false जोड़ते ही CSS या polyfill हट जाते हैं.
Claude Code से सबसे अच्छा परिणाम तब मिलता है जब task measurable हो. पहले current bundle size मापें, फिर CommonJS dependency, barrel file, default object export और side-effect files खोजें. उसके बाद छोटे scope में बदलाव करें और production build से verify करें. Masa यही flow Vite, React और Astro projects में use करता है जब bundle हल्का करना हो लेकिन UI न टूटे.
flowchart LR
A["source files"] --> B["ESM import/export graph"]
B --> C["bundler tree shaking"]
C --> D["minified production bundle"]
B --> E["side effects kept"]
E --> D
D --> F["measure bytes and gzip"]
Official docs को आधार बनाएं
हर bundler tree shaking को थोड़ा अलग तरीके से handle करता है. Production code बदलने से पहले official documentation देखें.
| Topic | Official link | Practical check |
|---|---|---|
| webpack | Tree Shaking | sideEffects, ESM, production build |
| webpack option | optimization.sideEffects | package flag कैसे पढ़ा जाता है |
| Rollup/Vite | Rollup treeshake | global moduleSideEffects बदलाव से बचें |
| Rollup detail | treeshake.moduleSideEffects | setup modules बचाकर रखें |
| esbuild | Tree shaking | ESM analysis और metafile measurement |
मुख्य बात यह है कि tree shaking random text deletion नहीं है. यह static ESM dependency graph पढ़ता है और code तभी हटाता है जब removal से runtime behavior बदलने का खतरा कम हो. CommonJS, namespace import, बड़ा default object और top-level CSS/polyfill import analysis को conservative बना देते हैं.
Claude Code के लिए prompt
पहला step investigation होना चाहिए, direct edit नहीं.
Large app में सीधे sideEffects: false लगाने से visual regression या missing setup छिप सकता है.
इस repository के production bundle में tree shaking कमजोर क्यों है, इसकी जांच करें.
पहले current build size, major chunks, heavy dependencies,
CommonJS dependencies और barrel exports को table में report करें.
हर proposed change के साथ risk, expected size impact और verification commands दें.
CSS, polyfills, analytics और global setup files हटनी नहीं चाहिए.
जब edit करना हो तो scope छोटा रखें.
इस pass में केवल src/utils और src/components/index.ts पर काम करें.
default object exports को named exports में बदलें और importing files update करें.
Change के बाद npm run build और bundle-size measurement चलाएं.
अगर public API बदले तो compatibility re-export रखें.
इस तरह Claude Code केवल code हटाने के बजाय behavior सुरक्षित रखते हुए size घटाता है.
Copy-paste runnable example
यह छोटा esbuild project default object export और named exports की तुलना करता है.
mkdir tree-shaking-lab
cd tree-shaking-lab
npm init -y
npm install --save-dev esbuild
mkdir src scripts
package.json को ऐसा रखें.
{
"name": "tree-shaking-lab",
"version": "1.0.0",
"type": "module",
"private": true,
"sideEffects": false,
"scripts": {
"measure": "node scripts/measure-tree-shaking.mjs"
},
"devDependencies": {
"esbuild": "^0.25.0"
}
}
कमज़ोर pattern में helpers एक object में छिपे हैं.
// src/bad-utils.ts
const utils = {
formatInr(amount: number): string {
return new Intl.NumberFormat("hi-IN", {
style: "currency",
currency: "INR"
}).format(amount);
},
heavyReport(rows: number[]): string {
const body = rows.map((row) => `row:${row}`).join("\n");
return `report\n${body}\n${"=".repeat(4000)}`;
},
debugOnly(): string {
return "debug:" + "x".repeat(4000);
}
};
export default utils;
बेहतर pattern में हर function अलग export है.
// src/good-utils.ts
export function formatInr(amount: number): string {
return new Intl.NumberFormat("hi-IN", {
style: "currency",
currency: "INR"
}).format(amount);
}
export function heavyReport(rows: number[]): string {
const body = rows.map((row) => `row:${row}`).join("\n");
return `report\n${body}\n${"=".repeat(4000)}`;
}
export function debugOnly(): string {
return "debug:" + "x".repeat(4000);
}
दो entry files बनाएं.
// src/bad-entry.ts
import utils from "./bad-utils";
console.log(utils.formatInr(1200));
// src/good-entry.ts
import { formatInr } from "./good-utils";
console.log(formatInr(1200));
Measurement script जोड़ें.
// scripts/measure-tree-shaking.mjs
import { gzipSync } from "node:zlib";
import { build } from "esbuild";
async function bundle(entryPoint) {
const result = await build({
entryPoints: [entryPoint],
bundle: true,
minify: true,
format: "esm",
treeShaking: true,
write: false,
metafile: true
});
const code = result.outputFiles[0].text;
return {
entryPoint,
bytes: Buffer.byteLength(code),
gzipBytes: gzipSync(code).byteLength,
inputs: Object.keys(result.metafile.inputs)
};
}
const rows = await Promise.all([
bundle("src/bad-entry.ts"),
bundle("src/good-entry.ts")
]);
console.table(rows);
अब चलाएं:
npm run measure
Real project में केवल raw bytes न देखें. Chunk names, gzip, Brotli और Lighthouse Total Blocking Time भी record करें. कौन सी dependency graph में बची है, यह देखने के लिए bundle analysis guide के साथ compare करें.
Use case 1: utility modules साफ करना
सबसे तेज़ gain अक्सर utils/index.ts या helpers.ts में मिलता है.
Date, currency, CSV, Markdown और debug tools एक ही file में हों तो एक function import करने पर भी analysis मुश्किल हो जाती है.
Claude Code को यह task दें.
src/utils को purpose के हिसाब से split करें.
Consumers को named imports पर बदलें और index.ts से केवल public helpers re-export करें.
अगर top-level Date.now, console, localStorage या fetch calls हों,
तो उन्हें functions के अंदर move करें.
बेहतर shape यह है.
// src/utils/formatDate.ts
export function formatDate(date: Date, locale = "hi-IN"): string {
return new Intl.DateTimeFormat(locale).format(date);
}
// src/utils/index.ts
export { formatDate } from "./formatDate";
export { formatInr } from "./formatInr";
// src/pages/invoice.ts
import { formatInr } from "../utils/formatInr";
export function invoiceLabel(total: number): string {
return `कुल: ${formatInr(total)}`;
}
Barrel file हमेशा खराब नहीं होती.
समस्या तब आती है जब वह setup चलाती है, बहुत सारे export * from chain करती है, या unrelated modules को graph में खींचती है.
Application code में direct import बेहतर है; public library में compatibility के लिए पतला barrel रखा जा सकता है.
Use case 2: internal UI library
Internal UI package में import { Button } from "@acme/ui" कभी-कभी Modal, DatePicker, Chart, icons, CSS और theme setup भी evaluate कर देता है.
अगर सभी components एक बड़े entry से जुड़े हैं, named exports अकेले काफी नहीं होते.
Subpath entries दें.
{
"name": "@acme/ui",
"type": "module",
"sideEffects": [
"**/*.css",
"./src/setup-theme.ts"
],
"exports": {
".": "./dist/index.js",
"./button": "./dist/button.js",
"./modal": "./dist/modal.js"
}
}
Consumer केवल ज़रूरी entry import करे.
import { Button } from "@acme/ui/button";
sideEffects: false बिना audit के न लगाएं.
यह React useEffect की बात नहीं है; यह बताता है कि module import होते ही कोई ज़रूरी बाहरी effect चलता है या नहीं.
CSS, polyfills, custom element registration और theme setup को जरूरत हो तो sideEffects array में रखें.
Use case 3: admin-only heavy dependencies lazy-load करना
Markdown processor, PDF generator, charts और rich text editor public first load में अक्सर जरूरी नहीं होते. Unused exports हटाने के लिए tree shaking और initial chunk से heavy features हटाने के लिए code splitting साथ इस्तेमाल करें.
// src/features/admin/loadMarkdownPreview.ts
export async function renderMarkdown(markdown: string): Promise<string> {
const [{ unified }, remarkParse, remarkHtml] = await Promise.all([
import("unified"),
import("remark-parse"),
import("remark-html")
]);
const file = await unified()
.use(remarkParse.default)
.use(remarkHtml.default)
.process(markdown);
return String(file);
}
Dynamic import tree shaking का replacement नहीं है. यह code को later chunk में भेजता है; अगर lazy chunk के अंदर CommonJS heavy है, तो वह chunk फिर भी बड़ा रहेगा.
Use case 4: npm package publish करना
Library publish करते समय consumers के bundler को ESM entry दें जिसे वह analyze कर सके.
केवल CommonJS main expose करने से frontend users को अच्छा tree shaking मिलना मुश्किल हो सकता है.
{
"name": "@masa/formatters",
"type": "module",
"sideEffects": false,
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
},
"./currency": {
"types": "./dist/currency.d.ts",
"import": "./dist/currency.js"
}
}
}
sideEffects: false तभी लिखें जब package सच में import-time side effects से free हो.
CSS import, polyfill install, global registration या analytics start होता है तो files को sideEffects array में list करें.
Common pitfalls और failure cases
| Pitfall | Symptom | Fix |
|---|---|---|
| Babel या TypeScript बहुत जल्दी CommonJS emit करता है | unused exports रहते हैं | bundler तक ESM रखें |
sideEffects: false बहुत broad है | CSS या polyfill गायब | side-effect files list करें |
| default object export | unused helpers भी रहते हैं | named exports में split करें |
| barrel file top-level setup चलाती है | एक component import भी भारी | barrel केवल re-export करे |
| dev build measure करना | size misleading | production, minify, gzip compare करें |
global moduleSideEffects: false | setup code हट जाता है | package/file level verify करें |
| namespace import | analysis conservative | specific named imports use करें |
सबसे खतरनाक failure subtle CSS regression है. DOM existence test pass हो सकता है, फिर भी styling missing हो सकती है. performance optimization की तरह build output, key screens और visible behavior को साथ में verify करें.
CI में bundle budget लगाएं
एक बार size घटाने के बाद अगली dependency update में bundle फिर बढ़ सकता है. इसलिए gzip budget CI में रखें.
// scripts/check-bundle-budget.mjs
import { statSync } from "node:fs";
import { gzipSync } from "node:zlib";
import { readFileSync } from "node:fs";
const file = "dist/assets/index.js";
const maxGzipBytes = 160 * 1024;
const raw = readFileSync(file);
const gzipBytes = gzipSync(raw).byteLength;
if (gzipBytes > maxGzipBytes) {
console.error(`Bundle budget exceeded: ${gzipBytes} > ${maxGzipBytes}`);
process.exit(1);
}
console.log({
file,
bytes: statSync(file).size,
gzipBytes
});
Production build के बाद चलाएं.
npm run build
node scripts/check-bundle-budget.mjs
पहला budget बहुत idealistic न रखें. Current gzip size के पास थोड़ा margin रखें और PR में size बढ़े तो reason मांगें. अगर bundle कम होने के बाद भी app slow है, तो speed optimization guide के साथ images, fonts, API latency और hydration भी देखें.
Claude Code review checklist
इस tree-shaking PR को review करें.
1. क्या unused exports production bundle से सच में हटे?
2. क्या CSS, polyfills और registration files बची रहीं?
3. क्या ESM bundler analysis तक preserved रहा?
4. क्या direct imports ने public API compatibility तोड़ी?
5. build, tests, key screens और bundle budget के results क्या हैं?
हर answer में file names और command evidence दें.
यह checklist refactor को publishable quality review में बदल देती है.
Masa के projects में sideEffects change तब तक complete नहीं माना जाता जब तक login, billing और admin screens खोलकर style और setup behavior verify न हो जाए.
Monetization और consulting angle
Tree shaking केवल engineering cleanup नहीं है. हल्का first load article पढ़ने, product page खोलने, signup form भरने और consulting form submit करने से पहले friction घटाता है. ClaudeCodeLab जैसे technical media में heavy code example page या slow landing page ads और inquiries दोनों के conversion path को कमजोर करता है.
ClaudeCodeLab Vite, Next.js, Astro और internal UI libraries के bundles audit कर सकता है, फिर tree shaking fixes, code splitting और CI budget में बदल सकता है.
Focused consultation के लिए package.json, build config, key routes और recent bundle report तैयार रखें.
Summary
Tree shaking तब काम करता है जब ESM, accurate sideEffects, controlled side effects और continuous measurement साथ हों.
Claude Code को छोटा, verifiable task दें: inspect, split, imports update, measure और failure cases review.
मैंने इस article का minimal sample locally npm run measure से चलाया और bad entry तथा good entry के output sizes अलग देखे.
Real projects में numbers dependencies और build config पर depend करते हैं, इसलिए हमेशा अपने production build में मापें और पहले लिखें कि कौन से side effects बचाने जरूरी हैं.
मुफ़्त PDF: Claude Code cheatsheet
Email डालें और commands, review habits तथा safe workflow वाली एक-page PDF पाएँ.
हम आपका data सुरक्षित रखते हैं और spam नहीं भेजते.
लेखक के बारे में
Masa
Claude Code workflow और team adoption पर काम करने वाला engineer.
संबंधित लेख
Claude Code Permission Receipt Pattern: scope, proof और rollback लिखना
Claude Code के लिए permission receipt: allowed actions, approval boundary, verification commands, rollback note और revenue CTA checks।
Claude Code और Codex के लिए सुरक्षित Agent Harness: permissions, verification और rollback
Claude Code और Codex agents के लिए सुरक्षित harness: permissions, plan, verification और rollback.
Claude Code Subagents गाइड: article और code work को सुरक्षित तरीके से delegate करें
Claude Code subagents से article और code work बांटें: delegation rules, prompts, pitfalls, checklist और examples.