在 Laravel 中使用 HTTP 缓存,生成静态文件路径
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15337100/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Working with HTTP cache in Laravel, static files path generation
提问by Stanislav
I'm planning to use Laravel framework in my next project. By now i get stuck in organizing links to static content in my project (images, scripts etc.) For example, i have this cache option (do cache all static files, nginx):
我计划在我的下一个项目中使用 Laravel 框架。到目前为止,我一直在组织项目中静态内容的链接(图像、脚本等)。例如,我有这个缓存选项(缓存所有静态文件,nginx):
location ~* \.(jpg|jpeg|gif|css|png|js|ico|html)$ {
expires max;
}
How can i make a link to file main.js? How to tell proxies that file is out of date if it was modified?
如何创建指向文件 main.js 的链接?如果文件被修改,如何告诉代理该文件已过期?
In my current projects i have versioning system wich uses file modification time to generate unique prefix to files. So link would be like http://site.com/22566223435/js/main.jsAnd next time when file change the link change automatically.
在我当前的项目中,我有版本控制系统,它使用文件修改时间来生成文件的唯一前缀。所以链接会像http://site.com/22566223435/js/main.js下次文件更改时链接会自动更改。
What is the best practice in Laravel to achive this functionality? Thanks!
Laravel 中实现此功能的最佳实践是什么?谢谢!
回答by vFragosop
I would do that as a query string, it's easy, accurate enough and doesn't need any complex layers to achieve. Simply put the last modification of the file as query string on their links. That will force the browser to refresh the file.
我会把它作为一个查询字符串来做,它很简单,足够准确,不需要任何复杂的层来实现。只需将文件的最后修改作为查询字符串放在它们的链接上。这将强制浏览器刷新文件。
<link rel="stylesheet" type="text/css" href="/css/style.min.css?v=<?= File::modified(path('public').'/css/style.min.css') ?>" />
To simplify this, you could create a simple class that generates links to files and caches the last modification for increased performance. It's also achievable with custom functions on LESS compiler if you use it.
为了简化这一点,您可以创建一个简单的类,该类生成文件链接并缓存上次修改以提高性能。如果您使用 LESS 编译器,也可以使用自定义函数来实现它。
Now, about server caching, if your application has that many users to really benefit from it, you should be looking into CDN's, which also handle worldwide distribution and will work wonderfully with that query string system.
现在,关于服务器缓存,如果您的应用程序有那么多用户真正从中受益,您应该研究 CDN,它也处理全球分发,并且将与该查询字符串系统完美配合。
Edit:
编辑:
It's also possible to approach that with RewriteRules on Apache (don't have any experience with nginx to help on that tho). The same technique used to generate the query strings, you could use to generate a prefix (or suffix) to the URI.
也可以使用 Apache 上的 RewriteRules 来解决这个问题(没有任何使用 nginx 的经验来帮助解决这个问题)。用于生成查询字符串的相同技术,您可以用于生成 URI 的前缀(或后缀)。
Another thing you could try is to define a subdomain mainly for handling static assets like assets.example.com
. This domain can be entirely handled by a webserver without the Laravel stack. But it depends a lot on how your assets are developed, compiled and used across your project.
您可以尝试的另一件事是定义一个子域,主要用于处理静态资产,如assets.example.com
. 这个域可以完全由没有 Laravel 堆栈的网络服务器处理。但这在很大程度上取决于您的资产如何在整个项目中开发、编译和使用。
Our Approach:
我们的方法:
On our company we use CloudFront and S3 for database entities assets. Each entity has it's own S3 directory and each asset is versioned through an unique filename (generated by md5, which avoids duplication on reuploaded assets). Something like:
在我们公司,我们将 CloudFront 和 S3 用于数据库实体资产。每个实体都有自己的 S3 目录,每个资产都通过唯一的文件名(由 md5 生成,避免重复上传资产)进行版本控制。就像是:
/posts/876/060b90d67ac0c5e24da6de6ae547e3b1.jpg
We also defined 10 subdomains on our CloudFront, so browsers don't reach the limit of 6-8 concurrent requests for the same domain:
我们还在 CloudFront 上定义了 10 个子域,因此浏览器不会达到对同一域的 6-8 个并发请求的限制:
cdn0.example.com
cdn1.example.com
cdn2.example.com
... and so on
Each entry on our database uses an exclusive subdomain picked by calculating resource.id % 10
, this is extremely fast and always returns the same subdomain for each entity (helping with client and CloudFront caches). This is the best you can get for serving images.
我们数据库中的每个条目都使用通过计算选择的独占子域resource.id % 10
,这非常快,并且始终为每个实体返回相同的子域(帮助处理客户端和 CloudFront 缓存)。这是提供图像的最佳方法。
UI images are stored on a exclusive subdomain assets.example.com
, and those are not versioned so far, because we don't change design that much and if we do, we would probably put the new assets inside something like a /v2/
or /newthemename/
folder. This approach helps a lot with rollbacks and even user chosen themes.
UI 图像存储在一个独占的子域中assets.example.com
,并且到目前为止还没有版本化,因为我们不会对设计进行太多更改,如果我们这样做,我们可能会将新资产放在诸如 a/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.
CSS 和 JS 由 Apache 从 Laravel/public
目录中提供。这不是最快的方法,但由于我们现在专注于开发,所以自动编译 LESS 和 Closure 就显得重要多了。当我们为最终用户启动时,我们可能会想到一个自动部署系统,它编译资产,将它们发布在 S3/CloudFront 上并带有时间戳前缀,并缓存它们的最后时间戳以进行视图渲染。