Setting up Symfony2 with Gulp and Bower instead of the Assetic Bundle

Time for a change

Hi! Today I’ll talk about how we configure and work with assets content in a Symfony application.

The Assetic Bundle is used by default in the Symfony framework to process Javascript, css, Less or sass files. But sometimes during development, this tool can stop working reliably and making collections. Eventually I decided that it was time to find a replacement.

Which tools?

In the world of Javascript many developers use tools such as Gulp, Grunt and Bower. These tools can quickly load libraries and assemble them in our application. I choose to use Gulp for building and Bower for package management of lib-sources.

So on our Ubuntu 14.04 server, suppose we installed NodeJS, (because we need to have Javascript on the server to use the tools I mentioned):

sudo apt-get install nodejs

In the folder with our Symfony application we must initialize the package.json file to npm (Node Package Manager):

npm init

Answer a few basic questions and start to install your tools:

npm install -S bower 
gulp 
less 
gulp-less 
gulp-clean 
gulp-concat 
gulp-uglify

Add the node_modules folder to the .gitignore file. (If you use git as a version control system).

In the next step we initialize the bower.json file to our lib-sources:

./node_modules/.bin/bower init

Again you’ll need to answer a few basic questions. In my projects, I usually use Bootstrap as my default framework for HTML, CSS, and JS developing. I’ll use it today for this example too:

./node_modules/.bin/bower install -S bootstrap

After installing, don’t forget to add the bower_components folder to .gitignore.

Ok, We have all the tools to start building the css file for our pages. Now create a gulpfile.js and start configuring gulp.

In the custom front-end files I make a web-src folder in the root folder of the symfony application. I write Less in the folder web-src/less and js in the web-src/js folder. In my entire application I have just one Less file (web-src/less/app.less) in which I include all required Less/css files from external libraries:

/*---------- app.less ------------*/
@import "../../bower_components/bootstrap/less/bootstrap.less";
/*---------- gulpfile.js ------------*/
var gulp = require('gulp'),
 less = require('gulp-less'),
 clean = require('gulp-clean');
gulp.task('less', function() {
 return gulp.src(['web-src/less/*.less'])
 .pipe(less({compress: true}))
 .pipe(gulp.dest('web/css/'));
});
gulp.task('images', function () {
 return gulp.src([
 'web-src/images/*'
 ])
 .pipe(gulp.dest('web/images/'))
});
gulp.task('fonts', function () {
 return gulp.src(['bower_components/bootstrap/fonts/*'])
 .pipe(gulp.dest('web/fonts/'))
});
gulp.task('clean', function () {
 return gulp.src(['web/css/*', 'web/js/*', 'web/images/*', 'web/fonts/*'])
 .pipe(clean());
});
gulp.task('default', ['clean'], function () {
 var tasks = ['images', 'fonts', 'less'];
tasks.forEach(function (val) {
 gulp.start(val);
 });
});
gulp.task('watch', function () {
 var less = gulp.watch('web-src/less/*.less', ['less']);
});

All images I save in the web-src folder too, because my IDE doesn’t find these files when I use them in app.less:

..
 app
bin
bower_components
node_modules
src
vendor
web
 |_css
 |_ js
web-src
 |_ less
 |_ app.less
 |_ js
bower.json
composer.json
 composer.lock
package.json
README.md

Add the task for building the js to our application:

/*---------- gulpfile.js ------------*/
var gulp = require('gulp'),
 …
 concatJs = require('gulp-concat'),
minifyJs = require('gulp-uglify');
…

gulp.task('lib-js', function() {
 return gulp.src([
 'bower_components/jquery/dist/jquery.js',
 'bower_components/bootstrap/dist/js/bootstrap.js'
 ])
 .pipe(concatJs('app.js'))
 .pipe(minifyJs())
 .pipe(gulp.dest('web/js/'));
});
gulp.task('pages-js', function() {
 return gulp.src([
 'web-src/js/*.js'
 ])
 .pipe(minifyJs())
 .pipe(gulp.dest('web/js/'));
});
gulp.task('clean', function () {
 return gulp.src(['web/css/*', 'web/js/*', 'web/images/*', 'web/fonts/*'])
 .pipe(clean());
});
gulp.task('default', ['clean'], function () {
 var tasks = ['images', 'fonts', 'less', 'lib-js', 'pages-js'];
tasks.forEach(function (val) {
 gulp.start(val);
 });
});
gulp.task('watch', function () {
 var less = gulp.watch('web-src/less/*.less', ['less']),
 js = gulp.watch('web-src/js/*.js', ['pages-js']);
});

After a few seconds we’ll have app.css and app.js files in our symfony application. Include these files in base.html.twig.

Now we have a full replacement for Assetic Bundle in place, it’s time to remove the original:

  1. remove the assetic configuration in app/config/config.yml and app/config/config_dev.yml
  2. remove Assetic Bundle from the app/AppKernel.php
  3. run the following command in console:
composer remove "symfony/assetic-bundle"

And there you have it! A functioning, reliable replacement for Assetic Bundle.