Files
2nd/10_Wiki/Topic_Programming/Frontend/Bundle Size Optimization.md
T
Antigravity Agent 9148c358d0 docs(10_Wiki): 위키 전체 재구성 — Topic_* 폴더를 4개 카테고리로 통합 + 대규모 중복 제거
Topic_Agent/Topic_Blog/Topics/Topics_Biz/Topics_Meeting/Topics_Rag의 마크다운 지식 문서를
Topic_General/Topic_Programming/Topic_Graphic/Topic_Business 4개 카테고리로 재분류.

- 중복 제거: frontmatter의 status:duplicate/merged + duplicate_of/redirect_to 필드로
  자기 자신을 중복으로 선언한 리다이렉트 stub 1032개 제거, 완전 동일 내용 파일 472개 제거,
  동일 파일명·다른 내용 충돌 시 더 큰(완전한) 버전만 유지(162개 제거) — 총 1639개 중복 제거.
- 분류: 폴더 단위로 명확한 항목(AI_and_ML/Coding/Architecture 등 → Programming,
  Comfyui/Visual_Effects → Graphic, Topics_Biz/Topics_Meeting/사업 등 → Business,
  Poetic_Blog_Writing/창의성/Game_Design 등 → General)은 폴더 우선순위로,
  나머지 혼재 폴더(Topic_Agent/Topic_Blog/Topics 루트/Thinking & Reasoning/Other/UI_UX_Assets)는
  title/tags 키워드 스코어링으로 파일 단위 분류(불명확한 경우 General로 폴백).
  원본 폴더명은 "From_*" 서브폴더로 보존해 추적 가능성 유지.
- 최종 배치: Programming 2784 / General 1608 / Graphic 285 / Business 249 = 4926개 문서.
- 에이전트 운영 상태(.astra/.agent/.obsidian/sessions/memory/_company/docs/lessons/_shared/src)는
  지식 콘텐츠가 아니므로 재분류 대상에서 제외하고 원위치 유지.
- Topics/Topic_email(상위 보호 폴더 Topic_email과 파일명 100% 중복) 삭제 — 보호 폴더 자체는 미변경.
- 완전히 비게 된 Topic_Agent/Topic_Blog/Topics_Biz/Topics_Rag 폴더 제거.
2026-07-05 00:33:48 +09:00

4.9 KiB

id, title, category, status, canonical_id, aliases, duplicate_of, source_trust_level, confidence_score, verification_status, tags, raw_sources, last_reinforced, github_commit, tech_stack
id title category status canonical_id aliases duplicate_of source_trust_level confidence_score verification_status tags raw_sources last_reinforced github_commit tech_stack
wiki-2026-0508-bundle-size-optimization Bundle Size Optimization 10_Wiki/Topics verified self
JS Bundle Optimization
Web Bundle Reduction
none A 0.9 applied
bundle
performance
webpack
vite
tree-shaking
2026-05-10 pending
language framework
JavaScript/TypeScript Vite/Rollup/Webpack

Bundle Size Optimization

매 한 줄

"매 byte 매 less 매 user time 매 less". Bundle size optimization은 production JS/CSS payload를 줄여 LCP/INP/TBT 개선 + mobile-first user 의 perceived speed 개선. 2026 standard tooling: Vite + Rollup tree-shaking, modern bundle analysis (Bundle Buddy, esbuild-visualizer), bundle budgets enforcement.

매 핵심

매 4 lever

  • Tree shaking: ESM only, sideEffects:false, no re-export wildcards.
  • Code splitting: route / component lazy import.
  • Compression: brotli > gzip; precompress at build.
  • Dependency surgery: heavy lib → lighter alt or self-implement.

매 측정 우선

  • Bundle visualizer (rollup-plugin-visualizer, source-map-explorer).
  • Bundle budget in CI (e.g., size-limit, bundlesize).
  • Real device testing (slow 3G profile).

매 응용

  1. Lazy-load route chunks.
  2. Remove unused locales (date-fns, moment).
  3. Replace lodash with native / lodash-es.

💻 패턴

Vite + visualizer

// vite.config.ts
import { defineConfig } from 'vite';
import { visualizer } from 'rollup-plugin-visualizer';

export default defineConfig({
  plugins: [
    visualizer({ filename: 'stats.html', gzipSize: true, brotliSize: true })
  ],
  build: {
    rollupOptions: {
      output: {
        manualChunks: {
          react: ['react', 'react-dom'],
          vendor: ['date-fns', 'zustand']
        }
      }
    }
  }
});

Route-level code split (React)

import { lazy, Suspense } from 'react';
const Dashboard = lazy(() => import('./Dashboard'));

<Suspense fallback={<Skeleton />}>
  <Dashboard />
</Suspense>

Dynamic import for rare path

async function exportToPDF(data: Item[]) {
  const { jsPDF } = await import('jspdf');
  const doc = new jsPDF();
  doc.text(JSON.stringify(data), 10, 10);
  doc.save('out.pdf');
}

Replace heavy lib

// X moment (~290KB)
import moment from 'moment';
moment().format('YYYY-MM-DD');

// O Intl (built-in, 0KB)
new Intl.DateTimeFormat('en-CA').format(new Date());

// O date-fns/format (tree-shakeable, ~3KB)
import { format } from 'date-fns/format';
format(new Date(), 'yyyy-MM-dd');

sideEffects flag

// package.json — library author 측
{
  "name": "my-lib",
  "type": "module",
  "sideEffects": false,
  "exports": {
    ".": {
      "import": "./dist/index.mjs",
      "types": "./dist/index.d.ts"
    }
  }
}

size-limit budget enforcement

// package.json
{
  "scripts": {
    "size": "size-limit"
  },
  "size-limit": [
    { "path": "dist/index.js", "limit": "50 KB" },
    { "path": "dist/vendor.js", "limit": "120 KB" }
  ]
}

Compression at build (brotli)

import compression from 'vite-plugin-compression2';

export default defineConfig({
  plugins: [
    compression({ algorithm: 'brotliCompress', exclude: [/\.(br)$/, /\.(gz)$/] })
  ]
});

Server: strip locales from dayjs

import dayjs from 'dayjs';
import 'dayjs/locale/ko'; // 매 필요한 것만
dayjs.locale('ko');

매 결정 기준

상황 Approach
Initial bundle > 200KB route split + lazy load
Single heavy lib replace 또는 dynamic import
Multi-tenant build per-tenant treeshake config
Library publish ESM + sideEffects:false
Edge runtime bundle ≤ 1MB 가까이 strict budget

기본값: measure first → split → compress → swap heavy deps.

🔗 Graph

🤖 LLM 활용

언제: webpack/vite config audit, lib alternative suggestion, bundle analyzer interpretation. 언제 X: 매 production 매 swap deploy — actual measurement 필수.

안티패턴

  • CommonJS lib import: tree shaking blocked — ESM 사용.
  • import * as foo: bundler 매 mark 매 모든 export used.
  • Polyfill 전체: target browser baseline + browserslist으로 narrow.
  • Single chunk all: SPA → 매 long initial — split per route.
  • Dev source maps in prod: ship source map only via separate URL or skip.

🧪 검증 / 중복

  • Verified (web.dev bundle size guide, Vite docs, size-limit GitHub).
  • 신뢰도 A.

🕓 Changelog

날짜 변경
2026-05-08 Phase 1
2026-05-10 Manual cleanup — bundle optim 4 lever + Vite/size-limit pattern