Deploy Vue.js, Laravel 5, Bootstrap, LESS/SCSS, Gulp, Browserify

Start your project with Vue.js as front-end, Laravel 5 as back-end and Gulp task runner to streamline your workflow.
A detailed guide so I could understand it myself.

PS: This guide is yet to finish…

Git

Init Git

git init

Create .gitignore

#### Laravel .gitignore
laravel/bootstrap/compiled.php
.env.*.php
.env.php
.env

#### Node .gitignore
# Logs
logs
*.log

# Runtime data
pids
*.pid
*.seed

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# node-waf configuration
.lock-wscript

# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release

# Dependency directory
# https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git
node_modules

#### Sass .gitignore
.sass-cache
*.css.map

#### Elixir .gitignore
/_build
/deps
erl_crash.dump
*.ez

#### Linux .gitignore
*~

# KDE directory preferences
.directory

# Linux trash folder which might appear on any partition or disk
.Trash-*

#### OSX .gitignore
.DS_Store
.AppleDouble
.LSOverride

# Icon must end with two \r
Icon


# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk

#### Windows .gitignore
# Windows image file caches
Thumbs.db
ehthumbs.db

# Folder config file
Desktop.ini

# Recycle Bin used on file shares
$RECYCLE.BIN/

# Windows Installer files
*.cab
*.msi
*.msm
*.msp

# Windows shortcuts
*.lnk

#### Vim .gitignore
[._]*.s[a-w][a-z]
[._]s[a-w][a-z]
*.un~
Session.vim
.netrwhist
*~

#### Sublime Text .gitignore
# cache files for sublime text
*.tmlanguage.cache
*.tmPreferences.cache
*.stTheme.cache

# workspace files are user-specific
*.sublime-workspace

# project files should be checked into the repository, unless a significant
# proportion of contributors will probably not be using SublimeText
# *.sublime-project

# sftp configuration file
sftp-config.json

Commit the Git

git add .gitignore
git commit -avm "INIT .gitignore - vue-js-laravel-gulp-deployment"

Install Laravel with Composer

Head to: https://getcomposer.org/download/
or use this

curl -sS https://getcomposer.org/installer | php

You can shorten the command composer instead of php composer.phar with alias

Type alias composer='php composer.phar'

composer create-project laravel/laravel --prefer-dist

or

composer create-project laravel/laravel laravel 5.1.3 --prefer-dist

This guide is written for Laravel 5.1.3

Goto laravel directory and run
composer update afterwards to make sure Laravel dependencies are updated

Goto laravel directory and run
php artisan key:generate afterwards to make sure you generate a key in
./laravel/app/config/app.php

Install NodeJS and others once

You may skip this if you already have done this.

Install NodeJS

Option 1 on Mac

I recommend to use Brew for your developing environment. To install Node and such unix-like dependencies, such as NodeJS, Nginx, Apache, etc.

Install Brew

Installing Homebrew from the terminal

ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

If ruby -e command not working for you, you should install XCode first from the App Store. This will help install Brew on your Mac

Check your brew health with:

brew doctor

If you installed a brew formula for example gettext, link it with brew link <formula>:

brew link gettext

More info about Brew for Mac

Install NodeJS

If your Brew is successfully installed

brew install npm

This will install node and npm.

Check your installation:

npm -v and node -v

Mine will say: 2.11.2 and v0.12.5

Now you can install any node dependencies with the flag -g without sudo.

For example: npm install -g browserify
instead of: sudo npm install -g browserify

End OPTION 1

Option 2

It's really great and small for the tasks you're going to love.
Head to: http://nodejs.org/
Make sure you install with sudo command

End OPTION 2

Install Node Dependencies

Also install GulpJS and Bower.IO

Use sudo for any npm install -g if you don't use brew for Mac.

npm install -g gulp
npm install -g bower
npm install -g browserify

Single line command:

sudo npm install -g gulp bower browserify

With the flag -g you installed it globally and now you can access it from anywhere on your system.

Gulp - The streaming build system

Bower - A package manager for the web

Browserify - browser-side require() the node way

What is Gulp

Official definition: Gulp: the streaming build system

Gulp is basically a tool that automates your frontend tasks, but it goes beyond that if you want it. It can upload your changed files to CDN networks, copy files to production environment, optimize images and more. There are inumerous plugins for all these functions and if you can't find one that suits your needs, you can always write your own.

Initialise a Gulp project

To initialise a new Gulp project from your project's directory run

npm init

and follow the instructions. The command will create your package.json file, necessary for any npm project.

name: vuejs-laravel-gulp-deployment
version: 0.0.0
description: Deployment with Vue, Laravel, Bootstrap with Gulp
entry point: gulpfile.js
test command: Enter
git repository: https://github.com/HariantoAtWork/vuejs-laravel-gulp
keywords: VueJS, Laravel, Bootstrap, LESS, SCSS, Gulp, Browserify, mdstn.com, mizu.work
author: Harianto van Insulinde
license: CC-BY-4.0
Is this ok? (yes): Enter

{
  "name": "vuejs-laravel-gulp-deployment",
  "version": "0.0.0",
  "description": "Deployment with Vue, Laravel, Bootstrap with Gulp",
  "main": "gulpfile.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/HariantoAtWork/vuejs-laravel-gulp.git"
  },
  "keywords": [
    "VueJS",
    "Laravel",
    "Bootstrap",
    "LESS",
    "SCSS",
    "Gulp",
    "Browserify",
    "mdstn.com",
    "mizu.work"
  ],
  "author": "Harianto van Insulinde",
  "license": "CC-BY-4.0",
  "bugs": {
    "url": "https://github.com/HariantoAtWork/vuejs-laravel-gulp/issues"
  },
  "homepage": "https://github.com/HariantoAtWork/vuejs-laravel-gulp#readme"
}

Finally, let's install gulp and some plugins as dependencies. We'll use:

  • "gulp-less": For LESS compilation
  • "gulp-sass": For SASS compilation
  • "gulp-autoprefixer": Adds CSS prefix for browser compatibility
  • "gulp-minify-css": For minifying CSS
  • "gulp-concat": For concatenation
  • "gulp-uglify": For javascript minification
  • "gulp-rename": For renaming files
  • "gulp-phpunit": For PHP Unit testing

In your terminal run:

npm install --save-dev gulp 
npm install --save-dev gulp-less  
npm install --save-dev gulp-sass  
npm install --save-dev gulp-autoprefixer 
npm install --save-dev gulp-minify-css  
npm install --save-dev gulp-concat  
npm install --save-dev gulp-uglify 
npm install --save-dev gulp-rename
# optional
npm install --save-dev gulp-phpunit
npm install --save-dev gulp-livereload 
npm install --save-dev gulp-notify 
npm install --save-dev node-notifier 
npm install --save-dev stream-combiner2 

Or use this single command:

npm install --save-dev gulp gulp-less gulp-sass gulp-autoprefixer gulp-minify-css gulp-concat gulp-uglify gulp-rename gulp-phpunit gulp-livereload gulp-notify node-notifier stream-combiner2 --cache-min 999999

We’re not going to use laravel-elixir for gulp

For VueJS (MVVM)

npm install --save vue

this will save as dependencies instead of devDependencies

If you already install this dependency before, add this extra flag:

--cache-min 999999.

That will install the dependencies and because we defined the --save-dev flag it will add them to the package.json file.

Bower

Bower - A package manager for the web

Set path Bower dependencies installation

After we’ve done installing Laravel with Composer while ago. We’re going to set up the path for Bower dependencies before we continue or it will install in the default directory bower_components. First we must create a file .bowerrc.
with

{
  "directory": "laravel/resources/assets/bower_components"
}

Initialise Bower

Just like we did for package.json we need to initiate the file for Bower. So we could save dependencies and download it back when we have to.

To initialise Bower from you project’s directory run:

bower init

and follow the instructions. The command will create your bower.json file, necessary for any Front End needs.

? May bower anonymously report usage statistics to improve the tool over time? (Y/n) : n

? name: (public) : vuejs-laravel-gulp-deployment

? version: (0.0.0) : Enter

? description: Deployment with Vue, Laravel, Bootstrap with Gulp

? main file: gulpfile.js

? what types of modules does this package expose?

  ◯ amd

  ◯ es6

  ◯ globals

❯◯ node

  ◯ yui

? keywords: VueJS, Laravel, Bootstrap, LESS, SCSS, Gulp, Browserify, mdstn.com, mizu.work

? authors: Harianto van Insulinde

? license: (MIT) : CC-BY-4.0

? homepage: mizu.work or mdstn.com

? set currently installed components as dependencies? (Y/n) :Enter

? add commonly ignored files to ignore list? (Y/n) :Enter

? would you like to mark this package as private which prevents it from being accidentally published to the registry? (y/N) : y

? Looks good? (Y/n) :Enter

{
  name: 'vuejs-laravel-gulp-deployment',
  version: '0.0.0',
  description: 'Deployment with Vue, Laravel, Bootstrap with Gulp',
  main: 'gulpfile.js',
  keywords: [
    'VueJS',
    'Laravel',
    'Bootstrap',
    'LESS',
    'SCSS',
    'Gulp',
    'Browserify',
    'mdstn.com',
    'mizu.work'
  ],
  authors: [
    'Harianto van Insulinde'
  ],
  license: 'CC-BY-4.0',
  homepage: 'mizu.work',
  ignore: [
    '**/.*',
    'node_modules',
    'bower_components',
    'laravel/resources/assets/bower_components',
    'test',
    'tests'
  ]
}

When you set .bowerrc correctly, you'll see the path:
laravel/resources/assets/bower_components is in the ignore, which is good.

Frontend dependencies

We'll be using Bootstrap and jQuery so let's install them with Bower.

Now run:

bower install -S bootstrap

The -S|--save flag will save the dependency in the bower.json file and later you can just run bower install to replicate the exact front-end dependencies of your project. If you're not one of those guys paranoid about github just dying one day and our poor selves left without our packages, you can freely add bower_components to your .gitignore file and just track bower.json.

I know you noticed already; I'm forgetting about jQuery. But actually we already got it. In its bower.json file Bootstrap defines that it depends on jQuery, so it got automatically pulled in together with Bootstrap.

Read more information about bower on http://bower.io

Here's how our components folder turned out (only the parts that concern us):

/  laravel/resources/assets/bower_components
   /  bootstrap
      /  dist
         /  js
            - bootstrap.js
            - bootstrap.min.js
         /  less
            - alerts.less
            - badges.less
            - bootstrap.less
            …
            …
            - variables.less
            - wells.less
   /  jquery
      /  dist
         - jquery.js
         - jquery.min.js

Configuring gulpfile.js

Buckle up, here begins the fun part! Let's create the configuration file gulpfile.js in root. This is its basic structure:

// gulpfile.js

// --- INIT
var gulp = require('gulp'),  
    less = require('gulp-less'), // compiles less to CSS
    scss = require('gulp-sass'), // compiles sass to CSS
    autoprefix  = require('gulp-autoprefixer'), // CSS browser compatibility
    cssmin = require('gulp-minify-css'), // minifies CSS
    concat = require('gulp-concat'),
    uglify = require('gulp-uglify'), // minifies JS
    rename = require('gulp-rename'),
// optional
    livereload = require('gulp-livereload'),
    notifier = require('node-notifier');

// Paths variables
var paths = {  
    'resources': {
        'less': './laravel/resources/assets/less/',
        'scss': './laravel/resources/assets/scss/',
        'js': './laravel/resources/assets/js/',
		'bower_components': './laravel/resources/assets/bower_components/',  
        'vendor': './laravel/resources/assets/vendor/', // front-end(css/js) things that has not yet Bower support
    },
    'public': {
        'css': './laravel/public/assets/css/',
        'js': './laravel/public/assets/js/'
    }

};

// --- TASKS

// --- WATCH

// --- COMBINED TASKS

// --- DEFAULT

For paths.resources.vendor you put interesting front end files that has not yet Bower repository. Just for the sake that everything should be logical and neat, for example:

hariantoatwork/front-end-stuff/…

hariantoatwork/js-component/…

other-github-dude/js-webscrape-awesomeness/…

other-bitbucket-dude/amazing-text-animation/…

The stylesheets

Let's create the following filestructure:

/  laravel/resources/assets
   /  less
      /  bootstrap
         - bootstrap.less
         - variables.less

      /  fonts
         - fonts.less

      - frontend.less
      - backend.less

   /  js  
      - frontend.js
      - backend.js
  
   /  bower_components
   /  vendor

/  laravel/public/assets
   /  img
      /  icons
         - favicon.icns
   /  fonts
   /  css
      - frontend.min.css
      - backend.min.css
   /  js
      - frontend.min.js
      - backend.min.js

You can copy bootstrap.less from Bootstrap and rename it to /laravel/resources/assets/less/bootstrap.less

You can copy variables.less from Bootstrap and put it to /laravel/resources/assets/less/variables.less

The file /laravel/resources/assets/less/frontend.less:

@import 'fonts/fonts.less';
@import 'bootstrap/bootstrap.less';   
//styles specific for the frontend 
// … 

The file /laravel/resources/assets/less/backend.less:

@import 'fonts/fonts.less';
@import 'bootstrap/bootstrap.less';   
//styles specific for the backend 
// … 

The stylesheets that are common to both the backend and front end are in bootstrap.less. That's also the file where we include all the components from Bootstrap we need. It will go something like this:

The file /laravel/resources/assets/less/bootstrap/bootstrap.less:

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

// Reset
@import "../../bower_components/bootstrap/less/normalize.less";
@import "../../bower_components/bootstrap/less/print.less";

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

If you already copy the (bower_components Bootstrap) bootstrap.less to (assets/less Bootstrap) bootstrap.less, make sure you correct the path like the script above

Make sure you copy your (bower_components) Bootstrap glyphicons in the public folder:
laravel/public/assets/fonts/glyphicons/

Search @icon-font-path: "../fonts/"; and replace the path with: /assets/fonts/glyphicons/.

The file /laravel/resources/assets/less/bootstrap/variables.less:

/*
…
…
*/
@icon-font-path: "/assets/fonts/glyphicons/"
/*
…
…
*/

Or use this script below to do the folder creating, files copying and change paths

#!/bin/sh
### Script created by @HariantoAtWork
### Date 2015-06-27

# PATHS

ROOT_DIR=`pwd`
RESOURCES_DIR=$ROOT_DIR/laravel/resources
RESOURCES_ASSETS=$RESOURCES_DIR/assets

BOWER_COMPONENTS=$RESOURCES_ASSETS/bower_components
BOOTSTRAP_LESS=$BOWER_COMPONENTS/bootstrap/less
BOOTSTRAP_FONTS=$BOWER_COMPONENTS/bootstrap/fonts

RESOURCES_LESS_BOOTSTRAP=$RESOURCES_ASSETS/less/bootstrap
PUBLIC_DIR=$ROOT_DIR/laravel/public
PUBLIC_ASSETS=$PUBLIC_DIR/assets
PUBLIC_FONTS=$PUBLIC_ASSETS/fonts
GLYPHICONS=$PUBLIC_FONTS/glyphicons


# ACTIONS

## Create folder: bootstrap in less
mkdir -p $RESOURCES_LESS_BOOTSTRAP
## Create glyphicons folder in public if not exist
mkdir -p $GLYPHICONS
# copy Bootstrap fonts to pubic
cp $BOOTSTRAP_FONTS/*.* $GLYPHICONS


## reads variables.less (from Bootstrap directory), change path names and save to current directory
sed 's|"../fonts/"|"/assets/fonts/glyphicons/"|g' $BOOTSTRAP_LESS/variables.less > $RESOURCES_LESS_BOOTSTRAP/variables.less 
## reads bootstrap.less (from Bootstrap directory), change path names, except with the line 'variables' and save to current directory
sed '/variables/!s|@import "|@import "../../bower_components/bootstrap/less/|g' $BOOTSTRAP_LESS/bootstrap.less > $RESOURCES_LESS_BOOTSTRAP/bootstrap.less

cd $ROOT_DIR
echo 'DONE.'

save as: patch_bootstrap_less.sh

and start it with: . patch_bootstrap_less.sh

And let's create some tasks:

// LESS: CSS frontend
gulp.task('less:frontend', function() {  
  // place code for your default task here
  // destination folder: /laravel/public/assets/css/ 
  return gulp.src(paths.resources.less+'frontend.less') // get file
    .pipe(less())
    .pipe(autoprefix({ browsers: ['last 2 versions'] }))
    .pipe(gulp.dest(paths.public.css)) // output: frontend.css
    .pipe(cssmin({keepSpecialComments:0}))
    .pipe(rename({suffix: '.min'}))
    .pipe(gulp.dest(paths.public.css)); // output: frontend.min.css

});

// LESS: CSS backend
gulp.task('less:backend', function() {  
  // place code for your default task here
  // destination folder: /laravel/public/assets/css/ 
  return gulp.src(paths.resources.less+'backend.less') // get file
    .pipe(less())
    .pipe(autoprefix({ browsers: ['last 2 versions'] }))
    .pipe(gulp.dest(paths.public.css)) // output: backend.css
    .pipe(cssmin({keepSpecialComments:0}))
    .pipe(rename({suffix: '.min'}))
    .pipe(gulp.dest(paths.public.css)); // output: backend.min.css
});

Remember we already set path for paths.resources.less and paths.public.css.

To run only this single task run gulp less:frontend in the command line.

The javascript

This one is pretty clear, first we're concatenating jquery.js, bootstrap.js and frontend.js in a single frontend.js file that will live in the public directory and than we repeat the same thing for the backend javascript file backend.js.

// --- TASKS
// JS frontend
gulp.task('js:frontend', function(){  
  return gulp.src([
      paths.resources.bower_components+'jquery/dist/jquery.js',
      paths.resources.bower_components+'bootstrap/dist/js/bootstrap.js',
      paths.resources.js+'frontend.js'
    ])
    .pipe(concat('frontend.min.js'))
    .pipe(uglify())
    .pipe(gulp.dest(paths.public.js)); // destination: laravel/public/assets/js/frontend.min.js
});

// JS backend
gulp.task('js:backend', function(){  
  return gulp.src([
      paths.resources.bower_components+'jquery/dist/jquery.js',
      paths.resources.bower_components+'bootstrap/dist/js/bootstrap.js',
      paths.resources.js+'backend.js'
    ])
    .pipe(concat('backend.min.js'))
    .pipe(uglify())
    .pipe(gulp.dest(paths.public.js)); // destination: laravel/public/assets/js/backend.min.js
});

To run only this single task run gulp frontend.js or gulp backend.js in the command line.

The tests

Skip this. gulp-phpunit is not working as expected

Gulp can automatically run your tests in Laravel, but we need to make sure PhpUnit exist. laravel/vendor/bin/phpunit.
Let’s update Laravel if you haven’t already. Head to laravel directory and perform this magic.

composer update

Open laravel/composer.json and check if "phpunit/phpunit": "~4.0" are present inside "require": {}.
If not, add manually and run
composer update

Let’s get back to gulpfile.js and check this task definition:

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

    //both notify and notify.onError will take optional notifier: growlNotifier for windows notifications
    //if options.notify is true be sure to handle the error here or suffer the consequenses!
    .on('error', notify.onError({
      title: 'PHPUnit Failed',
      message: 'One or more tests failed, see the cli for details.'
    }))

		//will fire only if no error is caught
    .pipe(notify({
      title: 'PHPUnit Passed',
      message: 'All tests passed!'
    }));
});

To run only this single task run gulp phpunit in the command line.

SKIP THIS!!! For some reason PHP Unit doesn't work.

Until today gulp-phpunit is still shit!

Watching the filesystem for changes

Gulp's superpower is running tasks without having to do many things. It watches your filesystem for changes and it only needs your instructions to know what to do and when to do it.

We already defined 5 tasks:
less:frontend, less:backend, js:frontend, js:backend and phpunit. You could run every one of them separately, if you want, but to fully harness the power of Gulp and automate pure project let's put the bits and pieces together and define the big bad watch task that will watch certain files and run determinate tasks.

// --- WATCH
// Rerun the task when a file changes
gulp.task('watch', function() {  
  gulp.watch(
      [paths.resources.less+'*.less', // files contain .less
       paths.resources.less+'**/*.less'], // sub directories with files contain .less
      ['less:frontend',
       'less:backend']); // run parallel gulp tasks on change
  gulp.watch(
      [paths.resources.js+'*.js', // files contain .js
       paths.resources.js+'**/*.js'], // sub directories with files contain .js
      ['js:frontend',
       'js:backend']); // run parallel gulp tasks on change
});

So, you're probably already guessing: every time one of the defined frontend javascript files is saved, Gulp will run the tasks less:frontend and js:frontend. Same thing with the tasks less:backend and js:backend and their appropriate files.

Finalizing (on this stage)

Create combined gulp tasks

// --- COMBINED TASKS
gulp.task('less', ['less:frontend', 'less:backend']);
gulp.task('scss', ['scss:frontend', 'scss:backend']);
gulp.task('js',   ['js:frontend',   'js:backend']);

When you run: gulp less this will automatically run the tasks less:frontend and less:backend.

And the default gulp action:

// --- DEFAULT
// When you run only with: `gulp`
gulp.task('default', ['watch', 'less', 'js']); 

Finally, the complete gulpfile.js

// gulpfile.js

// --- INIT
var gulp = require('gulp'),  
    less = require('gulp-less'), // compiles less to CSS
    scss = require('gulp-sass'), // compiles sass to CSS
    autoprefix  = require('gulp-autoprefixer'), // CSS browser compatibility
    cssmin = require('gulp-minify-css'), // minifies CSS
    concat = require('gulp-concat'),
    uglify = require('gulp-uglify'), // minifies JS
    rename = require('gulp-rename'),
// optional
    livereload = require('gulp-livereload'),
    notifier = require('node-notifier');

// Paths variables
var paths = {  
    'resources': {
        'less': './laravel/resources/assets/less/',
        'scss': './laravel/resources/assets/scss/',
        'js': './laravel/resources/assets/js/',
        'bower_components': './laravel/resources/assets/bower_components/',  
        'vendor': './laravel/resources/assets/vendor/' // front-end(css/js) things that has not yet Bower support
    },
    'public': {
        'css': './laravel/public/assets/css/',
        'js': './laravel/public/assets/js/'
    }

};

// --- TASKS
// LESS: CSS frontend
gulp.task('less:frontend', function() {  
  // place code for your default task here
  // destination folder: /laravel/public/assets/css/ 
  return gulp.src(paths.resources.less+'frontend.less') // get file
    .pipe(less())
    .pipe(autoprefix({ browsers: ['last 2 versions'] }))
    .pipe(gulp.dest(paths.public.css)) // output: frontend.css
    .pipe(cssmin({keepSpecialComments:0}))
    .pipe(rename({suffix: '.min'}))
    .pipe(gulp.dest(paths.public.css)); // output: frontend.min.css

});

// LESS: CSS backend
gulp.task('less:backend', function() {  
  // place code for your default task here
  // destination folder: /laravel/public/assets/css/ 
  return gulp.src(paths.resources.less+'backend.less') // get file
    .pipe(less())
    .pipe(autoprefix({ browsers: ['last 2 versions'] }))
    .pipe(gulp.dest(paths.public.css)) // output: backend.css
    .pipe(cssmin({keepSpecialComments:0}))
    .pipe(rename({suffix: '.min'}))
    .pipe(gulp.dest(paths.public.css)); // output: backend.min.css
});

// SCSS: CSS frontend
gulp.task('scss:frontend', function() {  
  // place code for your default task here
  // destination folder: /laravel/public/assets/css/ 
  return gulp.src(paths.resources.scss+'frontend.scss') // get file
    .pipe(scss())
    .pipe(autoprefix({ browsers: ['last 2 versions'] }))
    .pipe(gulp.dest(paths.public.css)) // output: frontend.css
    .pipe(cssmin({keepSpecialComments:0}))
    .pipe(rename({suffix: '.min'}))
    .pipe(gulp.dest(paths.public.css)); // output: frontend.min.css

});

// SCSS: CSS backend
gulp.task('scss:backend', function() {  
  // place code for your default task here
  // destination folder: /laravel/public/assets/css/ 
  return gulp.src(paths.resources.scss+'backend.scss') // get file
    .pipe(scss())
    .pipe(autoprefix({ browsers: ['last 2 versions'] }))
    .pipe(gulp.dest(paths.public.css)) // output: backend.css
    .pipe(cssmin({keepSpecialComments:0}))
    .pipe(rename({suffix: '.min'}))
    .pipe(gulp.dest(paths.public.css)); // output: backend.min.css
});

// JS frontend
gulp.task('js:frontend', function(){  
  return gulp.src([
      paths.resources.bower_components+'jquery/dist/jquery.js',
      paths.resources.bower_components+'bootstrap/dist/js/bootstrap.js',
      paths.resources.js+'frontend.js'
    ])
    .pipe(concat('frontend.min.js'))
    .pipe(uglify())
    .pipe(gulp.dest(paths.public.js)); // destination: laravel/public/assets/js/frontend.min.js
});

// JS backend
gulp.task('js:backend', function(){  
  return gulp.src([
      paths.resources.bower_components+'jquery/dist/jquery.js',
      paths.resources.bower_components+'bootstrap/dist/js/bootstrap.js',
      paths.resources.js+'backend.js'
    ])
    .pipe(concat('backend.min.js'))
    .pipe(uglify())
    .pipe(gulp.dest(paths.public.js)); // destination: laravel/public/assets/js/backend.min.js
});

// --- WATCH
// Rerun the task when a file changes
gulp.task('watch', function() {  
  gulp.watch(
      [paths.resources.less+'*.less', // files contain .less
       paths.resources.less+'**/*.less'], // sub directories with files contain .less
      ['less:frontend',
       'less:backend']); // run parallel gulp tasks on change
  gulp.watch(
      [paths.resources.js+'*.js', // files contain .js
       paths.resources.js+'**/*.js'], // sub directories with files contain .js
      ['js:frontend',
       'js:backend']); // run parallel gulp tasks on change
});

// --- COMBINED TASKS
gulp.task('less', ['less:frontend', 'less:backend']);
gulp.task('scss', ['scss:frontend', 'scss:backend']);
gulp.task('js',   ['js:frontend',   'js:backend']);


// --- DEFAULT
// When you run only with: `gulp`
//gulp.task('default', ['watch', 'scss', 'js']);
gulp.task('default', ['watch', 'less', 'js']);

Use Livereload with Gulp

We can use livereload. "gulp-livereload" will automatically refresh your browser when one of the tasks is done.

install the Live reload extension and activate it for the tab your app is running in.

// gulpfile.js
/*
…
…
*/
// --- INIT
// optional
var livereload = require('gulp-livereload'),
    notifier = require('node-notifier');

// --- RELOAD
gulp.task('reload:browser', function(){
    var options = {
        base: "laravel/public"
    };
    livereload.listen(options);

    gulp.watch([
            'laravel/public/*.html', 
            'laravel/public/assets/css/*.css', 
            'laravel/public/assets/js/*.js'
    ]).on('change', function(event){
        livereload.changed(event);
        notifier.notify({ message: 'Browser refreshed' });
    });
});

// --- COMBINED TASKS
gulp.task('reload', ['reload:browser']);

// --- DEFAULT
// When you run only with: `gulp`
//gulp.task('default', ['watch', 'scss', 'js', 'reload']); 
gulp.task('default', ['watch', 'less', 'js', 'reload']); 

Use gulp reload to watch public folders for file changes and refresh the browser

Create a VueJS page

This guide is work in progress

Beer me!

Thank you!