Skip to content

Instantly share code, notes, and snippets.

@hotmeteor
Forked from niallobrien/README.md
Last active May 25, 2017 16:29
Show Gist options
  • Save hotmeteor/bff4d02ae03480747d1f to your computer and use it in GitHub Desktop.
Save hotmeteor/bff4d02ae03480747d1f to your computer and use it in GitHub Desktop.
Laravel + Angular + Gulp

Laravel & Angular

Overview

This setup involves creating a Laravel API and an Angular client-app with Gulp covering the asset pipeline.

Our Laravel API server will serve one view only and that is to simply load the Angular app.

First, create a new directory for your project. We're going to place the server and client directories in here. You'll need to install Laravel, Yeoman, generator-gulp-angular and any other dependencies.

Server

mkdir exampleApp && $_
laravel new server

Open exampleApp/server/app/routes.php and change return View::make('hello'); to return View::make('index');

Client

For the client, run Yeoman to setup the app. We'll replace the build task to suit Laravel's setup.

mkdir client && $_
yo gulp-angular client

Before running any Gulp tasks, let's replace gulp-ruby-sass with gulp-sass. Gulp-sass is faster. We'll also need gulp-rename and gulp-notify.

npm install gulp-sass gulp-rename gulp-notify --save-dev

After you've run the generator and selected your preferred modules etc., replace exampleApp/client/gulp/build.js with the file provided below. The gulp build task will output all assets into exampleApp/server/public/ and output the html file as exampleApp/server/app/views/index.blade.php all setup to load your Angular app.

Gulp Tasks

  • gulp or gulp build to build an optimized version of your application in /server/public. The index file is placed in /server/app/views/ as index.blade.html
  • gulp serve to launch a browser sync server on your source files
  • gulp serve:dist to launch a server on your optimized application
  • gulp wiredep to fill bower dependencies in your .html file(s)
  • gulp test to launch your unit tests with Karma
  • gulp protractor to launch your e2e tests with Protractor
  • gulp protractor:dist to launch your e2e tests with Protractor on the dist files
{
"name": "public-src",
"private": true,
"dependencies": {
"bootstrap-sass-official": "~3.2.0+2",
"modernizr": "~2.6.3",
"jquery": "~1.11.0",
"ionicons": "~1.5.2",
"jquery-ui": "~1.11.1",
"angular": "~1.2.26",
"angular-bootstrap": "~0.11.2",
"angular-ui-sortable": "~0.12.11",
"angular-sanitize": "~1.2.26",
"angular-route": "~1.2.26",
"underscore": "~1.7.0"
},
"devDependencies": {}
}
'use strict';
// generated on 2014-09-26 using generator-gulp-webapp 0.1.0
var gulp = require('gulp');
var browserSync = require('browser-sync');
var reload = browserSync.reload;
var mainBowerFiles = require('main-bower-files');
// load plugins
var $ = require('gulp-load-plugins')({
pattern: ['gulp-*', 'uglify-save-license']
});
gulp.task('styles', function () {
return gulp.src('public-src/scss/main.scss')
.pipe($.plumber())
.pipe($.sass({
// style: 'expanded',
// precision: 10,
// onError: browserSync.notify
errLogToConsole: true,
onError: browserSync.notify
}))
.pipe($.autoprefixer(['last 5 versions', '> 1%', 'ie 8', 'ie 7'], { cascade: true }))
.pipe(gulp.dest('.tmp/styles'))
.pipe($.size())
.pipe(reload({ stream:true }));
// .pipe(gulp.dest('public/styles'));
});
gulp.task('scripts', function () {
return gulp.src('public-src/scripts/**/*.js')
.pipe($.jshint())
.pipe($.jshint.reporter(require('jshint-stylish')))
.pipe($.size());
});
gulp.task('views', function () {
return gulp.src('public-src/views/**/*.html')
.pipe($.minifyHtml({
empty: true,
spare: true,
quotes: true
}))
.pipe($.ngHtml2js({
moduleName: 'client',
prefix: 'views/'
}))
.pipe(gulp.dest('.tmp/views'))
.pipe($.size());
});
gulp.task('html', ['styles', 'scripts', 'views'], function () {
var jsFilter = $.filter('**/*.js');
var cssFilter = $.filter('**/*.css');
return gulp.src('public-src/*.html')
.pipe($.inject(gulp.src('.tmp/views/**/*.js'), {
read: false,
starttag: '<!-- inject:views -->',
addRootSlash: false,
addPrefix: '../'
}))
// .pipe($.useref.assets({searchPath: '{public-src}'}))
.pipe($.useref.assets())
.pipe($.rev())
.pipe(jsFilter)
.pipe($.ngAnnotate())
.pipe($.uglify({preserveComments: $.uglifySaveLicense}))
.pipe(jsFilter.restore())
.pipe(cssFilter)
// .pipe($.replace('bower_components/bootstrap-sass-official/vendor/assets/fonts/bootstrap','fonts'))
.pipe($.csso())
.pipe(cssFilter.restore())
.pipe($.useref.restore())
.pipe($.useref())
.pipe(gulp.dest('public'))
.pipe($.size());
});
gulp.task('images', function () {
return gulp.src('public-src/images/**/*')
.pipe($.cache($.imagemin({
optimizationLevel: 3,
progressive: true,
interlaced: true
})))
.pipe(gulp.dest('public/images'))
.pipe($.size());
});
gulp.task('fonts', function () {
return gulp.src(mainBowerFiles())
.pipe($.filter('**/*.{eot,svg,ttf,woff}'))
.pipe($.flatten())
.pipe(gulp.dest('public/fonts'))
.pipe($.size());
});
gulp.task('extras', function () {
return gulp.src([
'public-src/*.*',
'!public-src/*.html'
], { dot: true })
.pipe(gulp.dest('public'));
});
gulp.task('default', ['clean'], function () {
gulp.start('build');
});
gulp.task('serve', function() {
browserSync({
server: {
baseDir: 'public-src'
}
});
});
// inject bower components
gulp.task('wiredep', function () {
var wiredep = require('wiredep').stream;
gulp.src('public-src/scss/*.scss')
.pipe(wiredep({
directory: 'public-src/bower_components'
}))
.pipe(gulp.dest('public-src/styles'));
gulp.src('public-src/*.html')
.pipe(wiredep({
directory: 'public-src/bower_components',
exclude: ['bootstrap-sass-official']
}))
.pipe(gulp.dest('app'));
});
gulp.task('watch', ['styles', 'serve'], function () {
// watch for changes
gulp.watch([
'public-src/*.html',
'public-src/styles/**/*.css',
'public-src/scripts/**/*.js',
'public-src/images/**/*'
], { }, reload);
// gulp.watch([
// 'public-src/*.html',
// '.tmp/styles/**/*.css',
// 'public-src/scripts/**/*.js',
// 'public-src/images/**/*'
// ]).on('change', function (file) {
// server.changed(file.path);
// });
gulp.watch('public-src/scss/**/*.scss', ['styles']);
gulp.watch('public-src/scripts/**/*.js', ['scripts']);
gulp.watch('public-src/images/**/*', ['images']);
gulp.watch('bower.json', ['wiredep']);
});
gulp.task('copy-html', function () {
return gulp.src('public/index.html')
.pipe($.rename('index.blade.php'))
.pipe(gulp.dest('../server/app/views/'));
});
//gulp.task('copy-styles', function () {
// return gulp.src('public/styles/**/*.css')
// .pipe(gulp.dest('../server/public/styles/'));
//});
//
//gulp.task('copy-scripts', function () {
// return gulp.src('public/scripts/**/*.js')
// .pipe(gulp.dest('../server/public/scripts/'));
//});
//
//gulp.task('copy-partials', function () {
// return gulp.src('public/views/**/*.js')
// .pipe(gulp.dest('../server/public/partials/'));
//});
//
//gulp.task('copy-images', function () {
// return gulp.src('public/images/**/*')
// .pipe(gulp.dest('../server/public/images/'));
//});
//
//gulp.task('copy-fonts', function () {
// return gulp.src('public/fonts/**/*.{eot,svg,ttf,woff}')
// .pipe(gulp.dest('../server/public/fonts/'));
//});
gulp.task('copy', [
'copy-html'
// 'copy-styles',
// 'copy-scripts',
// 'copy-partials',
// 'copy-images',
// 'copy-fonts'
]);
gulp.task('clean', function () {
return gulp.src(['public'], { read: false }).pipe($.clean());
});
gulp.task('build', ['html', 'views', 'images', 'fonts', 'extras', 'copy']);
{
"name": "public-src",
"version": "0.0.0",
"dependencies": {},
"devDependencies": {
"browser-sync": "^1.5.1",
"connect": "^2.14.4",
"gulp": "^3.6.0",
"gulp-autoprefixer": "^0.0.7",
"gulp-bower-files": "^0.2.1",
"gulp-cache": "^0.1.1",
"gulp-clean": "^0.2.4",
"gulp-csso": "^0.2.6",
"gulp-filter": "^0.4.1",
"gulp-flatten": "^0.0.2",
"gulp-imagemin": "^0.5.0",
"gulp-inject": "^1.0.2",
"gulp-jshint": "^1.5.3",
"gulp-load-plugins": "^0.5.0",
"gulp-minify-html": "^0.1.5",
"gulp-ng-annotate": "^0.3.3",
"gulp-ng-html2js": "^0.1.8",
"gulp-notify": "^1.8.0",
"gulp-plumber": "^0.6.5",
"gulp-rename": "^1.2.0",
"gulp-rev": "^1.1.0",
"gulp-sass": "^1.0.0",
"gulp-size": "^0.3.0",
"gulp-uglify": "^0.2.1",
"gulp-useref": "^0.4.2",
"jshint-stylish": "^0.2.0",
"main-bower-files": "^2.0.0",
"opn": "^0.1.1",
"wiredep": "^1.4.3"
},
"engines": {
"node": ">=0.10.0"
}
}
@pabloweinx
Copy link

Really awesome. I was looking for this around the whole internet. Thanks!

@loljoho
Copy link

loljoho commented May 25, 2017

Do you happen to have an updated version with Webpack? I was hoping to do just this, except perhaps with the new FountainJS Angular 1 generator

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment