Interested how Laravel works under the hood? → Check my Laravel Core Adventures Course

How to Laravel series: Let's talk Gulp

#javascript

I'm too old for this sh**.

This post has already become quite old, and a lot has changed in that field since I wrote it. The examples I provide might not work anymore or are not suitable for how we work today. Please be aware of that while reading it.

In my last article I explained two ways of implementing Grunt to your Laravel application. Now we are taking a look at the same setup, but we are using Gulp instead of Grunt. Gulp what? Don’t worry, I will show you what Gulp is, how it works and why you probably should consider switching.

Introducing Gulp

Gulp is a JavaScript task-runner like Grunt. In fact, it is almost like Grunt. You can automate tasks for your workflow, you’re using similar modules and still there are some important differences you should know about. But before we check it out, let’s remind ourselves of what felt kind of awkward while using Grunt:

  • our Gruntfile was huge
  • the code was difficult to read
  • the modules have too much power, they are accomplishing far more than they should and there are too many repeating tasks

Now that we know where we stand, let's dive right in.

Setup

Take a fresh Laravel installation and put a folder called assets to your public folder. We are using the exact same file structure like we did the last time with Grunt.

assets/
    css
    images
    images-orig/
        image.jpg
    js/
        main.js
    sass/
        _styles.scss
        ui/
            _base.scss
            _normalize.scss

Our tasks are the same too:

  • Styles: Compiling and compressing our Sass files
  • Uglify: Compressing our JavaScript
  • Imagemin: Optimising our images
  • Watch: Doing all the things above, automatically
  • Livereload: Refresh the browser on a file's change

First we create a package.json file in our assets's root. We need to fill it with an empty object. This is because we will install all the modules with the --save parameter. This will save the module's dependencies right in our package.json file. At the end all our modules will be listed in this file and we have a nice overview of what we are using.

{}

Next we need to install Gulp globally and locally.
Again we are using the --save parameter, because Gulp itself is a module too.

npm install -g gulp
npm install --save-dev gulp

The second file we need is the Gulpfile.js. This is where we create all of our tasks.

// Get modules
var gulp = require('gulp');

// Task boilerplate
gulp.task('taskname', function() {

});

// The default task (called when you run `gulp` from cli)
gulp.task('default', ['']);

We need to define all of the modules that we want to use first. Afterwards we define an empty task and the default tasks. This is what will be triggered when we run the "gulp" command.

Task styles

Gulp module: gulp-sass  The first taks we will create is the Styles task. Here we want to compile our Sass file and save the CSS file in a different directory. This is super easy and when you see the code, you will immedatly notice what is going on. We will begin with installing the Sass module. Again, the save parameter will write this new dependency right to our package.json file.

npm install gulp-sass --save

Now let's take a look at the task's code. First we use a Gulp API function called src to pick the file. This is one of the major advantages we have with Gulp. Selecting files is something we need to do all the time in our tasks, this is why Gulp is taking care of this action and not the modules. Next we take the selected file and we pipe it to another function. This is the Sass module's function we have defined at the top of the Gulpfile. And at the end we take the compiled file and we define a destination which is another Gulp API function. Now we set this task as a default one.

// Get modules
var gulp = require('gulp');
var sass = require('gulp-sass')

// Task Sass
gulp.task('sass', function () {
    gulp.src('sass/styles.scss')
        .pipe(sass())
        .pipe(gulp.dest('css'));
});

// The default task (called when you run `gulp` from cli)
gulp.task('default', ['sass']);

Three lines of code, everything works and everyone immediately knows what is going on. This is really great! When we now run "gulp" the new CSS file will be created.

Task script

Gulp modules: gulp-uglify, gulp-rename  Next we want to minify our script. Here we need two more modules: one for minifying the file(Uglify) and another to rename the output. Let's install them.

npm install gulp-uglify --save
npm install gulp-rename --save

In our simple assets scenario, we want a single main.js file to be minified. Again we are using the Gulp API methods src and dest. Between those, we pipe the selected file through the uglify and the rename module.

gulp.task('scripts', function() {
    gulp.src('js/main.js')
        .pipe(uglify())
        .pipe(rename('main.min.js'))
        .pipe(gulp.dest('js'))
});

This task is very simple too. We can run it with "gulp scripts" or we set it as default like our first one.

Task imagemin

Gulp module: gulp-imagemin The next task we are going to build will optimize our images. The module we use is called Imagemin.

npm install gulp-imagemin --save

Instead of selecting one file, we will select all files within the images-orig folder. Then these images are optimized through the Imagemin module and saved in the destination folder named images.

gulp.task('images', function () {
    gulp.src('images-orig/*.{png,gif,jpg}')
        .pipe(imagemin())
        .pipe(gulp.dest('images/'));
});

Task watch

So far so good. We have all the main tasks created and I'm sure you have recognized the clean and simple way working with Gulp. But like in my last Grunt article we want to watch our asset files and trigger the right tasks on a change. We handle this with another Gulp API method: watch. Yeah right. We do not need another Gulp module, because watch is a built-in Gulp task. Let's take a quick look at the syntax. We are telling the watch method where to look for a change and which task to trigger afterwards.

gulp.task('watch', function () {
    gulp.watch('sass/**/*.scss', ['styles']);
    gulp.watch('js/**.js', ['scripts']);
    gulp.watch('images-orig/**', ['images']);
});

Task livereload

Gulp module: gulp-livereload Our final task will handle the refresh of the browser: livereload.

npm install --save gulp-livereload

Don't forget to set the variable for this module after installation, like we did for the other module's as well. We can now pipe livereload to our tasks. Of course you need the livereload browser extension too to make this work!

gulp.task('styles', function () {
    gulp.src('sass/styles.scss')
        .pipe(sass())
        .pipe(gulp.dest('css'))
        .pipe(livereload());
});

Now that you know how to add livereload to a task, you can use it whenever you need it. But there is more. Wouldn't it be great if we could refresh the browser if our Laravel views are changed? Yes! So let's add this too.

gulp.task('watch', function () {
    var server = livereload();

    gulp.watch('sass/**/*.scss', ['styles']);
    gulp.watch('js/**.js', ['scripts']);
    gulp.watch('images-orig/**', ['images']);
    gulp.watch('../../app/views/**/*.php').on('change', function(file) {
    server.changed(file.path);
});

We added two things here. First a variable called server. It is used in combination with the on method. We select all PHP files in our views folder and on a change we want to refresh the browser. Additonally we print out the name of the changed file. Let's test this right now. Start Gulp with the standard gulp command. Now change the hello.php file which comes with every Laravel installation. When you save the save the browser should reload. (Don't forget to enable the livereload browser extension)

Conclusion

Now that we are done, let's compare this Gulp setup with the Grunt one from my last article. With Grunt we needed about 80 lines to accomplish these tasks. Now we wrote less than 50 and the code is much more readable. Isn't this awesome?! I really fell in love with this syntax and Gulp is now my JavaScript task-runner of choice. Of course I would not recommend everybody to change immediatly their workflow. There are still much more modules for Grunt and maybe you  prefer to write your tasks in JSON. That's great too. Use what is best for you and your workflow, but I suggest to check out Gulp and maybe you will love it too. Find all of the code at Github here.

Do you enjoy my posts?

Sign up for my newsletter to receive updates on my latest content.

You will receive monthly updates on my latest articles and products. I do care about the protection of your data. Read my Privacy Policy.