- A Java runtime engine must be installed for the YUI compressor
- Does not interfere with scripts and CSS registered outside of packages
- Automatic or manually triggered compression
- Locking mechanism to prevent multiple concurrent compressions
- Workaround for the thundering herd problem
- Command-line maintenance script
Note: You can even include Yii's core scripts in a package. Unfortunately some Zii widgets like
CGridViewstill don't use the package system packages. But this will hopefully be fixed in Yii 1.1.15.
<?php return array( // ... 'clientScript' => array( 'class' => 'ext.packagecompressor.PackageCompressor' 'coreScriptPosition' => 2, // == POS_END 'packages' => array( 'forum-js' => array( 'baseUrl' => 'js', 'depends' => array('jQuery', 'maskedinput'), 'js' => array( 'modules/main.js', 'modules/editor.js', 'modules/forum.post.js', 'modules/forum.notify.js', ), ), 'forum-css' => array( // requires write permission for this directory 'baseUrl' => 'css', 'css' => array( 'main.css', 'forum.css', ), ), ), ), // ... );
With the packages defined above you can now for example register the forum packages in the forum section of your site:
Your users will receive single js and CSS files until you reset a package with
./yiic packages reset
How does it work?
Whenever a package is registered through
registerPackage() a single compressed
file is served to the user. If there is no compressed file yet, all files from the
package get combined and compressed, then this single file is published by the asset manager.
The extension uses the application state (which gets cached automatically) to store
information about a compressed package. So after the initial delay during compression
all subsequent requests will get the compressed file delivered lightning fast.
There's also a command line tool to create the compressed file for a package manually, e.g. at deployment time and to reset a package.
The compressed file name will contain a hash to make sure that no visitor ever gets and outdated version of a compressed package.
Extract the package in
protected/extensions into a directory called
-x.y.z suffix). Then configure the component to replace Yii's
<?php return array( // ... 'components' => array( 'clientScript' => array( 'class' => 'ext.packagecompressor.PackageCompressor' ), // ... ), // ... );
If you want to user the command-line utility, you should make the bundled command available in your console configuration:
<?php return array( // ... 'commandMap' => array( 'packages' => array( 'class' => 'ext.packagecompressor.PackagesCommand', ), // ... ), // ... );
Besides the usual
CClientScript properties the packager adds these other
configuration options, which you can set in your
main.php config file:
enableCompression: Wether compression should be enabled at all. Default is
true. It's recommended to turn this off during development.
enableCssImageFingerPrinting: Whether to enable automatic fingerprinting on CSS images, e.g. to add
?acd4gd3szbased on the md5 hash of the image file.
combineOnly: Wether all files should only be combined but not compressed. Default is
false. This is very useful to debug packaging issues.
blockDuringCompression: Wether other requests should pause during compression. Default is
true. This could sometimes be problematic on websites with heavy load, because the mass of paused processes could eat up all server ressources. As a workaround you can set this to
false. In this case during compression any concurrent requests will be served the unminified single files instead. If you also don't want that, you can still create the minified version from the command line before you deploy.
javaBin: The path to your java binary. The default is
javawhich assumes that the JRE binary is available in your OS' search path (which it usually is on linux systems).
This component comes with a maintenace command for yiic. It can be used to compress packages, reset packages or output details about compressed packages from the command line.
Note: It's important that the package configuration from your web configuration is also available in your console config. That means, you need have the same
clientScriptconfiguration in your
console.php. You may want to use a shared include file to do so. If you want to compress from the command-line you also need to configure an asset manager and an alias for
webroot. You also need to fix a problem with the
requestcomponent which returns '.' as baseUrl on console:<?php 'aliases' => array( 'webroot' => realpath(__DIR__.'/../..'), ), 'components' => 'assetManager'=>array( 'class' =>'CAssetManager', 'basePath' =>realpath(__DIR__.'/../../assets'), 'baseUrl' =>'/assets', ), 'request' => array( 'baseUrl' => '', ), //...
Note 2: You need write permissions from the command line to the
state.binfile in your
protected/runtimedirectory, if you want to reset packages.
Compress a package:
./yiic packages compress --name=<packagename>
Show meta information about a compressed package:
./yiic packages info --name=<packagename>
Reset all compressed packages:
./yiic packages reset
Reset specific package:
./yiic packages reset --name=<packagename>
Advanced example: CSS assets
CSS files often contain relative URL references to some asset files (images).
So if the compressed CSS file is published to the assets directory, these
paths will be broken (except if we'd also publish the images, which we don't).
As a workaround you can publish a CSS package into the same folder where the
source files reside. Therefore you have to specify a
baseUrl in your package.
<?php return array( // ... 'forum-css' => array( 'baseUrl' => 'css', 'css' => array( 'main.css', 'forum.css', ), ), // ... )
Now you can register this CSS package with
Note: Here the web server process must have write permissions to the CSS folder.
Advanced example: media support for CSS
CSS packages can contain a
media specification which will be used when the package
<?php return array( // ... 'main-css' => array( 'baseUrl' => 'css', 'media' => 'screen', 'css' => array( 'main.css', 'forum.css', ), ), 'main-css' => array( 'baseUrl' => 'css', 'media' => 'print', 'css' => array( 'print.css', ), ), // ... )
Advanced example: jQUery from CDN
If you want to use a CDN for jQuery you can configure it just as you would without the compressor. Everything will work when you register such a package:
<?php return array( // ... 'clientScript' => array( 'class' => 'ext.packagecompressor.PackageCompressor' 'coreScriptPosition' => 2, // == POS_END 'scriptMap' => array( 'jquery.js' => 'https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.js', ), 'packages' => array( 'forum' => array( 'depends' => array('jQuery', 'maskedinput'), 'js' => array( // ... ), ), ), ), // ... ),
Known Problems and Limitations
- PackageCompressor is not compatible with an absolute
baseUrl(eg. CDN Hosting) in Yii's assetManager
- Fix external URLs that don't have a protocol like
mediasupport for CSS.
- Add composer support
- Initial version