Starting a new project with Laravel 5, Gulp, Bower, and Bootstrap.

 

Edit:

Shortly after posting this guide Laravel 5 announced a new feature calledLaravel Elixer that does half this guide automatically. You can still learn from this guide about how it works “under the hood” so to speak, as well as how to integrate Bootstrap or other css frameworks, but you’ll likely want to migrate to Elixer. Check out the free video on Laracasts to learn more.


Laravel 5 (as of the time of this post) is currently under development, but if you’ve got a new project and want to use Laravel without worrying about having to upgrade soon, you can still start a new project with Laravel 5. Just note that you will have to pay attention to the commits and update accordingly if your app suddenly breaks without explanation.

Since we’re starting a new project I’m also going to discuss how to set up an efficient working environment using Gulp and Bower, as well as installing and setting up Bootstrap. We will also include PHPUnit, but those steps are optional.

For those that don’t know, Bower is a package manager for downloading frameworks, libraries, assets, utilities, and more. We are going to use it to install Boostrap and jQuery. Gulp, on the other hand, will be used to help us compile our CSS, LESS, and JS files, including the ones from Bootstrap. We will also be setting up the project so we can use all the convenient Bootstrap LESS variables.

This guide should be everything you need to start a new Laravel project and hit the ground running.

Install Laravel 5

I’m going to assume you have Composer already installed. If you don’t please have a look at the documentation.

composer create-project laravel/laravel example-app dev-develop --prefer-dist  

Remember to replace example-app with the name of your project.

This will download and set up a fresh Laravel 5 installation from the development branch. If you want to use PHPUnit for testing you should open up your composer.json and add:

"require-dev": {
    "phpunit/phpunit": "4.3.0"
},

Install Bower and Gulp

If you haven’t already you should install NodeJS. You can easily do it with help from their website. Once you’ve done that you can install Bower and Gulp with the following commands. If you get an error you may need to run them as an administrator with the sudo command.

npm install -g bower  
npm install -g gulp  

You’ll also need to install Gulp in the project directory for development.

cd example-app  
npm install --save-dev gulp  

You should also add /node_modules your .gitignore.

Set up Bower

Have a look at the directory structure of your new project.

example-app  
- app
- bootstrap
- config
- database
- public
- resources
  - assets
  - lang
  - views
- storage
- tests
- vendor

We want store all our development assets in resources/assets and our production assets in public/assets, so we need to configure Bower to use our development directory. Create a new file called .bowerrc and save it in the document root directory. All the file needs to contain is:

{
  "directory": "resources/assets/vendor"
}

Now we need to tell it what assets to get. There are a few different ways to do that but the most maintainable way is to create a new file called bower.json and place it in your document root directory. In here you can list all the packages you want to install. Take a look at the extensive package directory and keep and eye out for Bootstrap. Click on it when you find it to be directed to the Bootstrap Github repository. From there you can click onreleases to figure out what version you want to pull in. At the time of this writing the latest release is v3.2.0, so let’s put that into our bower.jsonfile.

{
  "name": "ExampleApp",
  "dependencies": {
    "bootstrap": "~3.2.0"
  }
}

Bootstrap will automatically require jQuery, so we don’t need to put that in too.

Now that we have our dependencies set up we can run:

bower update  

Set up Gulp

We’re now going to set up Gulp to compile to the correct directories, but first we need to fetch the dependencies we need with Node. To do that you’ll have to make a new file named package.json.

{
  "name": "ExampleApp",
  "version": "0.0.0",
  "description": "",
  "main": "gulpfile.js",
  "keywords": [
    "Laravel",
    "Gulp",
    "Bower",
    "Bootstrap"
  ],
  "author": "Your Name",
  "license": "MIT",
  "devDependencies": {
    "gulp": "^3.8.8",
    "gulp-less": "^1.3.6",
    "gulp-sass": "^1.0.0",
    "gulp-minify-css": "^0.3.10",
    "gulp-concat": "^2.4.1",
    "gulp-uglify": "^1.0.1",
    "gulp-rename": "^1.2.0",
    "gulp-phpunit": "^0.6.3",
    "gulp-notify-growl": "^1.0.2",
    "gulp-notify": "^1.8.0"
  }
}

Let’s install the dependencies by running:

npm install  

If you look back in package.json you’ll notice the variable main set to gulpfile.js. We need to create this file, so let’s do that.

In this file we need to do a lot of things. Let’s start by pulling in the plugins we just grabbed with Node. Note that if you don’t plan on using PHPUnit you can leave out notifygrowl, and phpunit from any lines pertaining them for the rest of the guide.

var gulp = require('gulp'),  
    less = require('gulp-less'),
    sass = require('gulp-sass'),
    minify = require('gulp-minify-css'),
    concat = require('gulp-concat'),
    uglify = require('gulp-uglify'),
    rename = require('gulp-rename'),
    notify = require('gulp-notify'),
    growl = require('gulp-notify-growl'),
    phpunit = require('gulp-phpunit');

Next, we need to set up our paths. These will correlate to the directories we discussed earlier. For simplicity we will set up both dev and productionpaths.

var paths = {  
    'dev': {
        'less': './resources/assets/less/',
        'js': './resources/assets/js/',
        'vendor': './resources/assets/vendor/'
    },
    'production': {
        'css': './public/assets/css/',
        'js': './public/assets/js/'
    }
};

Now let’s set up some tasks. Each Gulp module has a specific function and we will use them in series to get the result we want.

// CSS
gulp.task('css', function() {  
  return gulp.src(paths.dev.less+'app.less')
    .pipe(less())
    .pipe(gulp.dest(paths.production.css))
    .pipe(minify({keepSpecialComments:0}))
    .pipe(rename({suffix: '.min'}))
    .pipe(gulp.dest(paths.production.css));
});

// JS
gulp.task('js', function(){  
  return gulp.src([
      paths.dev.vendor+'jquery/dist/jquery.js',
      paths.dev.vendor+'bootstrap/dist/js/bootstrap.js',
      paths.dev.js+'js'
    ])
    .pipe(concat('app.min.js'))
    .pipe(uglify())
    .pipe(gulp.dest(paths.production.js));
});

// PHP Unit
gulp.task('phpunit', function() {  
  var options = {debug: false, notify: true};
  return gulp.src('./tests/*.php')
    .pipe(phpunit('./vendor/bin/phpunit', options))

    .on('error', notify.onError({
      title: 'PHPUnit Failed',
      message: 'One or more tests failed.'
    }))

    .pipe(notify({
      title: 'PHPUnit Passed',
      message: 'All tests passed!'
    }));
});

To make things work automatically let’s tell Gulp to watch our directories for changes, and if a file is updated, run the appropriate task.

gulp.task('watch', function() {  
  gulp.watch(paths.dev.less + '/*.less', ['css']);
  gulp.watch(paths.dev.js + '/*.js', ['js']);
  gulp.watch('./tests/*.php', ['phpunit']);
});

Finally, let’s set a default task to do all of the above whenever we run gulp.

gulp.task('default', ['css', 'js', 'phpunit', 'watch']);  

Try it out by running gulp from the command line. If it was successful you’ll notice a new assets folder inside your public directory. It should only have js folder in it right now, so let’s fix that.

Setting Up Bootstrap

Now that we have Bootstrap installed in assets/vendor/bootstrap let’s set up our project to take advantage of all the Bootstrap LESS variables and other goodies.

In your gulpfile.js you’ll notice we specified using resources/assets/less in the paths.dev.less variable, so we need to put all our LESS files in that directory.

First let’s create app.less:

// app.less

@import 'bootstrap.less';

You can use this file to import all your applications LESS files, or if you choose to work from a single file you can use this one. Take notice that we import bootstrap.less, so let’s create that now. This file will be almost the same as the bootstrap.less file in vendor/bootstrap/less with a few minor alterations.

// bootstrap.less

// Core variables and mixins
@import "variables.less";
@import "../vendor/bootstrap/less/mixins.less";

// Reset and dependencies
@import "../vendor/bootstrap/less/normalize.less";
@import "../vendor/bootstrap/less/print.less";
@import "../vendor/bootstrap/less/glyphicons.less";

// Core CSS
@import "../vendor/bootstrap/less/scaffolding.less";
@import "../vendor/bootstrap/less/type.less";
@import "../vendor/bootstrap/less/code.less";
@import "../vendor/bootstrap/less/grid.less";
@import "../vendor/bootstrap/less/tables.less";
@import "../vendor/bootstrap/less/forms.less";
@import "../vendor/bootstrap/less/buttons.less";

// Components
@import "../vendor/bootstrap/less/component-animations.less";
@import "../vendor/bootstrap/less/dropdowns.less";
@import "../vendor/bootstrap/less/button-groups.less";
@import "../vendor/bootstrap/less/input-groups.less";
@import "../vendor/bootstrap/less/navs.less";
@import "../vendor/bootstrap/less/navbar.less";
@import "../vendor/bootstrap/less/breadcrumbs.less";
@import "../vendor/bootstrap/less/pagination.less";
@import "../vendor/bootstrap/less/pager.less";
@import "../vendor/bootstrap/less/labels.less";
@import "../vendor/bootstrap/less/badges.less";
@import "../vendor/bootstrap/less/jumbotron.less";
@import "../vendor/bootstrap/less/thumbnails.less";
@import "../vendor/bootstrap/less/alerts.less";
@import "../vendor/bootstrap/less/progress-bars.less";
@import "../vendor/bootstrap/less/media.less";
@import "../vendor/bootstrap/less/list-group.less";
@import "../vendor/bootstrap/less/panels.less";
@import "../vendor/bootstrap/less/responsive-embed.less";
@import "../vendor/bootstrap/less/wells.less";
@import "../vendor/bootstrap/less/close.less";

// Components w/ JavaScript
@import "../vendor/bootstrap/less/modals.less";
@import "../vendor/bootstrap/less/tooltip.less";
@import "../vendor/bootstrap/less/popovers.less";
@import "../vendor/bootstrap/less/carousel.less";

// Utility classes
@import "../vendor/bootstrap/less/utilities.less";
@import "../vendor/bootstrap/less/responsive-utilities.less";

Like any Bootstrap installation you can pick and choose which components you need by commenting out the ones you don’t want, but the thing to note here is the import paths. All of them point to the vendor bootstrap files except for variables.less. This is because we want to edit variables.less without tampering with it in vendor, so we are going to copy it into our assets/less directory instead. You can do that now. Once you are done, run gulp again. It should compile everything into public/assets.

Finishing Up

We’re basically done now. All that’s left to do is link to your compiled assets to your master layout. Just don’t forget that in Laravel 5 your views are now located in resources/views.

If you have any questions please don’t hesitate to leave them in the comments.

Thanks for reading.