384 lines
8.3 KiB
Markdown
384 lines
8.3 KiB
Markdown
# 📊 Bundle Analysis Guide
|
|
|
|
Simple guide for analyzing and optimizing bundle sizes.
|
|
|
|
## 🎯 Quick Analysis
|
|
|
|
### Frontend Bundle Analysis
|
|
```bash
|
|
# Analyze bundle size
|
|
pnpm analyze
|
|
|
|
# Or use the script
|
|
pnpm bundle-analyze
|
|
```
|
|
|
|
### Key Metrics to Monitor
|
|
- **First Load JS**: Should be < 250KB
|
|
- **Total Bundle Size**: Should be < 1MB
|
|
- **Largest Chunks**: Identify optimization targets
|
|
|
|
## 🎯 Frontend Optimizations
|
|
|
|
### 1. Bundle Analysis & Code Splitting
|
|
|
|
```bash
|
|
# Analyze current bundle size
|
|
cd apps/portal
|
|
pnpm run analyze
|
|
|
|
# Build with analysis
|
|
pnpm run build:analyze
|
|
```
|
|
|
|
### 2. Dynamic Imports
|
|
|
|
```typescript
|
|
// Before: Static import
|
|
import { HeavyComponent } from './HeavyComponent';
|
|
|
|
// After: Dynamic import
|
|
const HeavyComponent = lazy(() => import('./HeavyComponent'));
|
|
|
|
// Route-level code splitting
|
|
const Dashboard = lazy(() => import('./pages/Dashboard'));
|
|
const Orders = lazy(() => import('./pages/Orders'));
|
|
```
|
|
|
|
### 3. Image Optimization
|
|
|
|
```typescript
|
|
// Use Next.js Image component with optimization
|
|
import Image from 'next/image';
|
|
|
|
<Image
|
|
src="/hero.jpg"
|
|
alt="Hero"
|
|
width={800}
|
|
height={600}
|
|
priority={false} // Lazy load non-critical images
|
|
placeholder="blur" // Add blur placeholder
|
|
/>
|
|
```
|
|
|
|
### 4. Tree Shaking Optimization
|
|
|
|
```typescript
|
|
// Before: Import entire library
|
|
import * as _ from 'lodash';
|
|
|
|
// After: Import specific functions
|
|
import { debounce, throttle } from 'lodash-es';
|
|
|
|
// Or use individual packages
|
|
import debounce from 'lodash.debounce';
|
|
```
|
|
|
|
### 5. React Query Optimization
|
|
|
|
```typescript
|
|
// Optimize React Query cache
|
|
const queryClient = new QueryClient({
|
|
defaultOptions: {
|
|
queries: {
|
|
// Reduce memory usage
|
|
cacheTime: 5 * 60 * 1000, // 5 minutes
|
|
staleTime: 1 * 60 * 1000, // 1 minute
|
|
// Limit concurrent queries
|
|
refetchOnWindowFocus: false,
|
|
},
|
|
},
|
|
});
|
|
```
|
|
|
|
## 🎯 Backend Optimizations
|
|
|
|
### 1. Heap Size Optimization
|
|
|
|
```json
|
|
// package.json - Optimized heap sizes
|
|
{
|
|
"scripts": {
|
|
"dev": "NODE_OPTIONS=\"--max-old-space-size=2048\" nest start --watch",
|
|
"build": "NODE_OPTIONS=\"--max-old-space-size=3072\" nest build",
|
|
"type-check": "NODE_OPTIONS=\"--max-old-space-size=4096\" tsc --noEmit"
|
|
}
|
|
}
|
|
```
|
|
|
|
### 2. Streaming Responses
|
|
|
|
```typescript
|
|
// For large data responses
|
|
@Get('large-dataset')
|
|
async getLargeDataset(@Res() res: Response) {
|
|
const stream = this.dataService.createDataStream();
|
|
|
|
res.setHeader('Content-Type', 'application/json');
|
|
res.setHeader('Transfer-Encoding', 'chunked');
|
|
|
|
stream.pipe(res);
|
|
}
|
|
```
|
|
|
|
### 3. Memory-Efficient Pagination
|
|
|
|
```typescript
|
|
// Cursor-based pagination instead of offset
|
|
interface PaginationOptions {
|
|
cursor?: string;
|
|
limit: number; // Max 100
|
|
}
|
|
|
|
async findWithCursor(options: PaginationOptions) {
|
|
return this.prisma.order.findMany({
|
|
take: Math.min(options.limit, 100),
|
|
...(options.cursor && {
|
|
cursor: { id: options.cursor },
|
|
skip: 1,
|
|
}),
|
|
orderBy: { createdAt: 'desc' },
|
|
});
|
|
}
|
|
```
|
|
|
|
### 4. Request/Response Caching
|
|
|
|
```typescript
|
|
// Memory-efficient caching
|
|
@Injectable()
|
|
export class CacheService {
|
|
private readonly cache = new Map<string, { data: any; expires: number }>();
|
|
private readonly maxSize = 1000; // Limit cache size
|
|
|
|
set(key: string, data: any, ttl: number = 300000) {
|
|
// Implement LRU eviction
|
|
if (this.cache.size >= this.maxSize) {
|
|
const firstKey = this.cache.keys().next().value;
|
|
this.cache.delete(firstKey);
|
|
}
|
|
|
|
this.cache.set(key, {
|
|
data,
|
|
expires: Date.now() + ttl,
|
|
});
|
|
}
|
|
}
|
|
```
|
|
|
|
### 5. Database Connection Optimization
|
|
|
|
```typescript
|
|
// Optimize Prisma connection pool
|
|
const prisma = new PrismaClient({
|
|
datasources: {
|
|
db: {
|
|
url: process.env.DATABASE_URL,
|
|
},
|
|
},
|
|
// Optimize connection pool
|
|
__internal: {
|
|
engine: {
|
|
connectionLimit: 10, // Reduce from default 20
|
|
},
|
|
},
|
|
});
|
|
```
|
|
|
|
## 🎯 Dependency Optimizations
|
|
|
|
### 1. Replace Heavy Dependencies
|
|
|
|
```bash
|
|
# Before: moment.js (67KB)
|
|
npm uninstall moment
|
|
|
|
# After: date-fns (13KB with tree shaking)
|
|
npm install date-fns
|
|
|
|
# Before: lodash (71KB)
|
|
npm uninstall lodash
|
|
|
|
# After: Individual functions or native alternatives
|
|
npm install lodash-es # Better tree shaking
|
|
```
|
|
|
|
### 2. Bundle Analysis Results
|
|
|
|
```bash
|
|
# Run bundle analysis
|
|
./scripts/memory-optimization.sh
|
|
|
|
# Key metrics to monitor:
|
|
# - First Load JS: < 250KB
|
|
# - Total Bundle Size: < 1MB
|
|
# - Largest Chunks: Identify optimization targets
|
|
```
|
|
|
|
### 3. Webpack Optimizations (Already Implemented)
|
|
|
|
- **Code Splitting**: Separate vendor, common, and UI chunks
|
|
- **Tree Shaking**: Remove unused code
|
|
- **Compression**: Gzip/Brotli compression
|
|
- **Caching**: Long-term caching for static assets
|
|
|
|
## 🎯 Runtime Optimizations
|
|
|
|
### 1. Memory Leak Detection
|
|
|
|
```typescript
|
|
// Add memory monitoring
|
|
@Injectable()
|
|
export class MemoryMonitorService {
|
|
@Cron('*/5 * * * *') // Every 5 minutes
|
|
checkMemoryUsage() {
|
|
const usage = process.memoryUsage();
|
|
|
|
if (usage.heapUsed > 500 * 1024 * 1024) { // 500MB
|
|
this.logger.warn('High memory usage detected', {
|
|
heapUsed: `${Math.round(usage.heapUsed / 1024 / 1024)}MB`,
|
|
heapTotal: `${Math.round(usage.heapTotal / 1024 / 1024)}MB`,
|
|
external: `${Math.round(usage.external / 1024 / 1024)}MB`,
|
|
});
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### 2. Garbage Collection Optimization
|
|
|
|
```bash
|
|
# Enable GC logging in production
|
|
NODE_OPTIONS="--max-old-space-size=2048 --gc-interval=100" npm start
|
|
|
|
# Monitor GC patterns
|
|
NODE_OPTIONS="--trace-gc --trace-gc-verbose" npm run dev
|
|
```
|
|
|
|
### 3. Worker Threads for CPU-Intensive Tasks
|
|
|
|
```typescript
|
|
// For heavy computations
|
|
import { Worker, isMainThread, parentPort } from 'worker_threads';
|
|
|
|
if (isMainThread) {
|
|
// Main thread
|
|
const worker = new Worker(__filename);
|
|
worker.postMessage({ data: largeDataset });
|
|
|
|
worker.on('message', (result) => {
|
|
// Handle processed result
|
|
});
|
|
} else {
|
|
// Worker thread
|
|
parentPort?.on('message', ({ data }) => {
|
|
const result = processLargeDataset(data);
|
|
parentPort?.postMessage(result);
|
|
});
|
|
}
|
|
```
|
|
|
|
## 📈 Monitoring & Metrics
|
|
|
|
### 1. Performance Monitoring
|
|
|
|
```typescript
|
|
// Add performance metrics
|
|
@Injectable()
|
|
export class PerformanceService {
|
|
trackMemoryUsage(operation: string) {
|
|
const start = process.memoryUsage();
|
|
|
|
return {
|
|
end: () => {
|
|
const end = process.memoryUsage();
|
|
const diff = {
|
|
heapUsed: end.heapUsed - start.heapUsed,
|
|
heapTotal: end.heapTotal - start.heapTotal,
|
|
};
|
|
|
|
this.logger.debug(`Memory usage for ${operation}`, diff);
|
|
},
|
|
};
|
|
}
|
|
}
|
|
```
|
|
|
|
### 2. Bundle Size Monitoring
|
|
|
|
```json
|
|
// Add to CI/CD pipeline
|
|
{
|
|
"scripts": {
|
|
"build:check-size": "npm run build && bundlesize"
|
|
},
|
|
"bundlesize": [
|
|
{
|
|
"path": ".next/static/js/*.js",
|
|
"maxSize": "250kb"
|
|
},
|
|
{
|
|
"path": ".next/static/css/*.css",
|
|
"maxSize": "50kb"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
## 🚀 Implementation Checklist
|
|
|
|
### Immediate Actions (Week 1)
|
|
- [ ] Run bundle analysis: `pnpm run analyze`
|
|
- [ ] Implement dynamic imports for heavy components
|
|
- [ ] Optimize image loading with Next.js Image
|
|
- [ ] Reduce heap allocation in development
|
|
|
|
### Short-term (Week 2-3)
|
|
- [ ] Replace heavy dependencies (moment → date-fns)
|
|
- [ ] Implement request caching
|
|
- [ ] Add memory monitoring
|
|
- [ ] Optimize database connection pool
|
|
|
|
### Long-term (Month 1)
|
|
- [ ] Implement streaming for large responses
|
|
- [ ] Add worker threads for CPU-intensive tasks
|
|
- [ ] Set up continuous bundle size monitoring
|
|
- [ ] Implement advanced caching strategies
|
|
|
|
## 🎯 Expected Results
|
|
|
|
### Memory Reduction Targets
|
|
- **Frontend Bundle**: 30-50% reduction
|
|
- **Backend Heap**: 25-40% reduction
|
|
- **Build Time**: 20-30% improvement
|
|
- **Runtime Memory**: 35-50% reduction
|
|
|
|
### Performance Improvements
|
|
- **First Load**: < 2 seconds
|
|
- **Page Transitions**: < 500ms
|
|
- **API Response**: < 200ms (95th percentile)
|
|
- **Memory Stability**: No memory leaks in 24h+ runs
|
|
|
|
## 🔧 Tools & Commands
|
|
|
|
```bash
|
|
# Frontend analysis
|
|
cd apps/portal && pnpm run analyze
|
|
|
|
# Backend memory check
|
|
cd apps/bff && NODE_OPTIONS="--trace-gc" pnpm dev
|
|
|
|
# Full optimization analysis
|
|
./scripts/memory-optimization.sh
|
|
|
|
# Dependency audit
|
|
pnpm audit --recursive
|
|
|
|
# Bundle size check
|
|
pnpm run build && ls -la .next/static/js/
|
|
```
|
|
|
|
---
|
|
|
|
**Note**: Always test memory optimizations in a staging environment before deploying to production. Monitor application performance and user experience after implementing changes.
|