React Best Practices
ryokun6/ryos
React performance optimization guidelines from Vercel Engineering (vercel-labs/agent-skills).
JavaScript bundle size auditor and budget enforcer. An agent skill from LeoYeAI/openclaw-master-skills.
$ npx skills add LeoYeAI/openclaw-master-skills --skill phy-bundle-size-audit -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install LeoYeAI/openclaw-master-skills phy-bundle-size-audit --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/LeoYeAI/openclaw-master-skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/phy-bundle-size-audit .claude/skills/phy-bundle-size-audit && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "phy-bundle-size-audit" agent skill from https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/phy-bundle-size-audit into .claude/skills/phy-bundle-size-audit/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "phy-bundle-size-audit", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/phy-bundle-size-auditType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add LeoYeAI/openclaw-master-skills --skill phy-bundle-size-audit -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install LeoYeAI/openclaw-master-skills phy-bundle-size-audit --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/LeoYeAI/openclaw-master-skills.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/phy-bundle-size-audit .agents/skills/phy-bundle-size-audit && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "phy-bundle-size-audit" agent skill from https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/phy-bundle-size-audit into .agents/skills/phy-bundle-size-audit/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "phy-bundle-size-audit", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add LeoYeAI/openclaw-master-skills --skill phy-bundle-size-audit -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install LeoYeAI/openclaw-master-skills phy-bundle-size-audit --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/LeoYeAI/openclaw-master-skills.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/phy-bundle-size-audit .cursor/skills/phy-bundle-size-audit && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "phy-bundle-size-audit" agent skill from https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/phy-bundle-size-audit into .cursor/skills/phy-bundle-size-audit/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "phy-bundle-size-audit", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/LeoYeAI/openclaw-master-skills.git --path skills/phy-bundle-size-audit--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add LeoYeAI/openclaw-master-skills --skill phy-bundle-size-audit -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install LeoYeAI/openclaw-master-skills phy-bundle-size-audit --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/LeoYeAI/openclaw-master-skills.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/phy-bundle-size-audit .gemini/skills/phy-bundle-size-audit && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "phy-bundle-size-audit" agent skill from https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/phy-bundle-size-audit into .gemini/skills/phy-bundle-size-audit/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "phy-bundle-size-audit", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install LeoYeAI/openclaw-master-skills phy-bundle-size-auditInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add LeoYeAI/openclaw-master-skills --skill phy-bundle-size-audit -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/LeoYeAI/openclaw-master-skills.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/phy-bundle-size-audit .github/skills/phy-bundle-size-audit && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "phy-bundle-size-audit" agent skill from https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/phy-bundle-size-audit into .github/skills/phy-bundle-size-audit/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "phy-bundle-size-audit", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add LeoYeAI/openclaw-master-skills --skill phy-bundle-size-audit -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install LeoYeAI/openclaw-master-skills phy-bundle-size-audit --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/LeoYeAI/openclaw-master-skills.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/phy-bundle-size-audit .opencode/skills/phy-bundle-size-audit && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "phy-bundle-size-audit" agent skill from https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/phy-bundle-size-audit into .opencode/skills/phy-bundle-size-audit/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "phy-bundle-size-audit", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
phy-bundle-size-auditJavaScript bundle size auditor and budget enforcer. An agent skill from LeoYeAI/openclaw-master-skills.
Phy Bundle Size Audit is an agent skill from LeoYeAI/openclaw-master-skills. JavaScript bundle size auditor and budget enforcer. Parses webpack stats JSON, Vite bundle report, Rollup output, or Next.js build output to identify largest chunks, flag chunks that exceed configurable size budgets, detect duplicate dependencies across chunks, find treeshaking failures (packages that should be side-effect-free but aren't), and generate CI fail-gate commands. Outputs a GitHub PR annotation-ready summary with per-chunk size, gzip estimate, and actionable optimization suggestions. Zero external API…
Its SKILL.md is about 4.9k tokens, which your agent loads only when the skill is triggered. The skill folder holds 1 other file (for example `_meta.json`).
It sits in Frontend & Design, covering Web performance. It works with webpack, Vite, Next.js and GitHub. The repository describes itself as: 🧠 Curated collection of 1209+ best OpenClaw skills — weekly updated by MyClaw.ai. The licence is Apache-2.0.
6 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit e5199b5. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
python3npmnpxFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md. Its commands use npm and npx, which can reach the network depending on how they are called.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Phy Bundle Size Audit loads about 4.9k tokens when it runs. Until then it costs about 176 tokens; SKILL.md has 411 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from LeoYeAI/openclaw-master-skills at commit e5199b5, republished under its Apache-2.0 licence (© LeoYeAI). 411 words, ~4,937 tokens.
.claude/skills/phy-bundle-size-audit/SKILL.md (or your agent's skills folder). This skill also uses 1 other file; get the full folder from GitHub.You added one import. Your Lighthouse score dropped 12 points. Your LCP went from 1.8s to 3.1s.
This skill parses your bundler's output — webpack stats JSON, Vite build report, or Next.js .next/ directory — identifies the largest chunks, finds which packages are bloating them, detects treeshaking failures, and gives you the exact code changes to fix it.
Supports webpack, Vite, Rollup, Next.js. Zero external API.
# Option 1: Webpack stats JSON (most detailed)
webpack --profile --json > stats.json
/bundle-size-audit stats.json
# Option 2: Vite build (auto-detected)
vite build
/bundle-size-audit dist/
# Option 3: Next.js build (auto-detected)
next build
/bundle-size-audit .next/
# Option 4: Rollup stats
rollup -c --bundleConfigAsCjs
/bundle-size-audit rollup-stats.json
# Option 5: Set size budgets
/bundle-size-audit --max-chunk 250kb --max-initial 500kb
# Option 6: Focus on a specific chunk or package
/bundle-size-audit --chunk main --package lodash
# Option 7: Generate CI fail-gate only
/bundle-size-audit --ci-configpython3 -c "
import os, json
from pathlib import Path
# Priority order for detection
checks = [
('webpack stats', ['stats.json', 'webpack-stats.json', 'build/stats.json']),
('Next.js', ['.next/build-manifest.json', '.next/server/pages-manifest.json']),
('Vite', ['dist/', 'dist/assets/']),
('Rollup', ['dist/', 'build/']),
('Create React App', ['build/static/js/', 'build/asset-manifest.json']),
]
found = []
for name, paths in checks:
for p in paths:
if os.path.exists(p):
found.append((name, p))
break
if found:
for name, path in found:
size = 0
if os.path.isfile(path):
size = os.path.getsize(path)
print(f'Detected {name}: {path} ({size:,} bytes)')
else:
# Directory — count JS files
js_files = list(Path(path).rglob('*.js'))
total = sum(f.stat().st_size for f in js_files)
print(f'Detected {name}: {path}/ ({len(js_files)} JS files, {total/1024:.0f} KB total)')
else:
print('No build artifacts found.')
print('Run your build first:')
print(' webpack --profile --json > stats.json')
print(' vite build')
print(' next build')
"import json
from pathlib import Path
def parse_webpack_stats(stats_path):
"""Parse webpack stats.json into chunk/asset summary."""
with open(stats_path) as f:
stats = json.load(f)
assets = []
for asset in stats.get('assets', []):
name = asset['name']
size = asset['size']
# Only JS and CSS assets
if not any(name.endswith(ext) for ext in ['.js', '.css', '.mjs']):
continue
assets.append({
'name': name,
'size': size,
'size_kb': round(size / 1024, 1),
'gzip_estimate_kb': round(size / 1024 * 0.3, 1), # ~30% compression typical
'chunks': asset.get('chunkNames', []),
'initial': asset.get('isOverSizeLimit', False),
})
# Sort by size desc
assets.sort(key=lambda x: x['size'], reverse=True)
# Module analysis — find largest modules
modules = []
for module in stats.get('modules', []):
if module.get('size', 0) > 10 * 1024: # >10KB only
modules.append({
'name': module.get('name', 'unknown'),
'size': module.get('size', 0),
'size_kb': round(module.get('size', 0) / 1024, 1),
'reasons': [r.get('moduleName', '') for r in module.get('reasons', [])[:3]],
})
modules.sort(key=lambda x: x['size'], reverse=True)
return assets, modules[:50] # top 50 modules
def parse_webpack_chunks(stats_path):
"""Identify chunks and their composition."""
with open(stats_path) as f:
stats = json.load(f)
chunks = []
for chunk in stats.get('chunks', []):
chunks.append({
'id': chunk.get('id'),
'names': chunk.get('names', []),
'size': chunk.get('size', 0),
'size_kb': round(chunk.get('size', 0) / 1024, 1),
'initial': chunk.get('initial', False),
'entry': chunk.get('entry', False),
'module_count': len(chunk.get('modules', [])),
'files': chunk.get('files', []),
})
chunks.sort(key=lambda x: x['size'], reverse=True)
return chunksimport os
from pathlib import Path
def parse_dist_directory(dist_path):
"""Parse build output directory for Vite/CRA/Rollup."""
js_dir = Path(dist_path)
# Find all JS files
js_files = []
for fpath in js_dir.rglob('*.js'):
if 'node_modules' in str(fpath):
continue
size = fpath.stat().st_size
js_files.append({
'name': str(fpath.relative_to(dist_path)),
'path': str(fpath),
'size': size,
'size_kb': round(size / 1024, 1),
'gzip_estimate_kb': round(size / 1024 * 0.3, 1),
'is_chunk': 'chunk' in fpath.name.lower() or fpath.parent.name == 'assets',
'is_vendor': 'vendor' in fpath.name.lower(),
})
js_files.sort(key=lambda x: x['size'], reverse=True)
# CSS files
css_files = []
for fpath in js_dir.rglob('*.css'):
size = fpath.stat().st_size
css_files.append({
'name': str(fpath.relative_to(dist_path)),
'size_kb': round(size / 1024, 1),
})
return js_files, css_files
def estimate_gzip(size_bytes):
"""Estimate gzip size. JS typically compresses 65-75%."""
return round(size_bytes * 0.30 / 1024, 1)# Next.js provides build-manifest.json and .next/analyze/ if ANALYZE=true
python3 -c "
import json, os
from pathlib import Path
next_dir = Path('.next')
if not next_dir.exists():
print('No .next/ directory found. Run: next build')
exit(1)
# Read build-manifest
manifest_path = next_dir / 'build-manifest.json'
if manifest_path.exists():
manifest = json.loads(manifest_path.read_text())
# Collect all JS files referenced
all_files = set()
for page, files in manifest.get('pages', {}).items():
for f in files:
all_files.add(f)
print(f'Pages: {len(manifest.get(\"pages\", {}))}')
print(f'Unique JS chunks: {len(all_files)}')
# Read static/chunks/
chunks_dir = next_dir / 'static' / 'chunks'
if chunks_dir.exists():
chunks = []
for fpath in chunks_dir.rglob('*.js'):
size = fpath.stat().st_size
chunks.append((fpath.name, size))
chunks.sort(key=lambda x: x[1], reverse=True)
total = sum(s for _, s in chunks)
print(f'\\nTotal chunks: {len(chunks)} ({total/1024:.0f} KB)')
print('\\nTop 10 chunks:')
for name, size in chunks[:10]:
print(f' {name}: {size/1024:.1f} KB (~{size*0.3/1024:.1f} KB gzip)')
"import re
from pathlib import Path
def find_duplicate_modules(stats_path):
"""Find the same package duplicated across chunks (common with npm hoisting issues)."""
with open(stats_path) as f:
stats = json.load(f)
# Track package versions seen in different chunks
package_chunks = {}
for module in stats.get('modules', []):
name = module.get('name', '')
# Extract package name from ./node_modules/package/...
match = re.search(r'node_modules/(@[^/]+/[^/]+|[^/]+)', name)
if not match:
continue
pkg = match.group(1)
# Which chunks contain this module?
chunk_ids = module.get('chunks', [])
if pkg not in package_chunks:
package_chunks[pkg] = set()
package_chunks[pkg].update(chunk_ids)
# Find packages in 3+ chunks (likely duplicated)
duplicates = {
pkg: chunks
for pkg, chunks in package_chunks.items()
if len(chunks) >= 3
}
return sorted(duplicates.items(), key=lambda x: len(x[1]), reverse=True)
def find_heavy_packages(stats_path, threshold_kb=50):
"""Find packages over threshold_kb in the bundle."""
with open(stats_path) as f:
stats = json.load(f)
package_sizes = {}
for module in stats.get('modules', []):
name = module.get('name', '')
size = module.get('size', 0)
match = re.search(r'node_modules/(@[^/]+/[^/]+|[^/]+)', name)
if not match:
continue
pkg = match.group(1)
package_sizes[pkg] = package_sizes.get(pkg, 0) + size
heavy = {
pkg: size
for pkg, size in package_sizes.items()
if size / 1024 > threshold_kb
}
return sorted(heavy.items(), key=lambda x: x[1], reverse=True)# Known packages with treeshaking issues + their lightweight alternatives
TREESHAKING_ALERTS = {
'lodash': {
'issue': 'lodash CommonJS bundle cannot be treeshaken. Full ~70KB always included.',
'fix': 'Use lodash-es OR import individual functions: import debounce from "lodash/debounce"',
'savings': '60-68 KB',
},
'moment': {
'issue': 'moment.js includes all 160+ locale files (~290KB). Treeshaking does NOT work.',
'fix': 'Replace with date-fns (treeshakeable, ~13KB used) or dayjs (~2KB)',
'savings': '270-290 KB',
},
'antd': {
'issue': 'antd without babel-plugin-import bundles the entire component library.',
'fix': 'Add babel-plugin-import or use antd/es/{component} imports',
'savings': '500+ KB',
},
'@mui/material': {
'issue': 'MUI default import (@mui/material) may bundle unused components.',
'fix': 'Use named imports: import Button from "@mui/material/Button"',
'savings': '100-200 KB',
},
'rxjs': {
'issue': 'import { Observable } from "rxjs" bundles the full library if not configured.',
'fix': 'Use rxjs/operators and ensure sideEffects: false in your bundler config',
'savings': '50-100 KB',
},
'aws-sdk': {
'issue': 'aws-sdk v2 cannot be treeshaken — it bundles every AWS service.',
'fix': 'Migrate to @aws-sdk/client-{service} (v3, fully treeshakeable)',
'savings': '200+ KB',
},
'firebase': {
'issue': 'firebase/app includes all modules unless modular API is used.',
'fix': 'Use modular imports: import { getAuth } from "firebase/auth"',
'savings': '100-400 KB',
},
}
def check_treeshaking_failures(stats_path):
"""Find packages known to have treeshaking issues."""
with open(stats_path) as f:
stats = json.load(f)
found_packages = set()
for module in stats.get('modules', []):
name = module.get('name', '')
for pkg in TREESHAKING_ALERTS:
if f'node_modules/{pkg}' in name or f'node_modules/{pkg}/' in name:
found_packages.add(pkg)
alerts = []
for pkg in found_packages:
alerts.append({
'package': pkg,
**TREESHAKING_ALERTS[pkg]
})
return alertsDEFAULT_BUDGETS = {
'initial_js': 250 * 1024, # 250 KB initial JS (gzipped target)
'initial_css': 50 * 1024, # 50 KB initial CSS
'any_chunk': 500 * 1024, # 500 KB max any single chunk
'total_js': 1000 * 1024, # 1 MB total JS
}
def check_budgets(assets, custom_budgets=None):
"""Check assets against size budgets."""
budgets = {**DEFAULT_BUDGETS, **(custom_budgets or {})}
violations = []
total_js = sum(a['size'] for a in assets if a['name'].endswith('.js'))
initial_js = sum(
a['size'] for a in assets
if a['name'].endswith('.js') and a.get('initial', False)
)
if initial_js > budgets['initial_js']:
violations.append({
'type': 'INITIAL_JS',
'actual_kb': round(initial_js / 1024, 1),
'budget_kb': round(budgets['initial_js'] / 1024, 1),
'overage_kb': round((initial_js - budgets['initial_js']) / 1024, 1),
'severity': 'HIGH',
})
for asset in assets:
if asset['size'] > budgets['any_chunk']:
violations.append({
'type': 'CHUNK_SIZE',
'chunk': asset['name'],
'actual_kb': asset['size_kb'],
'budget_kb': round(budgets['any_chunk'] / 1024, 1),
'overage_kb': round((asset['size'] - budgets['any_chunk']) / 1024, 1),
'severity': 'MEDIUM',
})
if total_js > budgets['total_js']:
violations.append({
'type': 'TOTAL_JS',
'actual_kb': round(total_js / 1024, 1),
'budget_kb': round(budgets['total_js'] / 1024, 1),
'overage_kb': round((total_js - budgets['total_js']) / 1024, 1),
'severity': 'LOW',
})
return violations## Bundle Size Audit
Project: my-app | Bundler: webpack 5.89 | Build: production
---
### Size Summary
| Chunk | Raw | Gzip Est. | Type | Status |
|-------|-----|-----------|------|--------|
| main.abc123.js | 312 KB | 94 KB | initial | 🔴 OVER BUDGET |
| vendor.def456.js | 489 KB | 147 KB | initial | 🟠 WARNING |
| dashboard.ghi789.js | 95 KB | 29 KB | async | ✅ OK |
| settings.jkl012.js | 41 KB | 12 KB | async | ✅ OK |
**Total JS: 937 KB (281 KB gzipped)**
**Initial JS: 801 KB — 🔴 EXCEEDS 500 KB budget (301 KB over)**
---
### 🔴 Budget Violations
| Violation | Actual | Budget | Overage | Impact |
|-----------|--------|--------|---------|--------|
| Initial JS | 801 KB | 500 KB | +301 KB | Slow LCP, fails Core Web Vitals |
| main.js chunk | 312 KB | 250 KB | +62 KB | Blocking parse time |
---
### 🔴 Treeshaking Failures (High Impact)
**lodash** — 68 KB that could be 4 KBProblem: import { debounce } from 'lodash' bundles the entire library (CommonJS) Fix: import debounce from 'lodash/debounce' OR: replace with lodash-es Savings: ~64 KB
**moment** — 287 KB that could be 13 KBProblem: moment.js bundles all 160+ locale files Fix: Replace with date-fns (treeshakeable): import { format, parseISO } from 'date-fns' Savings: ~274 KB
---
### 🟠 Duplicate Dependencies (Same Package in 3+ Chunks)
Package Chunk Count Issue react-dom 6 chunks Included in vendor + 5 async chunks lodash 4 chunks Not deduplicated — CommonJS import in multiple files styled-components 3 chunks Multiple versions? Run: npm ls styled-components
**Fix:** Ensure these packages are in `optimization.splitChunks.cacheGroups.vendor`:
```js
// webpack.config.js
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/](react|react-dom|lodash-es)[\\/]/,
name: 'vendors',
chunks: 'all',
},
},
},
},| Package | Size | % of Bundle | Treeshakeable? |
|---|---|---|---|
| moment | 287 KB | 30.6% | ❌ No |
| lodash | 68 KB | 7.3% | ⚠️ Only with lodash-es |
| @mui/icons-material | 61 KB | 6.5% | ✅ Yes, if named imports |
| draft-js | 58 KB | 6.2% | ⚠️ Partial |
| highlight.js | 49 KB | 5.2% | ✅ Use registerLanguage() |
| ... |
#1 — Replace moment.js → date-fns (~274 KB savings)
npm uninstall moment
npm install date-fns
# Then: find . -name "*.ts" | xargs grep -l "from 'moment'"
# Replace: import { format } from 'date-fns'#2 — Fix lodash imports (~64 KB savings)
# Find all lodash imports:
grep -r "from 'lodash'" src/ --include="*.ts" --include="*.tsx"
# Change to: import debounce from 'lodash/debounce'
# OR install lodash-es: npm install lodash-es#3 — Lazy-load dashboard route (~95 KB off initial bundle)
// Before:
import Dashboard from './Dashboard'
// After:
const Dashboard = React.lazy(() => import('./Dashboard'))Estimated total savings: 433 KB raw / ~130 KB gzipped After fixes: Initial JS ~368 KB ✅ (under 500 KB budget)
Add to your CI pipeline to prevent bundle regressions:
# Option 1: bundlesize (npm package)
npx bundlesize
# Requires .bundlesizerc in repo:
# {"files": [{"path": "dist/js/*.js", "maxSize": "250 kB"}]}
# Option 2: size-limit
npx size-limit
# Requires .size-limit.json:
# [{"path": "dist/js/main.*.js", "limit": "250 KB"}]
# Option 3: Pure bash check (no npm package needed)
python3 -c "
import os, sys
from pathlib import Path
budgets = {
'dist/js/main': 250 * 1024,
'dist/js/vendor': 500 * 1024,
}
failed = False
for pattern, limit in budgets.items():
matches = list(Path('.').glob(f'{pattern}*.js'))
for f in matches:
size = f.stat().st_size
if size > limit:
print(f'FAIL: {f} is {size/1024:.0f} KB (limit: {limit/1024:.0f} KB)')
failed = True
else:
print(f'PASS: {f} is {size/1024:.0f} KB')
sys.exit(1 if failed else 0)
"Add to .github/workflows/build.yml:
- name: Check bundle size
run: python3 scripts/check-bundle-size.pyFor interactive visualization:
# Install once
npm install --save-dev webpack-bundle-analyzer
# Generate report
npx webpack-bundle-analyzer stats.json dist/ --no-open --report report.html
# Opens interactive treemap — look for unexpectedly large node_modules blocks
# Next.js
ANALYZE=true next build
# Opens browser with interactive bundle analysis
---
## Quick Mode Output
Bundle Audit: my-app (webpack 5, production)
Initial JS: 801 KB gzip → 🔴 OVER 500 KB budget Total JS: 937 KB (281 KB gzip) Chunks: 4 (2 initial, 2 async)
🔴 moment.js: 287 KB — replace with date-fns → -274 KB 🔴 lodash: 68 KB — fix imports → -64 KB 🟠 @mui/icons-material: 61 KB — use named imports 🟡 6 duplicate react-dom instances — fix splitChunks
Estimated savings: 433 KB → Initial JS drops to ~368 KB ✅ Run /bundle-size-audit --ci-config for CI fail-gate
© LeoYeAI, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 1 other file in skills/phy-bundle-size-audit of LeoYeAI/openclaw-master-skills.
Open the folder on GitHubat commit e5199b5
Phy Bundle Size Audit next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Phy Bundle Size Audit this skillLeoYeAI/openclaw-master-skills | 2.2k | — | ~4.9k | Automated safety check: Pass | Apache-2.0 | |
| React Best Practicesryokun6/ryos | 1.3k | — | ~2k | Automated safety check: Pass | MIT | |
| Frontend Engineer Workflownanocoai/nanoclaw | 31k | — | ~1.5k | Automated safety check: Pass | MIT | |
| Igniteui Wc Optimize Bundle SizeIgniteUI/igniteui-webcomponents | 170 | — | ~3.6k | Automated safety check: Pass | MIT | |
| npm Package Comparatortinyfish-io/tinyfish-cookbook | 2.2k | — | ~2k | Automated safety check: Pass | MIT | |
| Nextjs Bundle Optimizerpproenca/dot-skills | 215 | — | ~1.5k | Automated safety check: Pass | MIT |
ryokun6/ryos
React performance optimization guidelines from Vercel Engineering (vercel-labs/agent-skills).
nanocoai/nanoclaw
Sets a build, test and verify routine for web projects: write typed, accessible code and never call work done until it is checked in a real browser with screenshots.
IgniteUI/igniteui-webcomponents
Reduce application bundle size with Ignite UI Web Components by registering only needed components via named imports from the package root with defineComponents instead of defineAllComponents…
tinyfish-io/tinyfish-cookbook
Compare two or more npm packages side by side using live data — downloads, bundle size, GitHub stars, last update, known vulnerabilities, and community sentiment.
pproenca/dot-skills
Next.js 16 bundle-size and build-time optimization — runs a data-driven iteration loop: measure baseline → analyze top offenders → apply ONE recipe → re-measure → verify nothing broke (build + types…
ericrisco/rsc-harness
A skill your agent uses when building, reviewing, testing, securing, or optimizing a Next.js App Router app: Server vs Client boundaries, use server actions, route handlers, the v15 vs v16 use cache…
LeoYeAI/openclaw-master-skills
Manages pipelines on a DevOps quality and efficiency platform through its OpenAPI: list workspaces and templates, create, update, run and cancel pipelines, and read run records.
LeoYeAI/openclaw-master-skills
Patches OpenClaw's Feishu extension so an edited document triggers an isolated agent session that reads the doc and replies inline, turning it into a live chat space.
LeoYeAI/openclaw-master-skills
Multi-context memory management system for OpenClaw agents with group-isolated storage, global shared memory, workspace organization, and group-specific skills isolation.
LeoYeAI/openclaw-master-skills
Runs a brand's AI-search visibility work end to end: diagnosing how AI platforms represent it, repositioning it, producing AI-optimized content and monitoring ongoing mentions.
LeoYeAI/openclaw-master-skills
Installs and authenticates the gws CLI, then automates Gmail, Drive, Sheets, Calendar, Docs, Chat and Tasks with ready-made recipes, persona bundles and security audits.
LeoYeAI/openclaw-master-skills
Runs four advisor roles, a fitness coach, nutritionist, data analyst and TCM practitioner, to build a health profile and track workouts, diet and wellness over time.
Works with
Categories
JavaScript bundle size auditor and budget enforcer. An agent skill from LeoYeAI/openclaw-master-skills. Phy Bundle Size Audit is an agent skill from LeoYeAI/openclaw-master-skills. JavaScript bundle size auditor and budget enforcer.
Phy Bundle Size Audit fits situations like: bundle too large; bundle analyzer; /bundle-size-audit.
Run `npx skills add LeoYeAI/openclaw-master-skills --skill phy-bundle-size-audit -a claude-code`. Or copy the skill folder (skills/phy-bundle-size-audit in LeoYeAI/openclaw-master-skills) into .claude/skills/phy-bundle-size-audit in your project. Claude Code loads it when a task matches its description.
Run `npx skills add LeoYeAI/openclaw-master-skills --skill phy-bundle-size-audit -a codex`. Or copy the skill folder (skills/phy-bundle-size-audit in LeoYeAI/openclaw-master-skills) into .agents/skills/phy-bundle-size-audit in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add LeoYeAI/openclaw-master-skills --skill phy-bundle-size-audit -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/phy-bundle-size-audit, .gemini/skills/phy-bundle-size-audit, .github/skills/phy-bundle-size-audit and .opencode/skills/phy-bundle-size-audit in your project.
Going by SKILL.md and its folder, Phy Bundle Size Audit needs the command-line tools its instructions call (python3, npm and npx). Our summary lists: Python 3.
SKILL.md contains no URLs. Its commands use npm and npx, which can reach the network depending on how they are called. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Phy Bundle Size Audit is published under the Apache-2.0 licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.
About 4.9k tokens (SKILL.md is roughly 20k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Phy Bundle Size Audit: React Best Practices (ryokun6/ryos, 1.3k stars), Frontend Engineer Workflow (nanocoai/nanoclaw, 31k stars), Igniteui Wc Optimize Bundle Size (IgniteUI/igniteui-webcomponents, 170 stars) and npm Package Comparator (tinyfish-io/tinyfish-cookbook, 2.2k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
LeoYeAI (a GitHub user) maintains it in LeoYeAI/openclaw-master-skills, which has 2,160 GitHub stars. The repository holds 1,235 skills in this directory. The repository was last updated on July 20, 2026.
Source: LeoYeAI/openclaw-master-skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.