阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > 图片等媒体资源优化

图片等媒体资源优化

作者:陈川 阅读数:34394人阅读 分类: 构建工具

图片等媒体资源优化的必要性

现代Web应用大量使用图片、视频等媒体资源,这些资源往往占据页面加载时间的大头。未优化的媒体资源会导致首屏加载缓慢、带宽浪费和用户体验下降。Vite作为新一代前端构建工具,提供了多种开箱即用的优化手段。

Vite内置的图片处理能力

Vite默认支持图片资源的导入,无需额外配置即可在代码中直接引用:

import logo from './assets/logo.png'

function Header() {
  return <img src={logo} alt="Logo" />
}

Vite会自动处理这些资源:

  • 小于4KB的图片转为base64内联
  • 较大的图片生成哈希文件名并复制到输出目录
  • 提供图片的public路径解析

图片格式选择与转换

WebP格式的优势

WebP通常比PNG/JPG小25-35%,支持透明度和动画。Vite可以通过插件自动转换:

npm install vite-plugin-webp -D

配置vite.config.js:

import { defineConfig } from 'vite'
import webp from 'vite-plugin-webp'

export default defineConfig({
  plugins: [
    webp({
      quality: 80,
      // 只转换大于10KB的图片
      filter: (filePath, fileBuffer) => fileBuffer.length > 10240
    })
  ]
})

AVIF格式的进阶优化

AVIF比WebP再小20-30%,但编码时间更长。适合对性能要求极高的场景:

// vite.config.js
import avif from 'vite-plugin-avif'

export default defineConfig({
  plugins: [
    avif({
      quality: 50,
      speed: 5  // 1-9,数值越大编码越快但压缩率越低
    })
  ]
})

响应式图片处理

基于视口的动态加载

使用vite-plugin-responsive-loader生成多尺寸版本:

// vite.config.js
import responsive from 'vite-plugin-responsive-loader'

export default defineConfig({
  plugins: [
    responsive({
      sizes: [320, 640, 1024, 1600],
      formats: ['webp', 'original']
    })
  ]
})

组件中使用:

const sources = [
  { srcset: '/assets/hero-320.webp 320w', type: 'image/webp' },
  { srcset: '/assets/hero-640.webp 640w', type: 'image/webp' },
  { srcset: '/assets/hero-1024.webp 1024w', type: 'image/webp' }
]

function HeroImage() {
  return (
    <picture>
      {sources.map((src, i) => (
        <source key={i} {...src} />
      ))}
      <img src="/assets/hero-1024.jpg" alt="Hero" />
    </picture>
  )
}

懒加载实现

原生loading属性

最简单的懒加载方式:

<img src="image.jpg" loading="lazy" alt="Lazy loaded" />

Intersection Observer API

更精细控制的实现:

// lazy.js
const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      const img = entry.target
      img.src = img.dataset.src
      observer.unobserve(img)
    }
  })
}, {
  rootMargin: '200px'
})

document.querySelectorAll('[data-src]').forEach(img => {
  observer.observe(img)
})

组件中使用:

<img data-src="/large-image.jpg" alt="Lazy" class="lazy" />

雪碧图优化

使用vite-plugin-sprite合并小图标:

npm install vite-plugin-sprite -D

配置示例:

// vite.config.js
import sprite from 'vite-plugin-sprite'

export default defineConfig({
  plugins: [
    sprite({
      // 匹配icons目录下的svg
      include: 'src/assets/icons/*.svg',
      output: 'public/sprites'
    })
  ]
})

使用生成的雪碧图:

.icon {
  background-image: url('/sprites/sprite.svg');
}
.icon-home {
  width: 24px;
  height: 24px;
  background-position: 0 0;
}

视频资源优化策略

视频格式选择

优先使用WebM而非MP4:

<video width="640" height="360" controls>
  <source src="video.webm" type="video/webm">
  <source src="video.mp4" type="video/mp4">
</video>

视频预加载策略

根据网络条件动态加载:

function loadVideo() {
  const connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection
  const video = document.getElementById('hero-video')
  
  if (connection) {
    const effectiveType = connection.effectiveType
    video.src = effectiveType === '4g' ? 'hd.webm' : 'sd.webm'
  } else {
    video.src = 'sd.webm'
  }
}

媒体资源的CDN加速

配置Vite的base路径指向CDN:

// vite.config.js
export default defineConfig({
  base: process.env.NODE_ENV === 'production' 
    ? 'https://cdn.yourdomain.com/assets/' 
    : '/'
})

结合内容哈希确保缓存有效性:

// vite.config.js
export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        assetFileNames: 'assets/[name]-[hash][extname]'
      }
    }
  }
})

媒体资源的按需加载

动态导入大尺寸资源:

function loadHeroImage() {
  import('./assets/hero-image.webp').then(module => {
    document.getElementById('hero').style.backgroundImage = `url(${module.default})`
  })
}

// 在需要时触发
window.addEventListener('scroll', loadHeroImage, { once: true })

缓存策略的最佳实践

配置强缓存和协商缓存:

# Nginx配置示例
location ~* \.(jpg|jpeg|png|gif|ico|webp|svg|mp4|webm)$ {
  expires 1y;
  add_header Cache-Control "public, immutable";
  access_log off;
}

对于频繁更新的资源:

location ~* \.(js|css)$ {
  expires 7d;
  add_header Cache-Control "public, must-revalidate";
}

性能监控与调优

使用Chrome DevTools的Coverage工具分析未使用资源:

// 在控制台直接运行
console.table(performance.getEntriesByType('resource')
  .filter(r => r.initiatorType === 'img')
  .map(r => ({
    name: r.name,
    duration: `${r.duration.toFixed(2)}ms`,
    size: `${(r.transferSize / 1024).toFixed(2)}KB`
  }))
)

实现资源加载监控:

const observer = new PerformanceObserver((list) => {
  list.getEntries().forEach(entry => {
    console.log(`[${entry.initiatorType}] ${entry.name}: 
      ${entry.duration.toFixed(2)}ms`)
  })
})

observer.observe({ entryTypes: ['resource'] })

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

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

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌