使用 Eleventy 和 Cloudinary Fetch(兼顾本地开发)

Avatar of Chris Coyier
Chris Coyier

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

这篇文章讨论的是一种非常具体的技术组合——Eleventy(静态网站生成器),其页面包含图像,而您最终希望这些图像由 Cloudinary 托管——但我只是想记录一下,因为听起来很多人都会遇到这种情况。

问题

  • Cloudinary 具有 Fetch URL 功能,这意味着您实际上无需学习任何东西(很棒!)即可使用他们的服务。您需要拥有一个帐户,但之后只需在图像前面加上 Cloudinary URL,然后 Cloudinary 就会优化、调整大小、格式化和通过 CDN 提供您的图像。太棒了。它并不是唯一提供此功能的服务,但它是一个不错的选择。
  • 但是……图像需要位于公共互联网上。在开发环境中,您的图像 URL 可能并非如此。它们可能存储在本地。因此,理想情况下,我们可以在开发环境中继续使用本地 URL,并在生产环境中使用 Cloudinary Fetch。

很多人以不同的方式解决了这个问题。我将记录我如何解决它(因为我最了解它),但也会链接一些其他人如何解决它(这可能更聪明,由您判断)。

目标

  • 在开发环境中,图像类似于 /images/image.png
  • 在生产环境中,图像类似于 https://res.cloudinary.com/css-tricks/image/fetch/w_1200,q_auto,f_auto/https://production-website.com/images/image.png

因此,如果我们要对其进行模板化(假设这里使用 Nunjucks,因为它是一种 Eleventy 支持的不错的模板语言),我们会得到类似如下伪代码的内容

<img src="
  {{CLOUDINARY_PREFIX}}{{FULLY_QUALIFIED_PRODUCTION_URL}}{{RELATIVE_IMAGE_URL}}
  "
  alt="Don't screw this up, fam."
/>
开发环境生产环境
{{CLOUDINARY_PREFIX}}“”“https://res.cloudinary.com/css-tricks/image/fetch/w_1200,q_auto,f_auto/”
{{FULLY_QUALIFIED_PRODUCTION_URL}}“”“https://production-website.com”
{{RELATIVE_IMAGE_URL}}“/images/image.jpg”“/images/image.jpg”

然后,诀窍就是获取这些……我想我们会称之为全局变量?……设置它们。可能只需要前两个。您可能只需要根据需要手动编写相对图像路径。

Eleventy 为此提供了一些神奇的功能。我们放在 _data 文件夹中的任何 *.js 文件都将转换为我们可以在模板中使用的变量。因此,如果我们创建了类似 /src/_data/sandwiches.js 的文件,并且它包含以下内容

module.exports = {
  ham: true
}

在我们的模板中,我们可以使用 {{sandwiches.ham}},它将被定义为 {{true}}

因为这是 JavaScript(Node),这意味着我们可以根据其他变量执行一些逻辑。在我们的案例中,一些其他全局变量将很有用,特别是 Node 提供的 process.env 变量。许多主机(Netlify、Vercel 等)都将“环境变量”作为一项可以在其系统中设置的功能,以便 process.env 在其系统上运行构建过程时可以使用它们。我们可以这样做,但这相当具体并且与这些主机绑定。设置 Node 全局变量的另一种方法是在运行命令之前从命令行字面设置它,因此,如果您要执行以下操作

SANDWICH="ham" eleventy

那么 process.env.SANDWICH 将在您的 Node JavaScript 中的任何位置都为 ham。结合所有这些……假设我们的生产构建过程设置了一个指示生产的变量,例如

PROD="true" eleventy

但在本地开发中,我们将使用该全局变量运行。因此,让我们在设置一些要用于构建图像源的全局变量时利用这些信息。在 /src/_data/images.js 中(完整的真实示例),我们将执行以下操作

module.exports = {

  imageLocation:
    process.env.PROD === 'true' 
      ? 'https://coding-fonts.css-tricks.com' 
      : '',

  urlPrefix:
    process.env.PROD === 'true'
      ? 'https://res.cloudinary.com/css-tricks/image/fetch/w_1600,q_auto,f_auto/'
      : ''

};

您还可以检查 process.env.CONTEXT === 'deploy-preview' 以测试 Netlify 部署预览 URL,以防您想以某种方式更改那里的逻辑。

现在,在我们的任何模板中,我们都可以使用 {{images.imageLocation}}{{images.urlPrefix}} 来构建源。

<img 
  src="
    {{images.urlPrefixLarge}}{{images.imageLocation}}/image.png
  "
  alt="Useful alternative text."
/>

就是这样。这将在开发环境中成为本地/相对源,然后在生产环境中,它将成为 Cloudinary Fetch 将使用的此前缀和完整限定的 URL。

现在它已在 Cloudinary 上,我们可以更进一步。可以调整前缀 URL 以调整图像大小,这意味着即使只有一个源图像,我们也可以为 响应式图像 创建一个相当合适的设置。这是 该设置,它提供了多个前缀,因此 可以将其用于完整语法。

最终结果意味着在开发环境中使用本地相对图像

多个版本在开发环境中是假的,但没关系,srcset 算是生产环境的问题。

……以及在生产环境中使用 Cloudinary Fetch URL

其他人的想法

Phil 前几天展示了如何使用 Netlify 重定向来实现这一点

https://twitter.com/philhawksworth/status/1328340868726726656

然后,本地开发的诀窍是捕获 404 错误并 使用更多重定向将它们重定向到本地

如果手动编写自己的响应式图像语法太麻烦(确实如此),我强烈建议对其进行抽象。在 Eleventy 中,Nicolas Hoizey 有一个项目:eleventy-plugin-images-responsiver。Eric Portis 也开发了一个项目,eleventy-respimg,它专门使用 Cloudinary,就像我这里所做的那样。

为了证明这件事确实一直萦绕在人们心头,Tim Kadlec 刚刚发表了一篇博文 “使用 Netlify 代理 Cloudinary 请求。” 他扩展了 Phil 的推文,增加了一些额外的性能背景和注意事项。