As some of you might have already read, Rails 3.1 is coming with a new asset pipeline. A fancy word for publishing assets to a static location which the browser can fully cache (by setting Expire time far away in the future). Since the filename of the published asset depends on the content of the file, visitors will never mix cached assets with new pages.
I always thought CAssetManager would be perfect for this too but it seems the filenames it generates are only depending on the original file and not on the content. Has anyone altered this behavior yet? It would really make user-agent caching a lot easier.
(Another benefit of this approach, and why they call it a pipeline in Rails, is that you can let other utilities, e.g. Sass, process the files and the output will be cached statically on the server and by the browser agent.)
I don’t really see this in the documentation / code. The hash is generated from the (absolute or relative) filename passed to CAssetManager::publish. Just checking the modified-date and updating the file is not a sufficient solution when caching files with Expires.
Example: I update the contents of my .css file but the filename stays the same. When I publish it, the published path will remain identical. The user-agent caches and keeps using the old-version of my css-file and will not update its version of my .css-file. When hashing the file-contents the path would’ve changed.
(I see that the hash-method in CAssetManager uses Yii::getVersion, so assets get a new path when Yii is upgraded. Good fix for the core developer’s assets but this isn’t working for application developers.)
Oww. I’ve re-read all your messages… and You’re totally right about Yii asset manager behavior. Did some tests and can say that hash_file with sha1 isn’t significantly slower than just getting mtime of a file. Will consider this method.
This feature is highly important. Do not know how to clear user’s cache, unless adding v=timestamp to each js and css and pictures, but that is quite time consuming and may cause a lot of troubles (if, for example script will be published twice with 2 different versions specified)
Any chance, that this feature will be implemented in Yii 1.1.x?
Or maybe there is some workaround for it now with minimal changes (extension or something)?
I just checked yii source files and will answer my own question myself.
For example, if you have /siteroot/assets folder
and some hashes under it, like
/abcdef/
/def123/
And you have /siteroot/protected/assets folder, where all your static files are actually located.
Now you updated some files in /siteroot/protected/assets and you want all client’s cache also became updated
All you need to do is to run in linux shell:
touch /siteroot/protected/assets
this will change modification time of /siteroot/protected/assets folder and will cause republishing it under new hash name in /siteroot/assets folder.
That’s all - all users will drop their cache (since assets folder path is another one now) and will get updated styles, pictures, js or whatever!
PS. This will probably work only if you publish your assets the way like that:
class Controller extends CController
{
private $_assetsBase;
public function getAssetsBase()
{
if ($this->_assetsBase === null) {
$this->_assetsBase = Yii::app()->assetManager->publish(
Yii::getPathOfAlias('application.assets'),
false,
-1,
YII_DEBUG
);
}
return $this->_assetsBase;
}
public $menu=array();
public $items=array();
public $breadcrumbs=array();
}
e.g. the 2nd parameter of assetManager->publish is false.
Yes, exactly that was added after Javache raised this topic. dhampik, I think I’ve reflected changes in an API docs somehow but it will be a big help if you’ll put a wiki article together describing the same you described in a post here.