这篇文章讨论的是一种非常具体的技术组合——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 重定向来实现这一点
然后,本地开发的诀窍是捕获 404 错误并 使用更多重定向将它们重定向到本地。
如果手动编写自己的响应式图像语法太麻烦(确实如此),我强烈建议对其进行抽象。在 Eleventy 中,Nicolas Hoizey 有一个项目:eleventy-plugin-images-responsiver。Eric Portis 也开发了一个项目,eleventy-respimg,它专门使用 Cloudinary,就像我这里所做的那样。
为了证明这件事确实一直萦绕在人们心头,Tim Kadlec 刚刚发表了一篇博文 “使用 Netlify 代理 Cloudinary 请求。” 他扩展了 Phil 的推文,增加了一些额外的性能背景和注意事项。
或者您可以稍微修改一下 browsersync-images-middleware,无论是否在 Eleventy 的世界中!
这意味着您不必 – 至少目前 – 使用任何特定的 CDN。