Key Takeaways
- Assetic is a PHP package that aids in the management, compilation, and optimization of assets such as scripts, stylesheets, and images. It helps optimize both file size and the number of HTTP requests, which are critical for performance, especially with the rise of mobile devices.
- Assetic operates on the concepts of collections and filters. Collections group together a bunch of assets, such as a single file or a group of files matching a specific pattern. Filters modify collections in various ways, implementing stages in the asset management process like compilation and minification.
- Installing Assetic can be done via Composer, and it provides support for numerous modules giving flexibility to choose the preferred approach. It also has packages available for frameworks like Zend Framework, Symfony, Laravel, and Silex.
- Assetic offers a simple file-based caching mechanism to ensure that filters aren’t run unnecessarily, and has an AssetWriter for generating .css and .js files. It can be used with a tool such as Guard to “watch” the filesystem and re-run it whenever one of the relevant files has changed.
There was a time when asset management meant little more than inserting a <link>
tag or two and a couple of <script>
tags into your HTML.
Nowadays, though, that approach just won’t cut it. There’s performance, for one thing. Assets are a significant performance drain both in terms of file size and the number of HTTP requests – optimizing both has become an essential part of the development process. This has been exacerbated by the proliferation of mobile devices.
Also, as client-side applications have become more and more sophisticated, managing dependencies amongst scripts and libraries has become increasingly complex.
Furthermore, technologies such as Less, Compass and Coffeescript require assets to be compiled, adding yet another step to the process of managing assets.
In this article I’m going to look at a PHP package called Assetic which helps manage, compile and optimize assets such as scripts, stylesheets and images.
What is asset management?
Let’s start by looking at what asset management actually is.
At its simplest, it’s a way of managing what resources are required by a website or a web application – or a specific page – and their dependencies. This might involve ensuring a particular library is available to your JavaScript, or making sure a CSS reset is applied before your other styles.
It sometimes helps to look at asset management in terms of several distinct stages. The first is compilation, a necessary step if you’re using a CSS framework such as Less, SASS, SCSS, Stylus, Compass etc, or something like Coffeescript or Dart. There are also a few additional compilation steps involved in some JavaScript-based tools; for example compiling Handlebars, Twig or Mustache templates.
The next stage is optimization. For CSS, typically you’ll minify your stylesheet files when you go into production mode. For JavaScript, you’d probably minify or pack your source files. Images can often be reduced quite significantly in size using various compression algorithms, and in some cases you can also reduce the number of HTTP requests by BASE-64 encoding them and embedding the data in your stylesheets.
Finally, concatenation. Reducing the number of HTTP requests can have significant performance gains, so CSS and JavaScript files are often concatenated together into a single, large file for each type. The technique of building “sprites” applies the same principle to images, though that’s outside the scope of this article.
Introducing Assetic
Assetic is a PHP package designed to help with the asset management process.
There are a couple of important concepts to understand when getting started with Assetic – collections and filters.
A collection groups together a bunch of assets. A single file is an asset. ‘Nix users in particular will be familar with glob, which is essentially a way of collecting together a bunch of files whose filenames match a particular pattern; Assetic treats these as an asset as well. For example, the glob patterm /assets/js/*.js
refers to all files in /assets/js
with the .js
extension.
A filter is applied to a collection to modify it in some way. If you refer back to the idea of stages in the asset management process, you can think of each stage as being implemented by one or more filters. So for example, one filter might be responsible for compilation, and one for minification.
Different filters are usually applied to different collections. For example, you might have a project with the following:
- A collection of
.less
files which are compiled with the Less filter, minified using a CSS minification filter and concatenated into one CSS file. - A collection of
.css
files which are simply minified - A collection of Coffeescript files are compiled using the Coffeescript filter, minified using the Google Closure Compiler filter, then concatenated into one
.js
file.
The exact combinations of file types and filters will depend on what technologies you’re using and your personal preference, such as your preferred minifier.
Assetic provides support for numerous modules, giving you the flexibility to choose whichever approach you prefer. For example, it’s up to you whether you minify your JavaScript using JSMin, the YUI Compressor or the Google Closure Compiler.
Installing Assetic
You can install Assetic by downloading or cloning from Github or better still, via Composer:
"kriswallsmith/assetic": "1.2.*@dev"
There are also Assetic packages available on Packagist for frameworks such as Zend Framework, Symfony, Laravel and Silex.
Usage
Let’s start with a simple example – creating an asset collection to concatenate a bunch of JavaScript files:
$js = new AssetCollection(array(
new GlobAsset('/assets/js/libs/*'),
new FileAsset('/assets/js/app.js'),
));
print $js->dump();
The code above takes all .js
files from /assets/js/libs
and then the file /assets/js/app.js
, and concatenates them when dump()
is called – we’ll look at what you do with the output shortly.
You can extend the above example by adding a filter – in this case, it uses JSMin to minify the resulting JavaScript:
$scripts = new AssetCollection(array(
new GlobAsset('/assets/js/libs/*'),
new FileAsset('/assets/js/app.js'),
), array(
new JSMinFilter(),
));
print $scripts->dump();
Note: If you wish to use JSMin, you can use the following PHP implementation:
"lmammino/jsmin4assetic": "1.0.*@dev"
(view it on Github here).
Your stylesheets will need a separate asset collection, given that the filters behave differently. Suppose you have a bunch of CSS files, and you’re using Less to define your grid:
$styles = new AssetCollection(array(
new FileAsset('/assets/less/grid.less', array(new LessFilter())),
new GlobAsset('/assets/css/*'),
), array(
new Yui\CssCompressorFilter('/path/to/yuicompressor.jar'),
));
print $styles->dump();
This uses the LessFilter
to compile grid.less
, concatenates it along with all the .css
files in /assets/css
, then compresses the whole thing using the YUI compressor.
Note that in order to get the example above working, you’ll need to ensure you have the YUI Compressor installed correctly, ensure that the path to its
.jar
files is correct, and add the following to yourcomposer.json
:"leafo/lessphp": "0.4.*@dev"
If you’d rather use CssMin than the YUI Compressor, you’ll need to install it, and your code becomes:
$styles = new AssetCollection(array(
new FileAsset('/assets/less/grid.less', array(new LessFilter())),
new GlobAsset('/assets/css/*'),
), array(
new CssMinFilter(),
));
print $styles->dump();
If you’re using SASS instead of Less, install SCSSphp by adding the following to your composer.json
:
"leafo/scssphp": "dev-master"
You can then use ScssphpFilter
to compile your SASS assets.
You can optimize images, too. In this example, we use glob to grab all images files from assets/img
and compress them with OptiPng, then do the same with Jpegs but use Jpegoptim:
$images = new AssetCollection(array(
new GlobAsset('/assets/img/*.png', array(new OptiPngFilter())),
new GlobAsset('/assets/img/*.jpg', array(new JpegoptimFilter()),
));
Manager Classes and the AssetFactory
There are other ways to configure your assets. The AssetManager
class is essentially a keyed store of assets – for example, you can collect the asset collections we defined in the previous section together like this:
$am = new AssetManager();
$am->set('jquery', new FileAsset('/path/to/jquery.js'));
$am->set('scripts', $scripts);
$am->set('styles', $styles);
The FilterManager
class works in much the same way:
$fm = new FilterManager();
$fm->set('sass', new SassFilter('/path/to/parser/sass'));
$fm->set('yui_css', new Yui\CssCompressorFilter('/path/to/yuicompressor.jar'));
Then you can use the AssetFactory
class to simplify the whole process:
use Assetic\Factory\AssetFactory;
$factory = new AssetFactory('/path/to/asset/directory/');
$factory->setAssetManager($am);
$factory->setFilterManager($fm);
$factory->setDebug(true);
$styles = $factory->createAsset(array(
'@reset', // load the asset manager's "reset" asset
'css/src/*.scss', // load every scss files from "/path/to/asset/directory/css/src/"
), array(
'scss', // filter through the filter manager's "scss" filter
'?yui_css', // don't use this filter in debug mode
));
echo $styles->dump();
Output
I’ve shown how to select what you want to include and how to apply filters; but I haven’t yet looked at where you do this or how you reference it. There are a number of approaches you can take.
One possibility is to create a PHP file in a publicly accessible directory, e.g. JavaScripts.php
and reference it from your HTML as if it were an asset:
<script src="/assets/JavaScripts.php"></script>
Or, you could create a file called stylesheets.php
and embed it inline:
<style>
<?php include('/assets/stylesheets.php');
</style>
Alternatively you could generate .css
and .js
files and just reference those as normal. You can use the AssetWriter
for this:
use Assetic\AssetWriter;
$scripts.js = new AssetCollection(array(
new GlobAsset('/assets/js/libs/*'),
new FileAsset('/assets/js/app.js'),
), array(
new JSMinFilter(),
));
// Set target path, relative to the path passed to the
// AssetWriter constructor as an argument shortly
$scripts->setTargetPath('scripts.js');
$am->set('scripts.js', $scripts.js);
// see above for instantiation of $styles
$styles->setTargetPath('stylesheets.css');
$am->set('styles', $styles);
$writer = new AssetWriter('/assets/build');
$writer->writeManagerAssets($am);
You could create a command-line script to do this as part of your workflow, or use a tool such as Guard to “watch” the filesystem and re-run it whenever one of the relevant files has changed.
Caching
Assetic ships with a simple file-based caching mechanism to ensure that filters aren’t run unnecessarily. Here’s an example of caching the output of the YUI Compressor:
use Assetic\Asset\AssetCache;
use Assetic\Asset\FileAsset;
use Assetic\Cache\FilesystemCache;
use Assetic\Filter\Yui;
$yui = new Yui\JsCompressorFilter('/path/to/yuicompressor.jar');
$js = new AssetCache(
new FileAsset('/path/to/some.js', array($yui)),
new FilesystemCache('/path/to/cache')
);
// the YUI compressor will only run on the first call
$js->dump();
$js->dump();
$js->dump();
Summary
In this article I’ve introduced Assetic – a PHP package for managing assets. I’ve shown how you can use it to manage dependencies, run compilation processes, minify / pack / compress / optimise assets, and concatenate files to minimise the number of HTTP requests. Be sure to check out the documentation for details of all the available filters; or, you could even look at implementing FilterInterface
/ extending BaseFilter
with a view to defining your own. For packages which complement it, refer to the suggested packages either when you first install it, or by inspecting the suggests
section of its composer.json
file.
Frequently Asked Questions (FAQs) about Assetic
What is Assetic and how does it work?
Assetic is a powerful asset management framework for PHP. It provides a systematic and efficient way to manage web assets such as CSS, JavaScript, and image files. Assetic works by allowing you to filter, combine, and compress these assets, which can significantly improve the performance of your website. It also supports a variety of filters, including CSS minification, JS minification, and LESS compilation, among others.
How can I install Assetic?
Assetic can be installed using Composer, a tool for dependency management in PHP. You can install Composer by following the instructions on its official website. Once Composer is installed, you can install Assetic by running the command “composer require kriswallsmith/assetic”.
How can I use Assetic with Symfony?
Assetic is often used with Symfony, a PHP web application framework. To use Assetic with Symfony, you need to install the Assetic bundle. Once installed, you can use Assetic to manage your web assets in your Symfony application. You can define asset collections in your Symfony configuration and use the Assetic controller to serve these assets.
What are the benefits of using Assetic?
Assetic offers several benefits. It allows you to manage your web assets in a systematic and efficient way, which can significantly improve the performance of your website. It also supports a variety of filters, which can help you to optimize your assets. Furthermore, Assetic is flexible and can be used with a variety of web application frameworks, including Symfony.
Can I use Assetic without Symfony?
Yes, Assetic can be used without Symfony. While Assetic is often used with Symfony, it is a standalone library and can be used with any PHP application. To use Assetic without Symfony, you need to install it using Composer and then use it to manage your web assets.
How can I use filters in Assetic?
Filters in Assetic allow you to transform your assets in various ways. For example, you can use a CSS minification filter to reduce the size of your CSS files, or a LESS compilation filter to compile your LESS files into CSS. To use a filter in Assetic, you need to define it in your configuration and then apply it to your assets.
What is asset collection in Assetic?
An asset collection in Assetic is a group of assets that are managed together. You can define an asset collection in your configuration and then use the Assetic controller to serve these assets. Asset collections can be used to combine and compress multiple assets into a single file, which can significantly improve the performance of your website.
How can I debug assets in Assetic?
Assetic provides a debug mode that can be used to troubleshoot issues with your assets. When debug mode is enabled, Assetic will serve each asset individually, rather than combining them into a single file. This can make it easier to identify and fix issues with your assets.
Can I use Assetic with other web application frameworks?
Yes, Assetic is a standalone library and can be used with any PHP application. While it is often used with Symfony, it can also be used with other web application frameworks. To use Assetic with another framework, you need to install it using Composer and then use it to manage your web assets.
How can I optimize my assets using Assetic?
Assetic provides several ways to optimize your assets. You can use filters to transform your assets in various ways, such as minifying CSS and JS files or compiling LESS files into CSS. You can also use asset collections to combine and compress multiple assets into a single file. These features can significantly improve the performance of your website.
Lukas is a freelance web and mobile developer based in Manchester in the North of England. He's been developing in PHP since moving away from those early days in web development of using all manner of tools such as Java Server Pages, classic ASP and XML data islands, along with JavaScript - back when it really was JavaScript and Netscape ruled the roost. When he's not developing websites and mobile applications and complaining that this was all fields, Lukas likes to cook all manner of World foods.