Gatsby - 防止小图像被内联为数据 URI
Gatsby - Prevent small images from being inlined as a data URI
我正在尝试为我的 head
标签中的每个 apple-touch-icon
尺寸提供图像。我这样做是这样的:
// not shown: import all image files: logo57, logo76, etc
<link rel="apple-touch-icon" sizes="57x57" href={logo57} />
<link rel="apple-touch-icon" sizes="76x76" href={logo76} />
<link rel="apple-touch-icon" sizes="120x120" href={logo120} />
<link rel="apple-touch-icon" sizes="152x152" href={logo152} />
<link rel="apple-touch-icon" sizes="167x167" href={logo167} />
<link rel="apple-touch-icon" sizes="180x180" href={logo180} />
问题是在呈现页面时,所有这些图像都直接包含在页面中作为数据 URI 中的 base 64,而不是相对 URL。像这样:
<link rel="apple-touch-icon" sizes="180x180" href="data:image/png;base64,iVBORw0KGgoAAAA....">
由于某些原因,这是有问题的。其一,这些图像仅在渐进式 Web 应用场景中才需要;普通桌面浏览器不需要它们,但桌面浏览器被迫下载所有这些 base 64 块,从而减慢页面加载速度。其次,即使在 PWA 场景中,每个设备也只需要这些图像中的一个,而不是所有图像,因此页面加载时间也会变慢。
这是针对小于 10,000 字节的图像的优化记录,因此将它们全部加载到此处可能是一个可以忽略不计的差异。但是,原始 png 的总大小约为 27kb(转换为 base 64 后我不知道),如果不需要,我似乎宁愿不在每个页面中包含这些数据。
我发现我可以将图像全部移动到 /static 文件夹并使用 href="logo57.png"
引用它们,但是我失去了编译时验证这些图像实际上存在于给定的 href ,以及在文件名中包含图像哈希(出于缓存原因)。
如何告诉 Gatsby 不要将这些图像作为数据 URI 直接内联到页面中?
您不应将这些资源 (import x from "..."
) 使用 Webpack,而应将它们放在 static
文件夹中并直接引用它们。如果您的 Gatsby 站点没有前缀(即 index.js
文件由 /
提供),那么您可以对路径进行硬编码(例如 href="/favicon.png"
)。否则,您需要使用 withPrefix 在生产中提供前缀。
您也可以为此使用 GraphQL。例如,如果您的徽标位于名为 images 的文件夹中,您的代码将如下所示:
const data = useStaticQuery(graphql`
query Logo {
file(absolutePath: { regex: "/images/logo.png/" }) {
publicURL
}
}
`)
return <link rel="apple-touch-icon" sizes="57x57" href={data.file.publicURL} />
请注意,您需要使用 gatsby-source-filesystem
才能在 GraphQL 中使用您的图像。它已经被 Gatsby 内部使用,所以不需要安装它。只需将其添加到您的 gatsby-config.js
:
module.exports = {
plugins: [
{ resolve: `gatsby-source-filesystem`, options: { path: `${__dirname}/src/images` } },
// other plugins here...
],
}
我正在尝试为我的 head
标签中的每个 apple-touch-icon
尺寸提供图像。我这样做是这样的:
// not shown: import all image files: logo57, logo76, etc
<link rel="apple-touch-icon" sizes="57x57" href={logo57} />
<link rel="apple-touch-icon" sizes="76x76" href={logo76} />
<link rel="apple-touch-icon" sizes="120x120" href={logo120} />
<link rel="apple-touch-icon" sizes="152x152" href={logo152} />
<link rel="apple-touch-icon" sizes="167x167" href={logo167} />
<link rel="apple-touch-icon" sizes="180x180" href={logo180} />
问题是在呈现页面时,所有这些图像都直接包含在页面中作为数据 URI 中的 base 64,而不是相对 URL。像这样:
<link rel="apple-touch-icon" sizes="180x180" href="data:image/png;base64,iVBORw0KGgoAAAA....">
由于某些原因,这是有问题的。其一,这些图像仅在渐进式 Web 应用场景中才需要;普通桌面浏览器不需要它们,但桌面浏览器被迫下载所有这些 base 64 块,从而减慢页面加载速度。其次,即使在 PWA 场景中,每个设备也只需要这些图像中的一个,而不是所有图像,因此页面加载时间也会变慢。
这是针对小于 10,000 字节的图像的优化记录,因此将它们全部加载到此处可能是一个可以忽略不计的差异。但是,原始 png 的总大小约为 27kb(转换为 base 64 后我不知道),如果不需要,我似乎宁愿不在每个页面中包含这些数据。
我发现我可以将图像全部移动到 /static 文件夹并使用 href="logo57.png"
引用它们,但是我失去了编译时验证这些图像实际上存在于给定的 href ,以及在文件名中包含图像哈希(出于缓存原因)。
如何告诉 Gatsby 不要将这些图像作为数据 URI 直接内联到页面中?
您不应将这些资源 (import x from "..."
) 使用 Webpack,而应将它们放在 static
文件夹中并直接引用它们。如果您的 Gatsby 站点没有前缀(即 index.js
文件由 /
提供),那么您可以对路径进行硬编码(例如 href="/favicon.png"
)。否则,您需要使用 withPrefix 在生产中提供前缀。
您也可以为此使用 GraphQL。例如,如果您的徽标位于名为 images 的文件夹中,您的代码将如下所示:
const data = useStaticQuery(graphql`
query Logo {
file(absolutePath: { regex: "/images/logo.png/" }) {
publicURL
}
}
`)
return <link rel="apple-touch-icon" sizes="57x57" href={data.file.publicURL} />
请注意,您需要使用 gatsby-source-filesystem
才能在 GraphQL 中使用您的图像。它已经被 Gatsby 内部使用,所以不需要安装它。只需将其添加到您的 gatsby-config.js
:
module.exports = {
plugins: [
{ resolve: `gatsby-source-filesystem`, options: { path: `${__dirname}/src/images` } },
// other plugins here...
],
}