Laravel/blade 缓存 css 文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23411463/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 09:27:20  来源:igfitidea点击:

Laravel/blade caching css files

csstwitter-bootstrapcachinglaravellaravel-4

提问by iOi

I am working on Nginx server, with PHP-FPM. I installed Laravel 4.1and bootstrap v3.1.1., and here is the problem. For the last 30 minutes, I have been trying to change a css rule that I first declared to check boostrap.

我正在使用 PHP-FPM 开发 Nginx 服务器。我安装了Laravel 4.1and bootstrap v3.1.1.,这就是问题所在。在过去的 30 分钟里,我一直在尝试更改我首先声明用于检查 boostrap 的 css 规则。

.jumbotron{
   background: red; 
}

The first time it worked. The jumbotron container was red. So, I removed that css value and started working, but still no matter which browse I use, the container is red. I even checked the css file through the Google Chromes inspection tool, and it is showing me that first value when jumbotron had a background:red. I deleted the css file and renamed it and add new styles, I configured chrome not to cache pages. But Still the same value. I'm convinced now, that Laravel has kept a cache of the first style declaration.

第一次奏效。大屏幕容器是红色的。所以,我删除了那个 css 值并开始工作,但无论我使用哪种浏览器,容器都是红色的。我什至通过 Google Chromes 检查工具检查了 css 文件,当 jumbotron 有一个background:red. 我删除了 css 文件并重命名了它并添加了新样式,我将 chrome 配置为不缓存页面。但仍然是相同的值。我现在确信,Laravel 保留了第一个样式声明的缓存。

Is there any way to disable this at all?

有没有办法完全禁用它?

回答by totymedli

General explanation

一般说明

When you access a Laravel Blade view, it will generate it to a temporary file so it doesn't have to process the Blade syntax every time you access to a view. These files are stored in app/storage/viewwith a filename that is the MD5 hash of the file path.

当您访问 Laravel Blade 视图时,它会将其生成到一个临时文件中,因此每次访问视图时都不必处理 Blade 语法。这些文件存储在app/storage/view文件名中,文件名是文件路径的 MD5 哈希值。

Usually when you change a view, Laravel regenerate these files automatically at the next view access and everything goes on. This is done by comparing the modification times of the generated file and the view's source file through the filemtime()function. Probably in your case there was a problem and the temporary file wasn't regenerated. In this case, you have to delete these files, so they can be regenerated. It doesn't harm anything, because they are autogenerated from your views and can be regenerated anytime. They are only for cache purposes.

通常,当您更改视图时,Laravel 会在下一次访问视图时自动重新生成这些文件,一切照旧。这是通过该filemtime()函数比较生成文件和视图源文件的修改时间来完成的。可能在您的情况下存在问题,并且没有重新生成临时文件。在这种情况下,您必须删除这些文件,以便重新生成它们。它不会伤害任何东西,因为它们是从您的视图中自动生成的,并且可以随时重新生成。它们仅用于缓存目的。

Normally, they should be refreshed automatically, but you can delete these files anytime if they get stuck and you have problems like these, but as I said these should be just rare exceptions.

通常,它们应该会自动刷新,但是如果这些文件卡住了并且您遇到了此类问题,您可以随时删除它们,但正如我所说,这些应该只是极少数例外。

Code break down

代码分解

All the following codes are from laravel/framerok/src/Illuminate/View/. I added some extra comments to the originals.

以下所有代码均来自laravel/framerok/src/Illuminate/View/. 我在原件上添加了一些额外的注释。

Get view

获取视图

Starting from Engines/CompilerEngine.phpwe have the main code we need to understand the mechanics.

Engines/CompilerEngine.php我们需要了解机制的主要代码开始。

public function get($path, array $data = array())
{
    // Push the path to the stack of the last compiled templates.
    $this->lastCompiled[] = $path;

    // If this given view has expired, which means it has simply been edited since
    // it was last compiled, we will re-compile the views so we can evaluate a
    // fresh copy of the view. We'll pass the compiler the path of the view.
    if ($this->compiler->isExpired($path))
    {
        $this->compiler->compile($path);
    }

    // Return the MD5 hash of the path concatenated
    // to the app's view storage folder path.
    $compiled = $this->compiler->getCompiledPath($path);

    // Once we have the path to the compiled file, we will evaluate the paths with
    // typical PHP just like any other templates. We also keep a stack of views
    // which have been rendered for right exception messages to be generated.
    $results = $this->evaluatePath($compiled, $data);

    // Remove last compiled path.
    array_pop($this->lastCompiled);

    return $results;
}

Check if regeneration required

检查是否需要再生

This will be done in Compilers/Compiler.php. This is an important function. Depending on the result it will be decided whether the view should be recompiled. If this returns falseinstead of truethat can be a reason for views not being regenerated.

这将在Compilers/Compiler.php. 这是一个重要的功能。根据结果​​,将决定是否应重新编译视图。如果返回false而不是返回true,则可能是视图未重新生成的原因。

public function isExpired($path)
{
    $compiled = $this->getCompiledPath($path);

    // If the compiled file doesn't exist we will indicate that the view is expired
    // so that it can be re-compiled. Else, we will verify the last modification
    // of the views is less than the modification times of the compiled views.
    if ( ! $this->cachePath || ! $this->files->exists($compiled))
    {
        return true;
    }

    $lastModified = $this->files->lastModified($path);

    return $lastModified >= $this->files->lastModified($compiled);
}

Regenerate view

重新生成视图

If the view is expired it will be regenerated. In Compilers\BladeCompiler.phpwe see that the compiler will loop through all Blade keywords and finally give back a string that contains the compiled PHP code. Then it will check if the view storage path is set and save the file there with a filename that is the MD5 hash of the view's filename.

如果视图过期,它将重新生成。在Compilers\BladeCompiler.php我们看到编译器将遍历所有 Blade 关键字,最后返回一个包含已编译 PHP 代码的字符串。然后它将检查是否设置了视图存储路径并将文件保存在那里,文件名是视图文件名的 MD5 哈希值。

public function compile($path)
{
    $contents = $this->compileString($this->files->get($path));

    if ( ! is_null($this->cachePath))
    {
        $this->files->put($this->getCompiledPath($path), $contents);
    }
}

Evaluate

评估

Finally in Engines/PhpEngine.phpthe view is evaluated. It imports the data passed to the view with extract()and includethe file with the passed path in a tryand catchall exceptions with handleViewException()that throws the exception again. There are some output buffering too.

最后在Engines/PhpEngine.php视图中进行评估。它进口传递到与视图中的数据extract(),并include与在传递路径的文件try,并catch与所有的例外handleViewException()是再次抛出异常。还有一些输出缓冲。

回答by act28

Same issue here. I am using VirtualBox with Shared Folders pointing to my document root.

同样的问题在这里。我将 VirtualBox 与指向我的文档根目录的共享文件夹一起使用。

This pointed me in the right direction: https://stackoverflow.com/a/26583609/1036602

这为我指明了正确的方向:https: //stackoverflow.com/a/26583609/1036602

Which led me to this: http://www.danhart.co.uk/blog/vagrant-virtualbox-modified-files-not-updating-via-nginx-apache

这让我想到了这个:http: //www.danhart.co.uk/blog/vagrant-virtualbox-modified-files-not-updating-via-nginx-apache

and this: https://forums.virtualbox.org/viewtopic.php?f=1&t=24905

还有这个:https: //forums.virtualbox.org/viewtopic.php?f=1&t=24905

If you're mounting your local dev root via vboxsf Shared Folders, set EnableSendFile Off in your apache2.conf (or sendfile off if using Nginx).

如果您通过 vboxsf 共享文件夹挂载本地开发根目录,请在您的 apache2.conf 中设置 EnableSendFile Off(如果使用 Nginx,则关闭 sendfile)。

回答by Sarcastron

For what it's worth and because this answer came up first in my google search...

对于它的价值,因为这个答案首先出现在我的谷歌搜索中......

I had the same problem. The CSS and JS files wouldn't update. Deleting the cache files didn't work. The timestamps were not the problem. The only way I could update them was to change the filename, load it directly to get the 404 error, and then change the name back to the original name.

我有同样的问题。CSS 和 JS 文件不会更新。删除缓存文件不起作用。时间戳不是问题。我可以更新它们的唯一方法是更改​​文件名,直接加载它以获取 404 错误,然后将名称更改回原始名称。

In the end the problem was not related to Laravel or the browser cache at all. The problem was due to NginX using sendfile which doesn't work with remote file systems. In my case, I was using VirtualBox for the OS and the remote file system was vboxsf through Guest Additions.

最后,问题根本与 Laravel 或浏览器缓存无关。问题是由于 NginX 使用了不适用于远程文件系统的 sendfile。就我而言,我使用 VirtualBox 作为操作系统,远程文件系统是通过 Guest Additions 的 vboxsf。

I hope this saves someone else some time.

我希望这可以为其他人节省一些时间。

回答by Антон Баранов

In Laravel 5.8+you can use so:

Laravel 5.8+ 中你可以这样使用:

The version method will automatically append a unique hash to the filenames of all compiled files, allowing for more convenient cache busting:

version 方法会自动将唯一的哈希附加到所有编译文件的文件名,从而更方便地清除缓存:

mix.js('resources/js/app.js', 'public/js').version();

After generating the versioned file, you won't know the exact file name. So, you should use Laravel's global mix function within your views to load the appropriately hashed asset. The mix function will automatically determine the current name of the hashed file:

生成版本化文件后,您将不知道确切的文件名。所以,你应该在你的视图中使用 Laravel 的全局混合函数来加载适当的散列资产。mix 函数将自动确定散列文件的当前名称:

<script src="{{ mix('/js/app.js') }}"></script>

full document: https://laravel.com/docs/5.8/mix

完整文档:https: //laravel.com/docs/5.8/mix