PackageCompressor
A Javascript/CSS compressor based on Yii's package system., (*1)
Requirements
- A Java runtime engine must be installed for the YUI compressor
Features
- Javascript and CSS compression of Yii clientscript packages
(using 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
You probably wonder,
why
yet
another
compression
extension
for
Yii?
The key difference is, that none of the existing solutions uses Yii's integrated
package system
for clientscripts. With this extension you can organize all your CSS and
Javascript in packages and even define dependencies among them. This may not be
very useful for smaller sites (even though you still can use the compressor there, too).
But it proved to be extremely helpful when you have to deal with many Javascript files
and want to cluster them into a couple of minified package files., (*2)
Note: You can even include Yii's core scripts
in a package. Unfortunately some Zii widgets like CListView
and CGridView
still don't
use the package system packages. But this will hopefully be fixed
in Yii 1.1.15., (*3)
Basic example
Packages are set up in your config file. Javascript and CSS packages must be separate.
Here's an example:, (*4)
<?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:, (*5)
Yii::app()->clientScript->registerPackage('forum-js');
Yii::app()->clientScript->registerPackage('forum-css');
Your users will receive single js and CSS files until you reset a package with, (*6)
./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., (*7)
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., (*8)
The compressed file name will contain a hash to make sure that no visitor ever gets
and outdated version of a compressed package., (*9)
Installation
Extract the package in protected/extensions
into a directory called packagecompressor
(remove the -x.y.z
suffix). Then configure the component to replace Yii's
CClientScript component:, (*10)
protected/config/main.php, (*11)
<?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:, (*12)
protected/config/console.php, (*13)
<?php
return array(
// ...
'commandMap' => array(
'packages' => array(
'class' => 'ext.packagecompressor.PackagesCommand',
),
// ...
),
// ...
);
Configuration
Besides the usual CClientScript
properties the packager adds these other
configuration options, which you can set in your main.php
config file:, (*14)
-
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 ?acd4gd3sz
based 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 java
which assumes that
the JRE binary is available in your OS' search path (which it usually is on linux systems).
Command-line maintenance
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., (*15)
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 clientScript
configuration 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 request
component
which returns '.' as baseUrl on console:, (*16)
<?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.bin
file in
your protected/runtime
directory, if you want to reset packages., (*17)
Compress a package:, (*18)
./yiic packages compress --name=<packagename>
Show meta information about a compressed package:, (*19)
./yiic packages info --name=<packagename>
Reset all compressed packages:, (*20)
./yiic packages reset
Reset specific package:, (*21)
./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., (*22)
<?php
return array(
// ...
'forum-css' => array(
'baseUrl' => 'css',
'css' => array(
'main.css',
'forum.css',
),
),
// ...
)
Now you can register this CSS package with, (*23)
Yii::app()->clientScript->registerPackage('forum-css');
Note: Here the web server process must have write permissions to the CSS folder., (*24)
CSS packages can contain a media
specification which will be used when the package
is registered., (*25)
<?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:, (*26)
<?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
Changelog
1.0.4
- Fix external URLs that don't have a protocol like
//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.js
1.0.3
- Add
media
support for CSS.
1.0.2
1.0.0