You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

提升Google Lighthouse性能分:非WebP下一代图片格式及转码方案咨询

Great question! Let's break this down step by step—first the alternative next-gen image formats you can use instead of WebP, then practical solutions for Rails and JavaScript to implement this optimization.

Alternative Next-Gen Image Formats to WebP

Since you're avoiding WebP due to compatibility concerns, these formats strike a good balance between compression efficiency and browser support:

  • AVIF: Offers better compression than WebP (both lossy and lossless) and is supported by most modern browsers (Chrome, Firefox, Edge, and Safari 16.4+). It’s a solid all-around choice for most use cases.
  • JPEG XL: Boasts exceptional compression (even better than AVIF for some image types) and supports features like progressive loading and animation. Note that while it’s supported in Firefox and Safari, Chrome has temporarily paused support—so it’s best for scenarios where you prioritize maximum file size reduction over broadest desktop Chrome support.
  • HEIC/HEIF: Optimized for photography, this format is widely used on iOS and macOS (supported natively in Safari). It’s a great pick if your audience is heavily Apple-focused, but support on non-Apple browsers is limited.
Rails Solutions for Converting & Serving Next-Gen Images

Rails has several built-in and third-party tools to handle image conversion and delivery:

1. Active Storage (Built-in)

If you’re using Rails’ built-in Active Storage, you can generate next-gen image variants directly—you just need to ensure your server has the required image processing libraries (like libvips with AVIF support, or ImageMagick with AVIF/JPEG XL enabled).

Example of generating an AVIF variant in a view:

<%= image_tag user.avatar.variant(format: :avif), alt: user.name %>

To serve the right format based on browser support, you can check the Accept header in a helper or controller:

def serve_optimal_image(image)
  if request.headers['Accept'].include?('image/avif')
    image.variant(format: :avif)
  else
    image.variant(format: :jpg)
  end
end

2. ImageProcessing Gem

This gem wraps libvips (faster than ImageMagick) and supports AVIF/JPEG XL conversion out of the box. Install it via Gemfile:

gem 'image_processing', '~> 1.12'

Then use it to convert images in your code:

processed_image = ImageProcessing::Vips.source('original.jpg')
  .convert(:avif)
  .resize_to_limit(1200, 1200)
  .call

processed_image.save('optimized.avif')

3. MiniMagick

If you prefer ImageMagick, MiniMagick lets you run conversion commands directly:

image = MiniMagick::Image.open('original.png')
image.format('avif')
image.write('optimized.avif')
JavaScript Solutions for Handling Next-Gen Images

On the frontend, the goal is to serve the right format to each browser while providing fallbacks. Here are the most reliable approaches:

This is the standard, no-JS way to serve multiple image formats. Browsers will automatically pick the first supported format:

<picture>
  <source srcset="image.avif" type="image/avif">
  <source srcset="image.jpg" type="image/jpeg">
  <img src="image.jpg" alt="Product photo" loading="lazy">
</picture>

2. Browser Support Detection with JavaScript

If you need more dynamic control (e.g., lazy loading or runtime format selection), use Image.prototype.canPlayType to check support:

async function supportsAVIF() {
  return new Promise(resolve => {
    const testImg = new Image();
    testImg.onload = () => resolve(true);
    testImg.onerror = () => resolve(false);
    // Minimal AVIF test image as base64
    testImg.src = 'data:image/avif;base64,AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAAB0AAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAIAAAACAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgQ0MAAAAABNjb2xybmNseAACAAIAAYAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAACVtZGF0EgAKCBgANogQEAwgMg8f8D///8WfhwB8+ErK42A=';
  });
}

// Usage
supportsAVIF().then(isSupported => {
  const imgElement = document.getElementById('product-image');
  imgElement.src = isSupported ? 'image.avif' : 'image.jpg';
});

3. Client-Side Conversion (For User-Uploaded Images)

If you need to convert user-uploaded JPG/PNG to next-gen formats in the browser (note: this uses client resources, so server-side is better for performance), you can use the Canvas API (if the browser supports AVIF/JPEG XL encoding):

async function convertImageToAVIF(file) {
  const img = new Image();
  img.src = URL.createObjectURL(file);
  await img.decode();

  const canvas = document.createElement('canvas');
  canvas.width = img.width;
  canvas.height = img.height;
  const ctx = canvas.getContext('2d');
  ctx.drawImage(img, 0, 0);

  // Convert canvas to AVIF blob (returns null if unsupported)
  return canvas.toBlob(blob => blob, 'image/avif', 0.8);
}
Best Practices
  • Always provide a JPG/PNG fallback for older browsers.
  • Prioritize server-side conversion over client-side to avoid wasting user device resources.
  • Test support across your target browser audience (use tools like Can I Use to verify format support).

内容的提问来源于stack exchange,提问作者Harshita

火山引擎 最新活动