1

我打算在我的下一个项目中使用 Laravel 框架。到目前为止,我陷入了组织项目中静态内容(图像、脚本等)的链接。例如,我有这个缓存选项(缓存所有静态文件,nginx):

location ~* \.(jpg|jpeg|gif|css|png|js|ico|html)$ {
    expires max;
}

如何创建指向文件 main.js 的链接?如果文件被修改,如何告诉代理文件已过期?

在我当前的项目中,我有版本控制系统,它使用文件修改时间来生成文件的唯一前缀。所以链接就像http://site.com/22566223435/js/main.js下次文件更改时链接会自动更改。

Laravel 中实现此功能的最佳实践是什么?谢谢!

4

1 回答 1

5

我会把它作为一个查询字符串来做,它很简单,足够准确,不需要任何复杂的层来实现。只需将文件的最后修改作为查询字符串放在其链接上。这将强制浏览器刷新文件。

<link rel="stylesheet" type="text/css" href="/css/style.min.css?v=<?= File::modified(path('public').'/css/style.min.css') ?>" />

为了简化这一点,您可以创建一个简单的类来生成文件链接并缓存最后的修改以提高性能。如果您使用 LESS 编译器上的自定义函数,它也可以实现。

现在,关于服务器缓存,如果您的应用程序有很多用户可以真正从中受益,那么您应该研究 CDN,它还可以处理全球分布,并且可以与该查询字符串系统完美配合。

编辑:

也可以使用 Apache 上的 RewriteRules 来解决这个问题(没有任何使用 nginx 的经验来帮助解决这个问题)。用于生成查询字符串的相同技术,您可以用来生成 URI 的前缀(或后缀)。

您可以尝试的另一件事是定义一个主要用于处理静态资产的子域,例如assets.example.com. 这个域可以完全由没有 Laravel 堆栈的网络服务器处理。但这在很大程度上取决于您的资产是如何在整个项目中开发、编译和使用的。

我们的方法:

在我们公司,我们将 CloudFront 和 S3 用于数据库实体资产。每个实体都有自己的 S3 目录,每个资产都通过唯一的文件名进行版本控制(由 md5 生成,这避免了重新上传资产的重复)。就像是:

/posts/876/060b90d67ac0c5e24da6de6ae547e3b1.jpg

我们还在 CloudFront 上定义了 10 个子域,因此浏览器不会达到同一域的 6-8 个并发请求的限制:

cdn0.example.com
cdn1.example.com
cdn2.example.com
... and so on

我们数据库中的每个条目都使用通过计算选择的专有子域resource.id % 10,这非常快,并且总是为每个实体返回相同的子域(帮助客户端和 CloudFront 缓存)。这是提供图像的最佳选择。

UI 图像存储在一个专有的子域中assets.example.com,并且到目前为止还没有版本化,因为我们不会对设计进行太多更改,如果我们这样做了,我们可能会将新资产放在一个/v2//newthemename/文件夹之类的东西中。这种方法对回滚甚至用户选择的主题有很大帮助。

CSS and JS are served by Apache from within Laravel /public directory. This is not the fastest way, but since we are focused on development right now, having automatic compiling of LESS and Closure is far more important. When we launch for end users, we will probably think of an automated deploy system which compiles assets, publishes them on S3/CloudFront with a timestamp prefix and caches their last timestamp for view rendering.

于 2013-03-11T15:47:37.463 回答