Asset Manager

Hi guys,

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.)

Well, currently Yii assets are pretty the same way if registered one file at a time instead of a dir.

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.)

It will not. Try publishing this single CSS and you’ll see that path will be different when you’ll update this file.

I just tried this:

  1. publish an asset, generated path is /assets/7a06f55b/style.css

  2. modify the css in its original path

  3. publish the asset again, the generated path is still /assets/7a06f55b/style.css

Could you please point me to the code that hashes the file?

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.

I totally support this feature, and perhaps an optional way to cache if people don’t want to keep reading off disk all the time?

Sure. I think it should replace current mtime checking. Added to Yii2 discussion forum: http://www.yiiframework.com/forum/index.php?/topic/23147-asset-manager/ You should be able to access it when you’ll post about 20 messages.

Ok great, too bad I now have to search the forums for topics to reply meaningfully to ;)

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.

You asked it, I did it.

AssetManager: clearing browser’s cache on site update

Hope this will be helpful for someone.

It definitely will. Thanks for writing it.