Files
gh-jamshu-jamshi-marketplac…/commands/optimize.md
2025-11-29 18:50:06 +08:00

643 lines
12 KiB
Markdown

Analyze and optimize your Odoo PWA for performance, bundle size, and user experience.
## What this command does:
- Analyzes bundle size
- Identifies performance bottlenecks
- Suggests optimizations
- Checks caching efficiency
- Reviews PWA configuration
- Provides actionable recommendations
---
## Quick Performance Check 🚀
### Run These Commands:
```bash
# Build for production
npm run build
# Analyze bundle size
npm run build -- --analyze
# Preview production build
npm run preview
# Run Lighthouse audit
# (Chrome DevTools → Lighthouse tab)
```
---
## Bundle Size Analysis 📦
### Check Current Size
```bash
# Build and see output
npm run build
# Typical output:
# dist/index.html 1.2 kB
# dist/assets/index-abc123.js 45.3 kB
# dist/assets/vendor-def456.js 120.5 kB
```
### Analyze Bundle Composition
```bash
# Install analyzer
npm install -D rollup-plugin-visualizer
# Add to vite.config.js
import { visualizer } from 'rollup-plugin-visualizer';
export default {
plugins: [
// ...other plugins
visualizer({
open: true,
gzipSize: true,
brotliSize: true
})
]
};
# Build and open report
npm run build
# Opens stats.html in browser
```
### Target Bundle Sizes:
-**Excellent**: < 200 KB (gzipped)
- ⚠️ **Good**: 200-500 KB
-**Needs Work**: > 500 KB
---
## Optimization Strategies
### 1. Code Splitting 📂
#### Lazy Load Routes
**SvelteKit** (automatic):
```javascript
// Routes are auto-split
// src/routes/+page.svelte → separate chunk
```
**React**:
```javascript
import { lazy, Suspense } from 'react';
const ExpenseList = lazy(() => import('./ExpenseList'));
function App() {
return (
<Suspense fallback={<Loading />}>
<ExpenseList />
</Suspense>
);
}
```
**Vue**:
```javascript
const ExpenseList = () => import('./ExpenseList.vue');
const routes = [
{
path: '/expenses',
component: ExpenseList // Lazy loaded
}
];
```
#### Manual Code Splitting
```javascript
// Split heavy utility into separate chunk
const heavyUtil = await import('./heavyUtility.js');
heavyUtil.doSomething();
```
### 2. Tree Shaking 🌳
#### Remove Unused Code
```javascript
// Bad: Imports everything
import * as utils from './utils';
// Good: Import only what you need
import { formatDate, formatCurrency } from './utils';
```
#### Check for Unused Dependencies
```bash
npm install -g depcheck
depcheck
# Remove unused packages
npm uninstall <unused-package>
```
### 3. Optimize Dependencies 📚
#### Use Lighter Alternatives
```javascript
// Instead of moment.js (heavy)
import moment from 'moment'; // 72 KB
// Use date-fns (tree-shakeable)
import { format } from 'date-fns'; // ~2 KB
// Or native Date
new Date().toLocaleDateString();
```
#### Common Heavy Packages & Alternatives:
-**moment** (72 KB) → ✅ **date-fns** (tree-shakeable)
-**lodash** (whole) → ✅ **lodash-es** (individual imports)
-**axios** → ✅ **fetch** (built-in)
-**uuid** → ✅ **crypto.randomUUID()** (built-in)
### 4. Optimize Images 🖼️
#### Compress Images
```bash
# Install image optimizer
npm install -D vite-plugin-imagemin
# Add to vite.config.js
import viteImagemin from 'vite-plugin-imagemin';
export default {
plugins: [
viteImagemin({
gifsicle: { optimizationLevel: 7 },
optipng: { optimizationLevel: 7 },
mozjpeg: { quality: 80 },
svgo: { plugins: [{ removeViewBox: false }] }
})
]
};
```
#### Lazy Load Images
```javascript
// Native lazy loading
<img src="large-image.jpg" loading="lazy" />
// Or with IntersectionObserver
```
#### Use Appropriate Formats
- **WebP** for photos (smaller than JPEG)
- **SVG** for icons/logos
- **PNG** only when transparency needed
### 5. Minimize JavaScript ⚡
#### Enable Minification (default in Vite)
```javascript
// vite.config.js
export default {
build: {
minify: 'terser', // or 'esbuild' (faster)
terserOptions: {
compress: {
drop_console: true, // Remove console.logs
drop_debugger: true
}
}
}
};
```
#### Remove Development Code
```javascript
// Use environment variables
if (import.meta.env.DEV) {
console.log('Debug info'); // Removed in production
}
```
---
## Caching Optimization 💾
### 1. Optimize Cache Strategy
#### Review Cache Settings
```javascript
// In cache store
const CACHE_VALIDITY = 5 * 60 * 1000; // 5 minutes
// Consider your use case:
// - Frequently changing data: 1-2 minutes
// - Moderate updates: 5-10 minutes
// - Rarely changes: 30-60 minutes
```
#### Limit Initial Load
```javascript
// Don't fetch everything at once
const records = await odoo.searchRecords(
model,
[],
fields,
100 // Limit to 100 records initially
);
// Load more on demand (pagination)
```
### 2. Optimize Sync Frequency
```javascript
// Adjust sync interval based on needs
const SYNC_INTERVAL = 5 * 60 * 1000; // 5 minutes
// Balance:
// - More frequent: Better UX, more bandwidth
// - Less frequent: Less bandwidth, slightly stale data
```
### 3. Selective Caching
```javascript
// Only cache fields you need
const fields = [
'x_studio_name',
'x_studio_amount',
'x_studio_date'
// Don't fetch unnecessary fields
];
```
---
## PWA Optimization 📱
### 1. Service Worker Configuration
#### Optimize Caching Strategy
```javascript
// In service worker or vite-plugin-pwa config
VitePWA({
workbox: {
runtimeCaching: [
{
urlPattern: /^https:\/\/fonts\.googleapis\.com\/.*/,
handler: 'CacheFirst',
options: {
cacheName: 'google-fonts',
expiration: {
maxEntries: 10,
maxAgeSeconds: 60 * 60 * 24 * 365 // 1 year
}
}
},
{
urlPattern: /^https:\/\/.*\.odoo\.com\/.*/,
handler: 'NetworkFirst',
options: {
cacheName: 'odoo-api',
networkTimeoutSeconds: 3
}
}
]
}
})
```
### 2. Optimize Manifest
```json
{
"name": "Expense Tracker",
"short_name": "Expenses",
"start_url": "/",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#0066cc",
"icons": [
{
"src": "/icon-192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "any maskable"
},
{
"src": "/icon-512.png",
"sizes": "512x512",
"type": "image/png"
}
]
}
```
### 3. Optimize Icons
```bash
# Use optimized PNG or WebP
# Compress images
# Provide multiple sizes
```
---
## Network Optimization 🌐
### 1. Reduce API Calls
#### Batch Requests
```javascript
// Bad: Multiple calls
const expenses = await fetchExpenses();
const tasks = await fetchTasks();
const partners = await fetchPartners();
// Good: Single call (if Odoo supports)
const data = await fetchAll(['expenses', 'tasks', 'partners']);
```
#### Cache Partner Names
```javascript
// Fetch once, reuse
const partners = await odoo.fetchPartners();
localStorage.setItem('partnerCache', JSON.stringify(partners));
// Later, use cached data
const cached = JSON.parse(localStorage.getItem('partnerCache'));
```
### 2. Incremental Loading
```javascript
// Load initial data
const initial = await fetchExpenses({ limit: 20 });
// Load more on scroll
function onScroll() {
if (nearBottom) {
loadMore();
}
}
```
### 3. Optimize Requests
```javascript
// Only fetch fields you display
const fields = ['id', 'x_studio_name', 'x_studio_amount'];
// Use appropriate domain filters
const domain = [
['x_studio_date', '>=', lastMonth],
['x_studio_status', '!=', 'deleted']
];
```
---
## UI Performance 🎨
### 1. Virtual Scrolling
For long lists:
```javascript
// SvelteKit
import { VirtualList } from 'svelte-virtual-list';
<VirtualList items={expenses} let:item>
<ExpenseCard expense={item} />
</VirtualList>
// React
import { FixedSizeList } from 'react-window';
// Vue
import { RecycleScroller } from 'vue-virtual-scroller';
```
### 2. Debounce Search
```javascript
import { debounce } from './utils';
const handleSearch = debounce((query) => {
searchExpenses(query);
}, 300); // Wait 300ms after typing stops
```
### 3. Optimize Rendering
```javascript
// SvelteKit: Use keyed each blocks
{#each expenses as expense (expense.id)}
<ExpenseCard {expense} />
{/each}
// React: Use keys and memo
const ExpenseCard = memo(({ expense }) => {
// ...
});
expenses.map(expense => (
<ExpenseCard key={expense.id} expense={expense} />
));
// Vue: Use v-memo
<ExpenseCard
v-for="expense in expenses"
:key="expense.id"
:expense="expense"
v-memo="[expense.id]"
/>
```
---
## Build Optimization 🔨
### Vite Config Optimizations
```javascript
// vite.config.js
export default {
build: {
// Target modern browsers
target: 'es2020',
// Optimize chunks
rollupOptions: {
output: {
manualChunks: {
vendor: ['svelte', '@sveltejs/kit'],
odoo: ['./src/lib/odoo.js', './src/lib/stores']
}
}
},
// Compression
minify: 'esbuild', // Faster than terser
// Source maps (only for debugging)
sourcemap: false
},
// Optimize dependencies
optimizeDeps: {
include: ['date-fns', 'lodash-es']
}
};
```
---
## Lighthouse Audit 💡
### Run Lighthouse
1. Open Chrome DevTools
2. Go to Lighthouse tab
3. Select categories:
- ✅ Performance
- ✅ Progressive Web App
- ✅ Best Practices
- ✅ Accessibility
- ✅ SEO
4. Click "Analyze page load"
### Target Scores:
- **Performance**: > 90
- **PWA**: 100
- **Best Practices**: > 95
- **Accessibility**: > 90
- **SEO**: > 90
### Common Issues & Fixes:
#### Low Performance Score
- Reduce bundle size
- Optimize images
- Enable caching
- Lazy load resources
#### PWA Issues
- Fix manifest.json
- Register service worker
- Add offline support
- Provide app icons
#### Accessibility Issues
- Add alt text to images
- Use semantic HTML
- Ensure color contrast
- Add ARIA labels
---
## Performance Monitoring 📊
### Add Performance Tracking
```javascript
// Measure initial load
window.addEventListener('load', () => {
const perfData = performance.getEntriesByType('navigation')[0];
console.log('Load time:', perfData.loadEventEnd - perfData.fetchStart);
console.log('DOM ready:', perfData.domContentLoadedEventEnd - perfData.fetchStart);
});
// Measure sync time
console.time('sync');
await expenseCache.refresh();
console.timeEnd('sync');
```
### Use Web Vitals
```bash
npm install web-vitals
# In app
import { getCLS, getFID, getFCP, getLCP, getTTFB } from 'web-vitals';
getCLS(console.log);
getFID(console.log);
getFCP(console.log);
getLCP(console.log);
getTTFB(console.log);
```
---
## Optimization Checklist ✅
### Bundle Size:
```
□ Analyzed bundle composition
□ Removed unused dependencies
□ Lazy loaded routes/components
□ Optimized images
□ Tree-shaking enabled
□ Minification enabled
□ Total size < 500 KB (gzipped)
```
### Caching:
```
□ Optimal cache validity period
□ Incremental sync working
□ Selective field fetching
□ Partner name caching
□ Appropriate sync frequency
□ IndexedDB optimized
```
### PWA:
```
□ Service worker registered
□ Offline mode works
□ App installable
□ Icons optimized
□ Manifest configured
□ Fast load time
```
### Performance:
```
□ Lighthouse score > 90
□ Initial load < 3s
□ Sync time < 2s
□ No console errors
□ Smooth scrolling
□ Fast navigation
```
---
## Example prompts to use this command:
- `/optimize` - Run optimization checks
- User: "Make my app faster"
- User: "Reduce bundle size"
- User: "Optimize performance"
## Related Commands:
- `/test-connection` - Test after optimization
- `/update-deps` - Update to faster versions
- `/troubleshoot` - Fix performance issues
- `/help` - More information
---
## Quick Wins 🎯
### Immediate Optimizations:
1. **Enable compression** (already in Vite)
2. **Remove console.logs** in production
3. **Lazy load routes** (easy with frameworks)
4. **Optimize images** (use WebP)
5. **Limit initial data fetch** (pagination)
### Medium Effort:
1. **Analyze and split bundles**
2. **Replace heavy dependencies**
3. **Implement virtual scrolling**
4. **Optimize service worker**
5. **Add performance monitoring**
### Long Term:
1. **Regular Lighthouse audits**
2. **Monitor real user metrics**
3. **Continuous optimization**
4. **Keep dependencies updated**
5. **Review and refactor regularly**