Pergunta

Suppose that we changed a lot of functionality for the module (templates, layouts, CSS) and we are going to move these changes to the production site, but a lot of customers have cached CSS in their browsers. So here is a question. How to force flush client's CSS cache and avoid file renaming (styles.css -> styles-v2.css). There is one logical way but it doesn't work in Magento, because it checks file existing (by the way this method works for JS files), see below:

<action method="addCss">
    <stylesheet>css/styles.css?1</stylesheet>
</action>  

Any ideas?

Foi útil?

Solução

One way of dealing with this is enabling merging of CSS. Then you could just clear the cache and a new merged file would be created with a new file name.

System -> Configuration -> Developer -> CSS settings -> Merge CSS Files

As far as I know, the hash code of the merged CSS file stays the same even if the underlying files changed - only if new files are added to the set of merged files, the hash changes. -- @Alex

Another way of dealing with this is instead of using the layout.xml,

just put them in your page/html/head.phtml

Or create a block that contains a <style> tag with version number and put it in the XML in your head so you can have it load on only specific pages and still sticking to using the XML layouts.

Outras dicas

You can use the OpenSource Module Aoe_JsCssTstamp which adds timestamp information to the merged CSS files. Timestamps for plain (un-merged) CSS files are not yet supported however but this would be easy to implement.

There is a free extension on github 'Magento Cachebuster' that does exactly this. It re

https://github.com/gknoppe-guidance/magento-cachebuster

The module provides cachebusting by automatically altering the URI created by Magento for >static files by adding the timestamp of the file to the filename:

Before: http://www.example.com/js/varien/js.js After: http://www.example.com/js/varien/js.1324429472.js

I use my own extension Speedster Advanced for this. But the basic principle is that the name of the merged css and js files includes the timestamp of the last modified file - see Mage_Core_Model_Design_Package::getMergedCssUrl(). Any time you edit any of the css files a new file name is created causing browsers to request the new file instead of reusing the cached version. Since your head block might be cached a Magento cache refresh is needed.

I also have implemented a cache buster for css files. Best way I guess is to extend Mage_Page_Block_Html_Head and over ride the function below and update $skinItems array with your desired changes.

protected function &_prepareStaticAndSkinElements($format, array $staticItems, array $skinItems, $mergeCallback = null)
{
    $designPackage = Mage::getDesign();
    //$skinItems: contains all css
    foreach ($skinItems as $params => $rows) {
        foreach ($rows as $key=>$name) {
            $file = $designPackage->getFilename($name, array('_type' => 'skin'));
            $skinItems[$params][$key] = $name . "?fmt=" . filemtime($file);
        }
    }
    return parent::_prepareStaticAndSkinElements($format, $staticItems, $skinItems, $mergeCallback);

}

Got the inspiration from here. Source

There is a simple but cumbersome workaround that doesn't require any plugins and just uses built in Magento capabilities - useful if you just have to quickly do it on an existing site without wanting to risk installing any more code.

The idea is that you can use the merged CSS system to generate a cache busting file name.

As the merged CSS file name is a hash of all the files that are merged together you simply add an extra blank css file into the theme with a date stamp for a name.

So:

  1. Turn on Merge CSS files in Configuration > Advanced > Developer
  2. In your theme layouts find where you add CSS files to the head (typically page.xml) and add an extra stylesheet file, call it anything you want as long as the name is unique eg <action method="addCss"><stylesheet>css/cachebust_091014.css</stylesheet></action>
  3. In your skin CSS folder create a new css file with that name, for the file contents I just put a comment saying what the file is for

Now push that live and flush the magento cache, the merged css file will now have a different name and your caches will be busted!

It's cumbersome as each time you want to bust the cache you need to change that file name, but it requires nothing other than built in Magento capabilities so it's handy if you find yourself stuck and need a quick fix!

=> Instead of using this code:

<action method="addCss">
    <stylesheet>css/styles.css?1</stylesheet>
</action>

=> Try to use this code :

<reference name="head">
    <block type="core/text" name="foocss">
        <action method="setText">
            <css><![CDATA[<link rel="stylesheet" type="text/css" href="foo.css?1" media="all" />]]></css>
        </action>
    </block>
</reference>

But it's not very nice...

I found a module that will append a query string to the end of all CSS and JS in xml layouts. The query string is configurable from the admin.

https://github.com/mklooss/Loewenstark_Head

The basic idea is to override _prepareStaticAndSkinElements to include a query string, as done in the module, shown below.

protected function &_prepareStaticAndSkinElements($format, array $staticItems, array $skinItems, $mergeCallback = null)
{
    $version = Mage::getStoreConfig("design/head/meta_version_tag");
    $format = sprintf($format, "%s?v{$version}", "%s");
    return parent::_prepareStaticAndSkinElements($format, $staticItems, $skinItems, $mergeCallback);
}

If I understand the proposed solution in your question, you can do that with a slight mod to a core file (don't actually edit the core file):

Mage/Page/Block/Html/Head.php

Add something like ?v=1 to line 198 so all css files have this appended:

$html .= $this->_prepareStaticAndSkinElements('<link rel="stylesheet" type="text/css" href="%s?v=1"%s />' . "\n",

I think Fooman Speedster Advanced (http://www.magentocommerce.com/magento-connect/fooman-speedsteradvanced-4030.html) could be a solution:

"Fully automated once installed, with automatic versioning when Javascript/CSS files are updated"

I have built a free module for this:

http://www.magentocommerce.com/magento-connect/frontend-flush-2048.html

Please let me know if it does not work as expected but I've built it so that the combined js and css files will have a different hash if the content of one of the concatenated files has changed. By default Magento only changes the hash of the combined file if the filename of one of the included files has changed.

UPDATE

I also made a free and simple minify module for the ones of you who believe in it.

http://www.magentocommerce.com/magento-connect/minify-7771.html

There's a really nice module created by Fabrizio Branca that does exactly the thing that you're interested in. It's called AOE_JsCSSTStamp . What it does? It adds a time stamp to both CSS and JS resources. When you flush CSS/JS cache then the timestamps are recreated.

The browser will see different filename - that's why it will redownload the resources again and be served with the freshest one instead of cached in the browser.

Just edit the method getCssJsHtml in Mage_Page_Block_Html_Head, add a string like this for a few days after css edit and that's all... it simply works

// static and skin css
        $html .= $this->_prepareStaticAndSkinElements('<link rel="stylesheet" type="text/css" href="%s?foo=WHAT_YOU_WANT_HERE"%s />' . "\n",
            empty($items['js_css']) ? [] : $items['js_css'],
            empty($items['skin_css']) ? [] : $items['skin_css'],
            $shouldMergeCss ? [Mage::getDesign(), 'getMergedCssUrl'] : null
        );

Few years later and not finding any useful extension that won't merge files and is simple, I created my own. The main idea is that after flushing cache, it will update the Timestamp. So in other words - when you change some css/js, just flush cache and Timestamp will be updated.

Source code is here -> https://github.com/archonkulis/ANSolutions_CssJsTimestamp

Works on 1.9+ version. Not sure about older versions, though, but most likely should work as well.

Make a copy of your theme with a new name (themev2) - both skin and app/design, etc. Then choose the new theme in admin.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a magento.stackexchange
scroll top