Image optimization and lazy loading
Image Optimization and Lazy Loading
Images play a crucial role in modern web applications, but improper handling can lead to performance issues. As a cross-platform development framework, uni-app offers various image processing solutions. Proper utilization of these technologies can significantly enhance application performance.
Image Format Selection
Choosing the right image format is the first step in optimization. Common formats include:
- JPEG: Suitable for photographic images, supports high compression ratios
- PNG: Suitable for images requiring transparency, lossless compression
- WebP: A new format introduced by Google, offering 30% better compression than JPEG
- SVG: Vector graphics, ideal for icons and simple graphics
// Selecting different formats in uni-app based on platform
const getImageUrl = (name) => {
// #ifdef H5
return `/static/images/${name}.webp`
// #endif
// #ifndef H5
return `/static/images/${name}.png`
// #endif
}
Image Compression Techniques
Uncompressed images can significantly increase bundle size and loading time. Common compression methods:
-
Tool Compression:
- TinyPNG (online tool)
- ImageOptim (Mac tool)
- Squoosh (Google's open-source tool)
-
Build-Time Compression: Configure webpack in uni-app projects for automatic compression:
// vue.config.js
module.exports = {
chainWebpack: (config) => {
config.module
.rule('images')
.test(/\.(png|jpe?g|gif|webp)(\?.*)?$/)
.use('image-webpack-loader')
.loader('image-webpack-loader')
.options({
mozjpeg: { progressive: true, quality: 65 },
optipng: { enabled: false },
pngquant: { quality: [0.65, 0.9], speed: 4 },
gifsicle: { interlaced: false },
webp: { quality: 75 }
})
}
}
Responsive Image Handling
Different devices require different image sizes. uni-app provides multiple solutions:
- CSS Media Queries:
.hero-image {
background-image: url('/static/images/hero-small.jpg');
}
@media (min-width: 768px) {
.hero-image {
background-image: url('/static/images/hero-medium.jpg');
}
}
@media (min-width: 1200px) {
.hero-image {
background-image: url('/static/images/hero-large.jpg');
}
}
<picture>
Element:
<picture>
<source media="(min-width: 1200px)" srcset="/static/images/banner-large.webp">
<source media="(min-width: 768px)" srcset="/static/images/banner-medium.webp">
<img src="/static/images/banner-small.webp" alt="Banner">
</picture>
Lazy Loading Implementation
Lazy loading delays the loading of images outside the viewport, significantly improving first-screen performance.
Native Lazy Loading
HTML5 introduces the loading="lazy"
attribute:
<img src="/static/images/product.jpg" loading="lazy" alt="Product">
Intersection Observer API
A more flexible lazy loading solution:
// Create observer
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target
img.src = img.dataset.src
observer.unobserve(img)
}
})
}, {
rootMargin: '0px 0px 200px 0px' // Load 200px ahead
})
// Observe all lazy-load images
document.querySelectorAll('img[data-src]').forEach(img => {
observer.observe(img)
})
uni-App Specific Solutions
uni-app provides dedicated lazy loading components and APIs:
<image>
Component Lazy Loading:
<image
lazy-load
:src="imageUrl"
mode="aspectFill"
></image>
- Page-Level Lazy Loading Configuration:
// pages.json
{
"pages": [
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "Home",
"enableLazyLoadImages": true // Enable image lazy loading
}
}
]
}
Advanced Optimization Techniques
Progressive Image Loading
Load low-quality images first, then replace with high-definition versions:
// Use BlurHash for placeholder
<template>
<div class="image-container">
<img
:src="blurHashUrl"
class="placeholder"
v-if="!loaded"
>
<img
:src="realImageUrl"
@load="handleLoad"
:class="{ 'full-image': loaded }"
>
</div>
</template>
<script>
export default {
data() {
return {
blurHashUrl: 'data:image/svg+xml;base64,...',
realImageUrl: '/static/images/high-quality.jpg',
loaded: false
}
},
methods: {
handleLoad() {
this.loaded = true
}
}
}
</script>
<style>
.placeholder {
filter: blur(10px);
transition: opacity 0.5s;
}
.full-image {
opacity: 1;
transition: opacity 0.5s;
}
</style>
CDN Acceleration
Using CDN can significantly improve image loading speed:
// Generate dynamic CDN URL
function getCDNUrl(path, width = 0, height = 0, quality = 80) {
const cdnBase = 'https://cdn.yourdomain.com'
let url = `${cdnBase}/${path}`
if (width || height) {
url += `?x-oss-process=image/resize`
if (width) url += `,w_${width}`
if (height) url += `,h_${height}`
url += `/quality,q_${quality}`
}
return url
}
// Usage example
const thumbnailUrl = getCDNUrl('products/123.jpg', 300, 200)
Preloading Critical Images
For first-screen critical images, use preloading:
<!-- Preload in HTML head -->
<link rel="preload" href="/static/images/hero-image.webp" as="image">
<!-- Preloading in uni-app -->
<script>
export default {
onLoad() {
uni.preloadImage({
urls: [
'/static/images/critical-1.jpg',
'/static/images/critical-2.png'
],
complete: () => {
console.log('Critical images preloaded')
}
})
}
}
</script>
Performance Monitoring and Tuning
Continuous monitoring of image performance is essential:
- Custom Performance Metrics:
// Monitor image loading time
const perfEntries = performance.getEntriesByType('resource')
.filter(entry => entry.initiatorType === 'img')
perfEntries.forEach(entry => {
console.log(`${entry.name} loading time: ${entry.duration.toFixed(2)}ms`)
})
-
Lighthouse Audits: Regularly use Chrome's Lighthouse tool to detect image-related performance issues.
-
uni-App Performance Panel: Use uni-app's built-in performance analysis tools:
uni.reportPerformance(1001, Date.now())
Multi-Platform Adaptation Strategies
Different platforms handle images differently:
// Platform-specific handling
function getOptimizedImage(url) {
// #ifdef APP-PLUS
return url.replace(/\.(jpg|png)$/, '.webp')
// #endif
// #ifdef MP-WEIXIN
return url + '?imageView2/2/w/500'
// #endif
// #ifdef H5
return new URL(url, location.origin).toString()
// #endif
return url
}
Error Handling and Fallback Solutions
Robust image loading requires handling various exceptions:
<template>
<image
:src="imageUrl"
@error="handleError"
:mode="mode"
></image>
</template>
<script>
export default {
data() {
return {
imageUrl: '/static/images/product.jpg',
fallbackUrl: '/static/images/placeholder.jpg',
mode: 'aspectFit'
}
},
methods: {
handleError(e) {
console.error('Image load failed:', e)
this.imageUrl = this.fallbackUrl
// Report error
uni.reportAnalytics('image_load_error', {
url: this.imageUrl,
platform: uni.getSystemInfoSync().platform
})
}
}
}
</script>
Practical Application Example
E-commerce product list page optimization example:
<template>
<view class="product-list">
<view
v-for="(product, index) in products"
:key="product.id"
class="product-item"
>
<image
lazy-load
:src="getThumbnailUrl(product.image)"
:data-src="getFullImageUrl(product.image)"
mode="aspectFill"
@load="handleImageLoad(index)"
@error="handleImageError(index)"
class="product-image"
></image>
<text class="product-name">{{ product.name }}</text>
</view>
</view>
</template>
<script>
export default {
data() {
return {
products: [], // Fetched from API
imageBaseUrl: 'https://cdn.example.com/images'
}
},
methods: {
getThumbnailUrl(imagePath) {
return `${this.imageBaseUrl}/${imagePath}?x-oss-process=image/resize,w_300/quality,q_70`
},
getFullImageUrl(imagePath) {
return `${this.imageBaseUrl}/${imagePath}`
},
handleImageLoad(index) {
// Image load success handling
this.$set(this.products[index], 'loaded', true)
},
handleImageError(index) {
// Use placeholder image
this.$set(this.products[index], 'image', 'placeholder.jpg')
}
},
async onLoad() {
// Preload first 3 product images
const res = await uni.request({ url: '/api/products' })
this.products = res.data
uni.preloadImage({
urls: this.products.slice(0, 3).map(p => this.getFullImageUrl(p.image))
})
}
}
</script>
<style>
.product-list {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20rpx;
padding: 20rpx;
}
.product-image {
width: 100%;
height: 300rpx;
background-color: #f5f5f5;
transition: opacity 0.3s;
}
.product-image[lazy-loaded] {
opacity: 1;
}
</style>
Future Development Trends
- AVIF Format: More efficient compression algorithm than WebP
- Native Lazy Loading: More browsers supporting
loading="lazy"
- AI Image Optimization: Intelligent cropping and content-aware compression
- Smarter CDNs: Dynamic optimization based on user device and network conditions
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn