阿里云主机折上折
  • 微信号
Current Site:Index > Image optimization and lazy loading

Image optimization and lazy loading

Author:Chuan Chen 阅读数:15652人阅读 分类: uni-app

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:

  1. Tool Compression:

    • TinyPNG (online tool)
    • ImageOptim (Mac tool)
    • Squoosh (Google's open-source tool)
  2. 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:

  1. 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');
  }
}
  1. <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:

  1. <image> Component Lazy Loading:
<image 
  lazy-load 
  :src="imageUrl" 
  mode="aspectFill"
></image>
  1. 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:

  1. 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`)
})
  1. Lighthouse Audits: Regularly use Chrome's Lighthouse tool to detect image-related performance issues.

  2. 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

  1. AVIF Format: More efficient compression algorithm than WebP
  2. Native Lazy Loading: More browsers supporting loading="lazy"
  3. AI Image Optimization: Intelligent cropping and content-aware compression
  4. Smarter CDNs: Dynamic optimization based on user device and network conditions

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.