非糊涂人 發表於 2025-4-17 21:02:00

SvelteKit 最新中文文档教程(21)—— 最佳实践之图片

<h2 id="前言">前言</h2>
<p>Svelte,一个语法简洁、入门容易,面向未来的前端框架。</p>
<p>从 Svelte 诞生之初,就备受开发者的喜爱,根据统计,<strong>从 2019 年到 2024 年,连续 6 年一直是开发者最感兴趣的前端框架 No.1</strong>:</p>
<p><img src="https://yayujs-blog.oss-cn-beijing.aliyuncs.com/405488775-48df16b1-939c-489b-8d52-6071869893f0.png"></p>
<p>Svelte 以其独特的编译时优化机制著称,具有<strong>轻量级</strong>、<strong>高性能</strong>、<strong>易上手</strong>等特性,<strong>非常适合构建轻量级 Web 项目</strong>。</p>
<p>为了帮助大家学习 Svelte,我同时搭建了 Svelte 最新的中文文档站点。</p>
<p>如果需要进阶学习,也可以入手我的小册《Svelte 开发指南》,语法篇、实战篇、原理篇三大篇章带你系统掌握 Svelte!</p>
<p>欢迎围观我的“网页版朋友圈”、加入“冴羽·成长陪伴社群”,踏上“前端大佬成长之路”。</p>
<h2 id="图片">图片</h2>
<p>图片会对您的应用性能产生重大影响。为了获得最佳效果,您应该通过以下方式优化它们:</p>
<ul>
<li>生成最优格式如 <code>.avif</code> 和 <code>.webp</code></li>
<li>为不同的屏幕创建不同尺寸的图片</li>
<li>确保资源可以被有效缓存</li>
</ul>
<p>手动完成这些工作很繁琐。根据您的需求和偏好,您可以使用多种技术。</p>
<h2 id="vite-的内置处理">Vite 的内置处理</h2>
<p>Vite 会自动处理导入的资源以提升性能。这包括通过 CSS <code>url()</code> 函数引用的资源。文件名中会添加哈希值以便缓存,小于 <code>assetsInlineLimit</code> 的资源会被内联。Vite 的资源处理最常用于图片,但对视频、音频等也很有用。</p>
<pre><code class="language-svelte">&lt;script&gt;
import logo from '$lib/assets/logo.png';
&lt;/script&gt;

&lt;img alt="项目标志" src={logo} /&gt;
</code></pre>
<h2 id="sveltejsenhanced-img">@sveltejs/enhanced-img</h2>
<p><code>@sveltejs/enhanced-img</code> 是在 Vite 内置资源处理基础上提供的插件。它提供即插即用的图片处理功能,可以提供更小的文件格式如 <code>avif</code> 或 <code>webp</code>,自动设置图片的固有 <code>width</code> 和 <code>height</code> 以避免布局偏移,为各种设备创建多种尺寸的图片,并出于隐私考虑去除 EXIF 数据。它可以在任何基于 Vite 的项目中使用,包括但不限于 SvelteKit 项目。</p>
<blockquote>
<p>[!NOTE] 作为构建插件,<code>@sveltejs/enhanced-img</code> 只能在构建过程中优化位于您机器上的文件。如果您的图片位于其他位置(如从数据库、CMS 或后端服务的路径),请阅读从 CDN 动态加载图片。</p>
<p><strong>警告</strong>:<code>@sveltejs/enhanced-img</code> 包是实验性的。它使用 1.0 之前的版本号,每个小版本发布可能会引入破坏性变更。</p>
</blockquote>
<h3 id="设置">设置</h3>
<p>安装:</p>
<pre><code class="language-bash">npm install --save-dev @sveltejs/enhanced-img
</code></pre>
<p>调整 <code>vite.config.js</code>:</p>
<pre><code class="language-js">import { sveltekit } from '@sveltejs/kit/vite';
+++import { enhancedImages } from '@sveltejs/enhanced-img';+++
import { defineConfig } from 'vite';

export default defineConfig({
plugins: [
    +++enhancedImages(),+++
    sveltekit()
]
});
</code></pre>
<p>由于转换图片的计算开销,第一次构建会花费更长时间。但是,构建输出会被缓存在 <code>./node_modules/.cache/imagetools</code> 中,因此后续的构建会很快。</p>
<h3 id="基本用法">基本用法</h3>
<p>在你的 <code>.svelte</code> 组件中使用 <code>&lt;enhanced:img&gt;</code> 而不是<code>&lt;img&gt;</code>,并通过 Vite 资源导入 路径引用图片文件:</p>
<pre><code class="language-svelte">&lt;enhanced:img src="./path/to/your/image.jpg" alt="An alt text" /&gt;
</code></pre>
<p>在构建时,您的 <code>&lt;enhanced:img&gt;</code> 标签将被 <code>&lt;img&gt;</code> 替换,并由 <code>&lt;picture&gt;</code> 包装,提供多种图片类型和尺寸。在不损失质量的情况下只能对图片进行缩小,这意味着你应该提供所需的最高分辨率图片——系统会为可能请求图片的各种设备类型生成较小的版本。</p>
<p>你应该为 HiDPI 显示器(又称视网膜显示器)提供 2x 分辨率的图片。<code>&lt;enhanced:img&gt;</code> 会自动负责向较小的设备提供较小版本的图片。</p>
<p>如果你想为 <code>&lt;enhanced:img&gt;</code> 添加样式,你应该添加一个 <code>class</code> 并针对它进行设置。</p>
<h3 id="动态选择图像">动态选择图像</h3>
<p>您也可以手动导入图片资源并将其传递给 <code>&lt;enhanced:img&gt;</code>。当您有一组静态图片并想要动态选择或遍历它们时,这种方法很有用。在这种情况下,您需要同时更新 <code>import</code> 语句和 <code>&lt;img&gt;</code> 元素,如下所示,以表明您想要处理它们。</p>
<pre><code class="language-svelte">&lt;script&gt;
import MyImage from './path/to/your/image.jpg?enhanced';
&lt;/script&gt;

&lt;enhanced:img src={MyImage} alt="some alt text" /&gt;
</code></pre>
<p>你也可以使用 Vite 的 import.meta.glob。请注意,你需要通过自定义查询来指定 <code>enhanced</code>:</p>
<pre><code class="language-svelte">&lt;script&gt;
const imageModules = import.meta.glob(
    '/path/to/assets/*.{avif,gif,heif,jpeg,jpg,png,tiff,webp,svg}',
    {
      eager: true,
      query: {
      enhanced: true
      }
    }
)
&lt;/script&gt;

{#each Object.entries(imageModules) as }
&lt;enhanced:img src={module.default} alt="some alt text" /&gt;
{/each}
</code></pre>
<h3 id="固有尺寸">固有尺寸</h3>
<p><code>width</code> 和 <code>height</code> 是可选的,因为它们可以从源图像中推断出来,并且在预处理 <code>&lt;enhanced:img&gt;</code> 标签时会自动添加。有了这些属性,浏览器可以保留正确的空间,防止布局偏移。</p>
<p>如果你想使用不同的 <code>width</code> 和 <code>height</code>,你可以用 CSS 来设置图像样式。由于预处理器会为你添加 <code>width</code> 和 <code>height</code>,如果你想要其中一个尺寸自动计算,那么你需要指定这一点:</p>
<pre><code class="language-svelte">&lt;style&gt;
.hero-image img {
    width: var(--size);
    height: auto;
}
&lt;/style&gt;
</code></pre>
<h3 id="srcset-和-sizes"><code>srcset</code> 和 <code>sizes</code></h3>
<p>如果你有一个大图像,比如占据设计宽度的主图,你应该指定 <code>sizes</code>,这样在较小的设备上就会请求较小版本的图像。例如,如果你有一个 1280px 的图像,你可能想要指定类似这样的内容:</p>
<pre><code class="language-svelte">&lt;enhanced:img src="./image.png" sizes="min(1280px, 100vw)"/&gt;
</code></pre>
<p>如果指定了 <code>sizes</code>,<code>&lt;enhanced:img&gt;</code> 将为较小的设备生成小尺寸图片,并填充 <code>srcset</code> 属性。</p>
<p>自动生成的最小图片宽度为 540px。如果你需要更小的图片或想要指定自定义宽度,可以使用 <code>w</code> 查询参数:</p>
<pre><code class="language-svelte">&lt;enhanced:img
src="./image.png?w=1280;640;400"
sizes="(min-width:1920px) 1280px, (min-width:1080px) 640px, (min-width:768px) 400px"
/&gt;
</code></pre>
<p>如果未提供 <code>sizes</code>,则将生成一个 HiDPI/Retina 图像和一个标准分辨率图像。您提供的图像应该是您希望显示分辨率的 2 倍,以便浏览器可以在具有高设备像素比的设备上显示该图像。</p>
<h3 id="每个图像的转换">每个图像的转换</h3>
<p>默认情况下,增强的图像将被转换为更高效的格式。但是,你可能希望应用其他转换,如模糊、质量调整、扁平化或旋转操作。你可以通过附加查询字符串来执行每个图像的转换:</p>
<pre><code class="language-svelte">&lt;enhanced:img src="./path/to/your/image.jpg?blur=15" alt="An alt text" /&gt;
</code></pre>
<p>查看 imagetools 仓库以获取完整的指令列表。.</p>
<h2 id="从-cdn-动态加载图片">从 CDN 动态加载图片</h2>
<p>在某些情况下,图片在构建时可能无法访问 —— 例如,它们可能存储在内容管理系统或其他地方。</p>
<p>使用内容分发网络(CDN)可以让你动态优化这些图片,并在尺寸方面提供更多灵活性,但可能需要一些设置开销和使用成本。根据缓存策略,在从 CDN 收到 304 响应之前,浏览器可能无法使用资源的缓存副本。构建面向 CDN 的 HTML 允许使用 <code>&lt;img&gt;</code> 标签,因为 CDN 可以根据 <code>User-Agent</code> 头部提供适当的格式,而构建时优化必须生成带有多个源的 <code>&lt;picture&gt;</code> 标签。最后,某些 CDN 可能会延迟生成图片,这可能会对低流量且图片频繁更改的网站的性能产生负面影响。</p>
<p>CDN 通常可以直接使用,无需任何库。然而,有许多支持 Svelte 的库可以让使用变得更简单。<code>@unpic/svelte</code> 是一个支持大量提供商的与 CDN 无关的库。你可能还会发现一些特定的 CDN(如 Cloudinary)有 Svelte 支持。最后,一些支持 Svelte 的内容管理系统(CMS)(如 Contentful、Storyblok 和 Contentstack 都内置了图像处理支持。</p>
<h2 id="最佳实践">最佳实践</h2>
<ul>
<li>对于每种图片类型,使用上述讨论过的适当解决方案。你可以在一个项目中混合使用这三种解决方案。例如,你可以使用 Vite 的内置处理来为 <code>&lt;meta&gt;</code> 标签提供图片,使用 <code>@sveltejs/enhanced-img</code> 在主页上显示图片,并使用动态方法显示用户提交的内容。</li>
<li>考虑通过 CDN 提供所有图片服务,无论你使用何种图片优化类型。CDN 通过在全球分发静态资源副本来减少延迟。</li>
<li>原始图片应具有良好的质量/分辨率,并且宽度应该是显示宽度的 2 倍,以便支持 HiDPI 设备。图片处理可以将图片尺寸缩小以在服务较小屏幕时节省带宽,但为了放大图片而创造像素会浪费带宽。</li>
<li>对于远大于移动设备宽度(大约400px)的图片,例如占据页面设计宽度的主图,指定 <code>sizes</code> 以便在较小设备上提供较小的图片。</li>
<li>对于重要图片,例如最大内容绘制(LCP)图片,设置 <code>fetchpriority="high" loading="eager"</code> 以尽早优先加载。</li>
<li>为图片提供容器或样式,使其受到约束,不会在页面加载时跳动影响累积布局偏移(CLS)。<code>width</code> 和 <code>height</code> 帮助浏览器在图片仍在加载时预留空间,因此 <code>@sveltejs/enhanced-img</code> 将为你添加 <code>width</code> 和 <code>height</code>。</li>
<li>始终提供良好的 <code>alt</code> 文本。如果你没有这样做,Svelte编译器会发出警告。</li>
<li>不要在 <code>sizes</code> 中使用 <code>em</code> 或 <code>rem</code> 并更改这些度量的默认大小。当在 <code>sizes</code> 或 <code>@media</code> 查询中使用时,<code>em</code> 和 <code>rem</code> 都被定义为用户的默认 <code>font-size</code>。对于像 <code>sizes="(min-width: 768px) min(100vw, 108rem), 64rem"</code> 这样的 <code>sizes</code> 声明,控制图片在页面上布局方式的实际 <code>em</code> 或 <code>rem</code> 如果被 CSS 更改可能会有所不同。例如,不要做类似 <code>html { font-size: 62.5%; }</code> 这样的事情,因为浏览器预加载器预留的空间现在会比创建后的 CSS 对象模型的实际空间更大。</li>
</ul>
<h2 id="svelte-中文文档">Svelte 中文文档</h2>
<p>点击查看中文文档:SvelteKit 图片</p>
<p>系统学习 Svelte,欢迎入手小册《Svelte 开发指南》。语法篇、实战篇、原理篇三大篇章带你系统掌握 Svelte!</p>
<p>此外我还写过 JavaScript 系列、TypeScript 系列、React 系列、Next.js 系列、冴羽答读者问等 14 个系列文章, 全系列文章目录:https://github.com/mqyqingfeng/Blog</p>
<p>欢迎围观我的“网页版朋友圈”、加入“冴羽·成长陪伴社群”,踏上“前端大佬成长之路”。</p><br><br>
来源:https://www.cnblogs.com/yayujs/p/18831638
頁: [1]
查看完整版本: SvelteKit 最新中文文档教程(21)—— 最佳实践之图片