Run Gulp Tasks in Laravel Easily with Elixir

As a developer(frontend or backend), you might have probably or still use a task runner, for those who haven’t used a task runner, a task runner is simply an automated tool for performing repetitive tasks like concatenation, minification, unit testing, linting e.t.c.

There are awesome task runners on github available for everyone to use, but out of all the task runners, gulp and grunt really stand out as they are very popular, mature and mostly used by developers.

For this article, gulp is a requirement and if you are new to gulp, this article should be extremely useful.

Elixir

When developing applications, there are many repetitive processes involved:

  • write a script
  • test your script
  • write a sass file
  • compile it
  • compress files and more

Sure we could write tasks with gulp and they do the job just fine, but as of Laravel 5, a new feature named Elixir has been added to Laravel.

Elixir developed by Jeffrey Way is a task runner built as a wrapper around gulp, it comes with basic tasks like:

  • compilation of sass, less and coffee files
  • concatenation
  • unit testing and more

Elixir is also open for extension as you could also define your gulp tasks and add it to elixir.

Configuration

Although not specified in the official documentation, elixir is configurable, due to the fact that elixir exposes a config object on the elixir object. A few of the configurable options include

  • production – checks if the current environment is set to production, defaults to true
  • assetsDir – assets directory path, default is resources/assets
  • cssOutput – default output directory for all css files, default is public/css
  • jsOutput – default output directory for all js files, default is public/js
  • sourcemaps – if sourcemaps should be generated, default is true

Assets Compilation

To use elixir, from the root of your Laravel application run the command:


npm install

There should be a package.json file with the dependencies (gulp and laravel-elixir) listed.

Less and Sass

In your gulpfile.js you should see something like this to start.


var elixir = require('laravel-elixir');
    
elixir(function(mix) {
    mix.less('app.less');
});

All this simply does is compile a less file named app.less which is located in resources/assets/less. After compilation, the file is stored in public/css.

To compile sass files you would basically do the same thing but instead of storing the sass file in resources/assets/less you would store it in resources/assets/sass folder and compile it using:


elixir(function(mix) {
    mix.sass('app.scss');
});

You could also compile .sass files. If you prefer using ruby sass instead of libsass you would just change the method on the mix object from sass to rubySass, but for this to work you’ll need sass installed on your computer.

Coffeescript

The mix object also exposes a coffee method that compiles coffee files in resources/assets/coffee and saves them in public/js folder.

Compilation of multiple files is also possible, all you need do is pass an array containing names of files to compile


mix.sass(['awesome.scss', 'legendary.scss']);
mix.coffee(['awesome.coffee', 'legendary.coffee']);

Method chaining

Method chaining is also allowed if you want to use multiple tasks at once.


mix.sass('legendary.scss')
    .coffee('legendary.coffee');

Vendor Prefixes

Furthermore, you do not need to worry about CSS vendor prefixes, as elixir comes with gulp-autoprefixer, so if you write a CSS property that still requires vendor prefixes it automatically adds them for you.

If you wrote something like this:


a:hover {
    transform: scale(1.1);
}

you would get:


a:hover {
    -webkit-transform: scale(1.1);
    -moz-transform: scale(1.1);
    transform: scale(1.1);
}

Before rounding up on assets compilation, you should know that the less, sass, rubySass and coffee functions all take in three parameters

  • Source: The name of the file or an array of files to compile.
  • Output: The output directory to save the compiled files.
  • Options: Configurable options for compilation depending on the plugin used e.g options for coffee compilation would be options you would use for gulp-coffee plugin.

Concatenation

You can also concatenate files with elixir, to combine your stylesheets just use


mix.styles([
    'module1.css',
    'module2.css'
]);

By default, files are combined from resources/css directory, the combined files are then stored in public/css and the result of the combination is saved as all.css.

The same is true for JavaScript files with only a few exceptions, the method on the mix object is named scripts the source directory is resources/js and destination is public/js and the output file is named app.js.


mix.scripts([
    'module1.js', 'module2.js'
]);

Changing Output File

To change the name of the output file, you pass in a second parameter to the styles or scripts method


mix.scripts(
    ['module1.js', 'module2.js'],
    'path/to/output/file.js'
);

Change Source Directory

By default, elixir will look into the resources/ folder. To change the source directory, you pass in a third parameter with the path to the directory.


mix.scripts(
    ['module1.js', 'module2.js'],
    'path/to/output/file.js',
    'path/to/source'
);

The mix object also exposes the other methods for combining files in a directory, to combine all css files in a directory


mix.stylesIn('public/css');

and for javascript files


mix.scriptsIn('public/js');

Versioning or Hashing

When you fix a javascript or css file and you push the changes to your server, some users instantly get the update while others don’t due to the fact that their browser still has the previous script cached, to fix this problem developers always change the name of the file either by appending a query string to the file or using random strings to name the file, this process is known as hashing or versioning.

Elixir also includes hashing, to hash a file you simply:


mix.version('path/to/file');

all files to be hashed no matter the path provided is relative to the public folder. Hashing of multiple file is also supported, to hash multiple files, pass in an array of files.


mix.version(['path/to/file1', 'path/to/file2']);

After hashing, all files are saved in public/build and a unique hash is placed between the filename and the file extension.


mix.version('css/main.css'); // public/build/css/main-39d5f9a7.css
mix.version('js/app.js'); // public/build/js/app-78efbae6.js

To always use the latest versioned/hashed file from your blade templates or just from any php file, Laravel provides a helper function elixir. Without this function you would have to manually type in the name of the hashed file every time you compile an asset.


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

Running your test suites

By default elixir comes with two tasks for your test suites. One for phpunit and the other for phpspec, in your gulpfile phpUnit method is called on the mix object for phpunit test suite


mix.phpUnit();

while for phpspec


mix.phpSpec();

Execute elixir tasks

To run the tasks listed above, you can simply run


gulp

From the root of your Laravel application, this should run all the tasks defined in your gulpfile. Instead of running gulp everytime you make a change you can just run

Watch Files for Changes


gulp watch

to watch the files for changes, so whenever you save a sass file, it is automatically compiled, if any test task is defined, whenever you save your php file your configured test suite is run.

There is also an optional --production flag you can pass to the gulp command to trigger asset optimization like minification.

Execute a Single Task

Sometimes you might just want to run a single task, and for style compilation run


gulp styles

for compilation of coffeescript files


gulp scripts

for your test suites run


gulp tdd

this does not only run your test suite, it also watches your files for changes.

Custom Tasks and extensions

It is very evident that elixir comes with some helpful tasks but, not all the required ones for example there is no task for stylus compilation, or image compression, but other users have developed tasks as packages for these purposes, to define your own task, you simply need to extend elixir.


elixir.extend(nameOfTask, function(arguments) {
    // define a gulp task here
    // setup watcher for certain files which is optional
    // queue the gulp task
});

Let’s build a simple task that logs the current date to the console.


var gulp = require('gulp'),
    elixir = require('laravel-elixir');
    
elixir.extend('logDate', function() {
    gulp.task('date_logger', function() {
        console.log(new Date());
    });
    
    // this.registerWatcher('date_logger', '/**/*.js');
    return this.queueTask('date_logger');
});

To use the above task, from your mix object, call


mix.logDate();

and if the watcher is uncommented, you can run


gulp watch 

From the command line and whenever a file with js extension is saved the logDate task is run.

Conclusion

Gulp is a powerful tool on its own and Elixir only makes using it even easier. Add in the Laravel goodness like the helper functions and Elixir is a great tool to integrate Gulp into your Laravel projects.

Give it a try and let us know how you like it in the comments.

Samuel Oloruntoba

Self-proclaimed full-stack web developer and a quasi-academic. I work mostly on the backend (PHP and Node) with a recent enthusiasm for frontend development (React, SVG, HTML5 Canvas).