Performance Optimization
Advanced techniques for optimizing O2VEND theme and app performance.
Overview
Performance optimization is crucial for providing a fast, responsive user experience. This guide covers advanced techniques for optimizing themes and apps.
Performance Metrics
Key Metrics to Monitor
- First Contentful Paint (FCP): < 1.8s
- Largest Contentful Paint (LCP): < 2.5s
- Time to Interactive (TTI): < 3.8s
- Total Blocking Time (TBT): < 200ms
- Cumulative Layout Shift (CLS): < 0.1
Theme Performance Optimization
1. Template Optimization
Minimize Liquid Logic
❌ Avoid complex logic in templates:
{% for collection in collections %}
{% for product in collection.products %}
{% for variant in product.variants %}
{% for option in variant.options %}
{{ option.name }}
{% endfor %}
{% endfor %}
{% endfor %}
{% endfor %}
✅ Use snippets to break down complexity:
{% for collection in collections %}
{% render 'collection-grid', collection: collection %}
{% endfor %}
Cache Expensive Operations
{% assign product_count = collection.products.size %}
{% assign has_discount = product.compare_at_price > product.price %}
{% assign formatted_price = product.price | money %}
2. Asset Optimization
Minify CSS and JavaScript
# Minify CSS
cssnano theme.css > theme.min.css
# Minify JavaScript
terser theme.js > theme.min.js
Combine Files
<!-- Instead of multiple files -->
{{ 'theme.css' | asset_url | stylesheet_tag }}
{{ 'components.css' | asset_url | stylesheet_tag }}
<!-- Combine into one -->
{{ 'theme.min.css' | asset_url | stylesheet_tag }}
Optimize Images
- Use WebP format when possible
- Implement responsive images
- Lazy load images below the fold
- Compress images (target 70-80% quality)
3. Widget Performance
Limit Widget Count
{% assign limited_widgets = widgets.content | limit: 10 %}
{% for widget in limited_widgets %}
{{ widget | render_widget }}
{% endfor %}
Lazy Load Widgets
<div class="lazy-widget" data-widget-id="{{ widget.id }}">
<!-- Widget placeholder -->
</div>
<script>
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
loadWidget(entry.target);
observer.unobserve(entry.target);
}
});
});
</script>
App Performance Optimization
1. Efficient Hook Implementation
Minimize Hook Processing Time
// ❌ Slow: Processing in hook
liquid.registerHook('theme_head', (context) => {
// Heavy processing
const data = processLargeDataset();
return data;
});
// ✅ Fast: Cache results
const cachedData = processLargeDataset();
liquid.registerHook('theme_head', (context) => {
return cachedData;
});
2. Asset Loading
Defer Non-Critical Assets
<!-- Critical CSS inline -->
<style>
/* Critical styles */
</style>
<!-- Non-critical CSS deferred -->
<link rel="preload" href="{{ 'theme.css' | asset_url }}" as="style" onload="this.onload=null;this.rel='stylesheet'">
API Performance
1. Request Optimization
Batch Requests
// ❌ Multiple requests
const products = await api.getProducts();
const categories = await api.getCategories();
const brands = await api.getBrands();
// ✅ Single batch request
const data = await api.batch({
products: '/products',
categories: '/categories',
brands: '/brands'
});
Implement Caching
const cache = new Map();
async function getCachedData(key, fetcher) {
if (cache.has(key)) {
return cache.get(key);
}
const data = await fetcher();
cache.set(key, data);
return data;
}
2. Pagination
Use Efficient Pagination
// Use cursor-based pagination when available
const products = await api.getProducts({
page: 1,
pageSize: 20,
cursor: lastCursor
});
Database Optimization
1. Query Optimization
- Use indexes on frequently queried fields
- Limit result sets
- Use projections to fetch only needed fields
- Implement connection pooling
2. Caching Strategy
// Multi-level caching
const cache = {
memory: new Map(),
redis: redisClient,
async get(key) {
// Check memory cache
if (this.memory.has(key)) {
return this.memory.get(key);
}
// Check Redis cache
const redisValue = await this.redis.get(key);
if (redisValue) {
this.memory.set(key, redisValue);
return redisValue;
}
return null;
}
};
Monitoring and Profiling
1. Performance Monitoring
// Measure performance
performance.mark('start');
// ... code ...
performance.mark('end');
performance.measure('operation', 'start', 'end');
console.log(performance.getEntriesByName('operation'));
2. Error Tracking
// Track performance errors
window.addEventListener('error', (event) => {
// Send to monitoring service
trackError({
message: event.message,
filename: event.filename,
lineno: event.lineno
});
});
Best Practices
- Measure First: Always measure before optimizing
- Optimize Critical Path: Focus on above-the-fold content
- Lazy Load: Defer non-critical resources
- Cache Aggressively: Cache API responses and computed values
- Minify Assets: Always minify production assets
- Monitor Performance: Continuously monitor performance metrics
- Test Regularly: Performance test after each change
Tools
- Lighthouse: Performance auditing
- WebPageTest: Detailed performance analysis
- Chrome DevTools: Performance profiling
- Bundle Analyzer: Analyze JavaScript bundles