如果您在 Web 开发领域工作了一段时间,您就会知道 Web 需要速度。事实很简单:速度很重要,更快被认为更好。
提高性能的一个“简单方法”是使用CDN。我们在 CSS-Tricks 中已经多次讨论过这个问题。它很简单,因为您不需要重写代码库或手动编辑内容,但这是我们许多人可能会忽略的性能领域,因为,嗯,托管、服务器和 cPanel,哦,我的天哪!
值得庆幸的是,集成 CDN 的过程并不一定很困难。理想情况下,您将配置好这些内容,然后像 Google PageSpeed 这样的工具会以高性能分数的形式发出欢呼声,这反过来又会带来更好的搜索引擎排名、更高的收入、您的加薪等等……您明白了。
这篇文章将介绍为自定义 Web 应用程序设置 CDN 的过程,以及一些我们可以用来充分利用我们工作的技巧。正如我所说,它并不一定很困难,所以让我们深入研究,让 Web 更快吧!
值得注意的是,对于使用 WordPress 等 CMS 的用户来说,设置 CDN 可能比我们这里介绍的要简单,因为插件可以帮助完成这项工作。我们将假设并非所有人都享有这种便利(向 Web 应用程序致敬!),并以更传统的方式进行操作。
等等,你讲到 CDN 的时候我就听不懂了
我们回顾一下 CDN 的基本概念以及它们的使用目的,从这里开始。
CDN 的工作原理是,从您的网站服务器获取静态资源并将它们缓存在其服务器上。当浏览器请求访问您的网站时,静态内容将通过 CDN 提供,而不是通过您的网站提供。这样做速度更快,因为 CDN 服务器在全球范围内分布,并充当代理,确定哪个服务器物理上最靠近您的访问者,从而以更快的、更便捷的网络提供内容。因此,它的全称是:内容分发网络。

那么,浏览器如何知道从 CDN 获取资源而不是从您的服务器获取资源呢?您的静态资源的 URL 将被替换为指向 CDN 服务器,而不是指向您自己网站的 URL。
例如,假设我们希望 CDN 被配置为子域。对于 CSS-Tricks,它可能是类似于 cdn.css-tricks.com
的内容,这将是我们所有资产的相对 URL 基础。
简而言之,我们网站上像这样的资产的 URL
https://css-tricks.org.cn/image.jpg
https://css-tricks.org.cn/style.css
https://css-tricks.org.cn/script.js
…将变成
http://cdn.css-tricks.com/image.jpg
http://cdn.css-tricks.com/style.css
http://cdn.css-tricks.com/script.js
浏览器向您的 CDN 发送请求,而不是向您的服务器发送请求,从而减轻服务器的负载,并最终使您的整个网站更快。
等等,一个网站用两台服务器?
是的,在某种程度上,但这并不意味着您要管理两台服务器。
我们实际上是在讨论使用 CDN 作为虚拟层,它位于您的服务器和用户的浏览器之间。该虚拟层监听浏览器向您的服务器发送的请求,并乐于代表服务器使用缓存的资产进行响应。
在某些情况下,您可能直接将资产上传到 CDN,并将所有负担从您的服务器上卸下。我们将在本文中讨论的是一个流程,其中 CDN 从您的服务器获取资产并预先缓存它们,因此不需要上传到不同的服务器并管理多个位置。
如何在自定义应用程序上实现 CDN
两个最广泛使用的 CDN 服务是 Amazon AWS 和 MaxCDN,当然还有许多其他服务可用。我们将重点关注 MaxCDN 作为设置方法的示例。
步骤 1:选择 CDN 并注册您的网站
一旦您决定 CDN 是您 Web 应用程序的最佳选择,您就需要注册一个帐户。有很多很多选项可供选择,而不是权衡每个选项的优缺点(这可能是一个很好的未来文章),这里列出了一些入门选项。
注册帐户时,一个常见的步骤是设置一个**拉取区域**或**分发**。拉取区域或分发由 CDN 作为您日常支持文件的存储桶使用。它将自动从您指定的某个位置拉取数据,以响应对该文件的第一个请求。这些文件将通过您选择的 CDN 的子域或您选择的指向 CDN 的自定义域(子域)提供给最终用户。存储桶中的数据将在可自定义的时间段后从服务器自动清除。
步骤 2:创建您的 CDN URL
您的 CDN URL 是所有资产在设置完成后将指向的 URL。一个好的经验法则是使用一个 URL 名称,该名称易于在您的数据库中对所有现有 URL 进行搜索和替换。
与任何其他子域一样,这需要在您的主机 DNS 设置中作为 CNAME 记录进行设置。

步骤 3:将您的资产指向 CDN
让我们看一下创建 CDN URL 变量的方法,以及如何使用它来帮助以编程方式将 URL 添加到我们的静态资源之前。我们之所以要这样做,是因为 (1) 它可以减少我们在标记中犯错的可能性,以及 (2) 如果我们需要更改 URL,它更容易维护 URL。
我们将通过定义一个全局 CDN 变量来做到这一点,然后将此变量添加到我们的静态资源 URL 之前。我们在 PHP 和 JavaScript 级别都定义了此变量,以便我们在将来使用它时具有更大的灵活性。如果我们决定放弃 CDN,它也使我们更容易操作,因为我们只需用一个简单的 /
替换变量,即可恢复到原始服务器的相对路径。
请注意,以下示例旨在说明示例,而不是字面上的用法。您的实际用法可能有所不同。
<?php
define('cdnURL', 'http://cdn.css-tricks.com/');
?>
<html>
<head>
<title>Hello World!</>
<script type='text/javascript'>
/* Let’s define a javascript global for using the CDN inside scripts */
var cdnURL = '<?php echo cdnURL ?>';
</script>
<link rel='stylesheet' href='<?php echo cdnURL ?>css/style.css' />
</head>
<body>
<img src='<?php echo cdnURL ?>img/logo.png' />
<button>Submit</button>
<script type='text/javascript' src='<?php echo cdnURL ?>js/main.js'></script>
</body>
</html>
或者,在 JavaScript 中完成
(function() {
var preloadImage = document.createElement('img');
preloadImage.src = cdnURL + 'img/logo.png';
})();
这确实需要您作为开发人员稍微改变一下思维方式。每个静态资源都需要在前面加上 cdnURL
变量。
同样的想法也适用于您的 CSS。例如,我们还可以设置一个全局 CDN 变量,并使用 CSS 预处理器(如 LESS)将其添加到我们的 CSS 资源之前
@cdnURL: 'http://cdn.css-tricks.com/';
button {
background-image: url('@{cdnURL}img/button.png');
&:hover {
background-image: url('@{cdnURL}img/button_hover.png');
}
}
…或者 Sass 也是一样的
$cdnURL: 'http://cdn.css-tricks.com/';
button {
background-image: url('#{$cdnURL}img/button.png');
&:hover {
background-image: url('#{$cdnURL}img/button_hover.png');
}
}
最棒的是,您可以通过将 cdnURL
设置为 /
来关闭 CDN,这将重新创建您所有的相对 URL。这还有一个好处,那就是如果您想切换 CDN URL,您只需要更改 cdnURL
即可。
这确实是设置 CDN 的三个步骤,将 CDN 链接到您的服务器,然后将您现有的资产指向它,以便 CDN 可以在被请求时提供这些内容。
让我们谈谈一些高级设置
设置 CDN 并没有那么可怕,对吧?现在我们已经克服了主要的障碍,我们可以玩一些高级设置,优化我们的资产服务方式。
生存时间 (TTL)
CDN 通常会为资产设置一个生存时间 (TTL)。这是一种告诉 CDN 在多久(以秒为单位)内应该将资产视为过期的花哨方式。在那之后,它会在服务器上再次查找“新鲜”的副本。
TTL 越长,该资产的“版本”将在 CDN 中停留的时间越长,并继续被提供。TTL 越短,它就越频繁地放弃存储的资产“版本”,并返回到原始服务器以查找更新的版本。

使资产无效
TTL 的双刃剑是,您可以在服务器上更新资产,但更改不会反映在您的网站上,直到 TTL 到期,CDN 才会再次访问服务器以查找新的副本。
我们可以通过使资产无效来克服这个问题。这里的诀窍是在更新时更改文件名。如果文件名更改,CDN 不会知道任何差别,并将新命名的文件视为一个全新的资产,而不是对现有资产的更新。
换句话说,这个:http://cdn.css-tricks.com/image100.jpg
…将被重命名为类似于:http://cdn.css-tricks.com/image101.jpg
再见旧版本,你好新版本!
利用 TTL 进行版本控制
嘿,所以如果 CDN 保留了资产的一个版本,并且我们的服务器上有一个它还没有获取的最新副本,那么我们实际上有两个相同资产的迭代。我们可以用它来创建一种“版本控制”形式,在服务器上更新资产并不意味着我们自动丢失它们,并且可以在需要时恢复到过去的副本。
真正复杂的做法是在每次更改时重命名所有资源,就像我们在使资产无效时所做的那样。但是,从维护角度来看,即使我们必须为此创建一个变量(就像我们为cdnURL
所做的那样),这也是过分的。我们将进行一些作弊,因为这就是我们在一个以技巧为基础的博客上运作的方式。
我们将从将静态资产放置到它们自己的文件夹中开始,这样一来:http://cdn.css-tricks.com/image.jpg
…变成了这样:http://cdn.css-tricks.com/img100/image.jpg
为了使文件失效并强制 CDN 提供最新版本,我们将修改子目录路径,如下所示:http://cdn.css-tricks.com/img101/image.jpg
看到区别了吗?文件名保持不变,但它现在似乎位于服务器上的目录中。同样,CDN 不会知道任何差别,并将此视为一个全新的文件。我们刚刚创建了一个伪版本控制形式,它直接发生在文件夹中!
但是等等,我们可以做得更好。
每次更新时都更改文件夹上的数字仍然是一个繁琐的过程,并且是维护我们网站的另一个步骤。我们可以做的是对网站的.htaccess
文件进行一些小的更改,以便为我们完成繁重的工作。
我们将通过从同一个文件夹中提供所有资产来欺骗 CDN,但让它看起来像是从版本化的文件夹中提供,这要归功于一些重写规则。
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^ver-[0-9]+.[0-9]+.[0-9]+(.*)$ $1 [L,NC]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?/$1 [QSA,L]
</IfModule>
哈!现在我们的服务器正在 URL 中伪造版本号,同时从服务器上最初上传的同一个路径提供我们的示例image.jpg
资产。
按需使所有资产无效
最后一件要做的事情是将我们的版本控制技巧整合到我们的 HTML 标记中,这样一来,只要我们想要完全使资产失效,CDN 就会刷新所有资产。
我们将设置一个配置文件,在其中定义一个版本号的变量,将该变量导入到我们的资产 URL 结构中,然后在每次想要在整个范围内推送资产刷新时更改版本号。
下面是它在 PHP 配置文件中可能的样子
VERSION
1.0.0
Configure::load('cdn');
define('VERSION', file_get_contents(APP.DS."Config".DS."VERSION"));
define('CDN', Configure::read('CDN.path').VERSION.'/'); /* the trailing slash is important */
下面是它在 LESS 配置文件中可能的样子
@VERSION: '1.0.0';
@import 'cdn';
@import 'version';
@CDNURL: '@{CDN}@{VERSION}/';
button {
background-image: url('@{CDNURL}img/button.png');
&:hover {
background-image: url('@{CDNURL}img/button_hover.png');
}
}
如您所见,您还可以选择将 CDN 变量用作文件、环境变量或任何最适合您的方式。原则基本相同,所有这些都会实现将 CDN URL(和版本号)合并到我们所有外部资源中的预期最终结果。
CDN,FTW!
希望这能消除设置 CDN 的恐惧。它当然看起来是一项艰巨的任务,并且绝对存在一些高级设置,可能会让你迷失在细节中。初始设置是我们大多数人需要的,并且在性能和用户体验方面,以及其他众多方面(双关语)带来了巨大的好处。
事实是,如果您使用流行的 CMS(如 WordPress)管理网站上的内容,那么它会变得更加简单,因为有大量的插件可以进一步简化流程。
即使我们没有插件的优势,设置 CDN 仍然非常简单,即使是那些最不了解托管的人也是如此。设置是最大的障碍,我们已经将其分解为三个基本步骤。其他的事情就顺理成章了。
很棒的解释,我真的对 CDN 不太了解,除了使用库之外,但现在我明白了为什么我访问的很多网站会从 cdn.website.com 等 URL 获取图片。非常感谢,我喜欢这个网站
嘿,Murat,很高兴你发现它对你有用 - 这就是我们的目标!
David
很棒的概述,David。
如果您想使用 Cloudflare 之类的东西,我建议您最好通过它们提供整个网站,而不仅仅是文件资产。
您的资产离请求它们的人更近,从而减少了往返时间,这很好,但如果他们请求的页面也同样靠近,那就更好了。虽然这是特定于 Cloudflare 的,但这可以避免在网站上或通过您的 CSS 重命名任何资产。
再次感谢您发表这篇文章,任何推动更多性能网站的事情都是一件好事。
干杯,
Justin
嘿,Justin,
感谢您的评论 - 很高兴您喜欢这篇文章。
关于 Cloudflare,我确实理解 Cloudfare 是通过提供静态文件资产来工作的,所以我不太确定您指的是提供整个网站是什么意思?您不能通过 Cloudflare 提供动态页面,我不认为他们提供托管服务。
干杯。
David
他们不提供托管,但他们确实会缓存您页面的静态版本(与 Google 的方式非常相似),因此如果您的服务器出现故障,Cloudflare 会显示一条通知,说明这种情况,并表示它正在显示页面的缓存版本。
非常感谢您,David,您用非常简单的语言解释了关于 CDN 的很多内容。我从 CDN 中学到了很多新东西!
Kunal Yadav
嘿,Kunal,很高兴你发现它对你有用!
干杯
David
很酷的东西,David,
简短的话对于所有考虑使用 CDN 的人来说,这是自从切片面包以来最好的事情。我一直怀疑是否应该使用 CDN,即使它会花费我一些钱,但好的是,现在的 CDN 提供免费的积分,这样您就可以随意使用它们,比如 30 天 10 美元积分,我几乎没用完 0.03 美元,哈哈。我们是开发者,我们应该学习新东西,而这正是那些#NoRagrets 之一,因为您将完全从 CDN 中获益,尤其是在您使用“DNS 预取 CDN”将其设置好的情况下。
2 秒就够了!
此致,
Mic
嘿,Mic,
我之前也迟迟没有为我的网站采用 CDN,但它们带来的差别真是太大了——你必须从不同的角度去看待它。与其查看 GTMetrix 等计时网站,不如看看从最终用户角度来看的感觉。
实际上,CDN 从附近位置快速传递大部分内容,网站的加载体验将明显改善。
David
很棒,很准确,很有描述性……恭喜你!
vuchkov.biz
谢谢 Vuchkov!
纤维花盆是兼具美观和实用性的装饰性花盆,适合室内和室外,提升空间的审美和视觉效果。它也是酒店和购物中心青睐的装饰元素,如今已成为各种项目的亮点。作为 Decoratime,我们为客户提供各种颜色选择,制造出适合家居、酒店和购物中心的精美花盆。我们不仅拥有众多装饰性花盆款式,还可以根据您的想法和设计制作纤维花盆。我们的花盆适合各种天气,不会生锈,也不会随着时间推移而变形。凭借精湛的纤维花盆制造技术,我们的产品广受好评,成为最受欢迎的花盆选择之一。优质的纤维花盆价格和款式,尽在 saksi.org。选择纤维花盆,首选 Decoratime!