Stories

Detail Return Return

SvelteKit 最新中文文檔教程(21)—— 最佳實踐之圖片 - Stories Detail

前言

Svelte,一個語法簡潔、入門容易,面向未來的前端框架。

從 Svelte 誕生之初,就備受開發者的喜愛,根據統計,從 2019 年到 2024 年,連續 6 年一直是開發者最感興趣的前端框架 No.1

image.png

Svelte 以其獨特的編譯時優化機制著稱,具有輕量級高性能易上手等特性,非常適合構建輕量級 Web 項目

為了幫助大家學習 Svelte,我同時搭建了 Svelte 最新的中文文檔站點。

如果需要進階學習,也可以入手我的小冊《Svelte 開發指南》,語法篇、實戰篇、原理篇三大篇章帶你係統掌握 Svelte!

歡迎圍觀我的“網頁版朋友圈”、加入“冴羽·成長陪伴社羣”,踏上“前端大佬成長之路”。

圖片

圖片會對您的應用性能產生重大影響。為了獲得最佳效果,您應該通過以下方式優化它們:

  • 生成最優格式如 .avif.webp
  • 為不同的屏幕創建不同尺寸的圖片
  • 確保資源可以被有效緩存

手動完成這些工作很繁瑣。根據您的需求和偏好,您可以使用多種技術。

Vite 的內置處理

Vite 會自動處理導入的資源以提升性能。這包括通過 CSS url() 函數引用的資源。文件名中會添加哈希值以便緩存,小於 assetsInlineLimit 的資源會被內聯。Vite 的資源處理最常用於圖片,但對視頻、音頻等也很有用。

<script>
  import logo from '$lib/assets/logo.png';
</script>

<img alt="項目標誌" src={logo} />

@sveltejs/enhanced-img

@sveltejs/enhanced-img 是在 Vite 內置資源處理基礎上提供的插件。它提供即插即用的圖片處理功能,可以提供更小的文件格式如 avifwebp,自動設置圖片的固有 widthheight 以避免佈局偏移,為各種設備創建多種尺寸的圖片,並出於隱私考慮去除 EXIF 數據。它可以在任何基於 Vite 的項目中使用,包括但不限於 SvelteKit 項目。

[!NOTE] 作為構建插件,@sveltejs/enhanced-img 只能在構建過程中優化位於您機器上的文件。如果您的圖片位於其他位置(如從數據庫、CMS 或後端服務的路徑),請閲讀從 CDN 動態加載圖片。

警告@sveltejs/enhanced-img 包是實驗性的。它使用 1.0 之前的版本號,每個小版本發佈可能會引入破壞性變更。

設置

安裝:

npm install --save-dev @sveltejs/enhanced-img

調整 vite.config.js

import { sveltekit } from '@sveltejs/kit/vite';
+++import { enhancedImages } from '@sveltejs/enhanced-img';+++
import { defineConfig } from 'vite';

export default defineConfig({
  plugins: [
    +++enhancedImages(),+++
    sveltekit()
  ]
});

由於轉換圖片的計算開銷,第一次構建會花費更長時間。但是,構建輸出會被緩存在 ./node_modules/.cache/imagetools 中,因此後續的構建會很快。

基本用法

在你的 .svelte 組件中使用 <enhanced:img> 而不是<img>,並通過 Vite 資源導入 路徑引用圖片文件:

<enhanced:img src="./path/to/your/image.jpg" alt="An alt text" />

在構建時,您的 <enhanced:img> 標籤將被 <img> 替換,並由 <picture> 包裝,提供多種圖片類型和尺寸。在不損失質量的情況下只能對圖片進行縮小,這意味着你應該提供所需的最高分辨率圖片——系統會為可能請求圖片的各種設備類型生成較小的版本。

你應該為 HiDPI 顯示器(又稱視網膜顯示器)提供 2x 分辨率的圖片。<enhanced:img> 會自動負責向較小的設備提供較小版本的圖片。

如果你想為 <enhanced:img> 添加樣式,你應該添加一個 class 並針對它進行設置。

動態選擇圖像

您也可以手動導入圖片資源並將其傳遞給 <enhanced:img>。當您有一組靜態圖片並想要動態選擇或遍歷它們時,這種方法很有用。在這種情況下,您需要同時更新 import 語句和 <img> 元素,如下所示,以表明您想要處理它們。

<script>
  import MyImage from './path/to/your/image.jpg?enhanced';
</script>

<enhanced:img src={MyImage} alt="some alt text" />

你也可以使用 Vite 的 import.meta.glob。請注意,你需要通過自定義查詢來指定 enhanced

<script>
  const imageModules = import.meta.glob(
    '/path/to/assets/*.{avif,gif,heif,jpeg,jpg,png,tiff,webp,svg}',
    {
      eager: true,
      query: {
        enhanced: true
      }
    }
  )
</script>

{#each Object.entries(imageModules) as [_path, module]}
  <enhanced:img src={module.default} alt="some alt text" />
{/each}

固有尺寸

widthheight 是可選的,因為它們可以從源圖像中推斷出來,並且在預處理 <enhanced:img> 標籤時會自動添加。有了這些屬性,瀏覽器可以保留正確的空間,防止佈局偏移。

如果你想使用不同的 widthheight,你可以用 CSS 來設置圖像樣式。由於預處理器會為你添加 widthheight,如果你想要其中一個尺寸自動計算,那麼你需要指定這一點:

<style>
  .hero-image img {
    width: var(--size);
    height: auto;
  }
</style>

srcsetsizes

如果你有一個大圖像,比如佔據設計寬度的主圖,你應該指定 sizes,這樣在較小的設備上就會請求較小版本的圖像。例如,如果你有一個 1280px 的圖像,你可能想要指定類似這樣的內容:

<enhanced:img src="./image.png" sizes="min(1280px, 100vw)"/>

如果指定了 sizes<enhanced:img> 將為較小的設備生成小尺寸圖片,並填充 srcset 屬性。

自動生成的最小圖片寬度為 540px。如果你需要更小的圖片或想要指定自定義寬度,可以使用 w 查詢參數:

<enhanced:img
  src="./image.png?w=1280;640;400"
  sizes="(min-width:1920px) 1280px, (min-width:1080px) 640px, (min-width:768px) 400px"
/>

如果未提供 sizes,則將生成一個 HiDPI/Retina 圖像和一個標準分辨率圖像。您提供的圖像應該是您希望顯示分辨率的 2 倍,以便瀏覽器可以在具有高設備像素比的設備上顯示該圖像。

每個圖像的轉換

默認情況下,增強的圖像將被轉換為更高效的格式。但是,你可能希望應用其他轉換,如模糊、質量調整、扁平化或旋轉操作。你可以通過附加查詢字符串來執行每個圖像的轉換:

<enhanced:img src="./path/to/your/image.jpg?blur=15" alt="An alt text" />

查看 imagetools 倉庫以獲取完整的指令列表。.

從 CDN 動態加載圖片

在某些情況下,圖片在構建時可能無法訪問 —— 例如,它們可能存儲在內容管理系統或其他地方。

使用內容分發網絡(CDN)可以讓你動態優化這些圖片,並在尺寸方面提供更多靈活性,但可能需要一些設置開銷和使用成本。根據緩存策略,在從 CDN 收到 304 響應之前,瀏覽器可能無法使用資源的緩存副本。構建面向 CDN 的 HTML 允許使用 <img> 標籤,因為 CDN 可以根據 User-Agent 頭部提供適當的格式,而構建時優化必須生成帶有多個源的 <picture> 標籤。最後,某些 CDN 可能會延遲生成圖片,這可能會對低流量且圖片頻繁更改的網站的性能產生負面影響。

CDN 通常可以直接使用,無需任何庫。然而,有許多支持 Svelte 的庫可以讓使用變得更簡單。@unpic/svelte 是一個支持大量提供商的與 CDN 無關的庫。你可能還會發現一些特定的 CDN(如 Cloudinary)有 Svelte 支持。最後,一些支持 Svelte 的內容管理系統(CMS)(如 Contentful、Storyblok 和 Contentstack 都內置了圖像處理支持。

最佳實踐

  • 對於每種圖片類型,使用上述討論過的適當解決方案。你可以在一個項目中混合使用這三種解決方案。例如,你可以使用 Vite 的內置處理來為 <meta> 標籤提供圖片,使用 @sveltejs/enhanced-img 在主頁上顯示圖片,並使用動態方法顯示用户提交的內容。
  • 考慮通過 CDN 提供所有圖片服務,無論你使用何種圖片優化類型。CDN 通過在全球分發靜態資源副本來減少延遲。
  • 原始圖片應具有良好的質量/分辨率,並且寬度應該是顯示寬度的 2 倍,以便支持 HiDPI 設備。圖片處理可以將圖片尺寸縮小以在服務較小屏幕時節省帶寬,但為了放大圖片而創造像素會浪費帶寬。
  • 對於遠大於移動設備寬度(大約400px)的圖片,例如佔據頁面設計寬度的主圖,指定 sizes 以便在較小設備上提供較小的圖片。
  • 對於重要圖片,例如最大內容繪製(LCP)圖片,設置 fetchpriority="high" loading="eager" 以儘早優先加載。
  • 為圖片提供容器或樣式,使其受到約束,不會在頁面加載時跳動影響累積佈局偏移(CLS)。widthheight 幫助瀏覽器在圖片仍在加載時預留空間,因此 @sveltejs/enhanced-img 將為你添加 widthheight
  • 始終提供良好的 alt 文本。如果你沒有這樣做,Svelte編譯器會發出警告。
  • 不要在 sizes 中使用 emrem 並更改這些度量的默認大小。當在 sizes@media 查詢中使用時,emrem 都被定義為用户的默認 font-size。對於像 sizes="(min-width: 768px) min(100vw, 108rem), 64rem" 這樣的 sizes 聲明,控制圖片在頁面上佈局方式的實際 emrem 如果被 CSS 更改可能會有所不同。例如,不要做類似 html { font-size: 62.5%; } 這樣的事情,因為瀏覽器預加載器預留的空間現在會比創建後的 CSS 對象模型的實際空間更大。

Svelte 中文文檔

點擊查看中文文檔:SvelteKit 圖片

系統學習 Svelte,歡迎入手小冊《Svelte 開發指南》。語法篇、實戰篇、原理篇三大篇章帶你係統掌握 Svelte!

此外我還寫過 JavaScript 系列、TypeScript 系列、React 系列、Next.js 系列、冴羽答讀者問等 14 個系列文章, 全系列文章目錄:https://github.com/mqyqingfeng/Blog

歡迎圍觀我的“網頁版朋友圈”、加入“冴羽·成長陪伴社羣”,踏上“前端大佬成長之路”。

Add a new Comments

Some HTML is okay.