在Laravel中使用HTTP缓存,静态文件路径生成



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

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

我怎么做一个链接到文件main.js?如果文件被修改了,如何告诉代理文件过期?

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

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

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

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

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

现在,关于服务器缓存,如果你的应用程序有很多用户真正从中受益,你应该看看CDN,它也处理全球分布,将与查询字符串系统很好地工作。

编辑:

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

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

我们的方法:

在我们公司,我们使用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和JS由Apache从Laravel /public目录中提供。这不是最快的方法,但由于我们现在专注于开发,因此自动编译LESS和Closure更为重要。当我们为最终用户启动时,我们可能会想到一个自动部署系统,它编译资源,在S3/CloudFront上发布它们,并带有时间戳前缀,并缓存它们的最后时间戳用于视图渲染。

最新更新