Production Ready Asset Pipeline with Elixir

For past laravel projects I’ve been maintaining my own package for setting up grunt and gulp in an instant. Laravel-asset was nothing special but it got the work done and saved me a lot of time when spinning up new projects.

Laravel Elixir has been out for a while and is solving the same issue but in a different way. Instead of giving you long example files that a preconfigured to do everything you normally would want out of the box, they opted to create a new api for gulp that is far more simple. Making building the same functionality that laravel-asset offered very simple.

I thought I would share how to get the same functionality in Elixir and decomission laravel-asset officially.

Features we need to setup:

  • Compile sass
  • Concatenate js with browserify
  • Minify css
  • Minify js
  • Minify images
  • Add cache busting hashes to each url
  • Start LiveReload (now BrowserSync)

Our gulp.js file:

elixir(function(mix) {
    mix.copy('resources/assets/fonts', 'public/fonts');
    mix.browserify('app.js');
    mix.sass('app.scss');
    mix.imagemin();
    mix.version(['css/app.css', 'css/app.js']);
    mix.browserSync();
});

In your blade files as per the Elixir documentation, for cache busting to work you need to reference your css and js files using the Elixir function like so:

<link rel="stylesheet" href="{{ elixir('css/all.css') }}">
<script src="{{ elixir('js/app.js') }}"></script>

As of right now Elixir does not support imagemin and browserSync out of the box. For this reason you will need to install 3rd party elixir tasks.

npm install --save-dev laravel-elixir-imagemin

And require them on the top of your gulp.js file.

require('laravel-elixir-imagemin');

BrowserSync

For BrowserSync to work you need to use port 3000 when accessing your app http://homestead.app:3000.

If you’re using a custom domain you will need to configure BrowserSync like so:

mix.browserSync({proxy: 'custom.app'});

Also given we are using BrowserSync in conjunction with versioning the build in elixir() function will cause us some problems. I sent a pull request to Taylor, but in the meantime define a similar function and use it in your views like so:

/**
 * Get the path to a versioned Elixir file.
 *
 * @param  string  $file
 * @return string
 *
 * @throws \InvalidArgumentException
 */
function eelixir($file)
{
	if (App::environment('local')) {
		return $file;
	}

	return elixir($file);
}

Update

Got my pull request for BrowserSync support in Elixir accepted, so less I’ve updated the post to reflect this.