Pro Yearly is on sale from $80 to $50! »

Deal with Laravel assets by Bower & Gulp

Deal with Laravel assets by Bower & Gulp

PHP 也有 Day #11

F830ec52d5bf72ee64fd1a43a6a82a49?s=128

大澤木小鐵

October 16, 2014
Tweet

Transcript

  1. DEAL WITH LARAVEL ASSETS BY BOWER & GULP Jace Ju

    @ KKBOX
  2. What problems in Laravel 4 assets?

  3. No Built-in assets manager

  4. No Dependency management

  5. Twitter Bootstrap -> jQuery Backbone.js -> underscore.js

  6. No Assets pre-compile & minify

  7. No Changes watching & Live reload

  8. No Packing & Revision

  9. Where is better solution?

  10. Bower + Gulp !!

  11. Bower A package manager for the web http://bower.io/

  12. Gulp The streaming build system http://gulpjs.com/

  13. Quick Demo http://y2u.be/iTkM1LJcLsU

  14. None
  15. How to do this?

  16. Install IO.JS (by Platform)

  17. Install Bower & Gulp $ npm install -g bower gulp

    /usr/local/bin/gulp -> /usr/local/lib/node_modules/gulp/bin/gulp.js /usr/local/bin/bower -> /usr/local/lib/node_modules/bower/bin/bower ...
  18. Create Laravel Project (4.2) $ laravel new project-name Crafting application...

    Application ready! Build something amazing.
  19. Create custom assets

  20. Create assets folders $ cd project-name $ mkdir -p assets/{scripts,styles,images,fonts}

    project-name ├── ... (laravel folders) └── assets ├── scripts ├── styles ├── images └── fonts
  21. Create custom assets $ vi assets/styles/main.scss $ vi assets/scripts/index.js

  22. Add bower support

  23. Create bower.json $ bower init ? name: project-name ? version:

    0.0.0 ? description: ? main file: ? what types of modules does this package expose?: ? keywords: ... ? Looks good?: Yes
  24. bower.json $ cat bower.json { name: 'project-name', version: '0.0.0', authors:

    [ 'Author <author@example.com>' ], license: 'MIT', private: true, ignore: [ ... ] }
  25. Create .bowerrc $ echo "/public/bower_components" >> .gitignore $ vi .bowerrc

    { "directory": "public/bower_components" }
  26. Install package $ bower install --save bootstrap bower cached git://github.com/twbs/bootstrap.git#3.3.1

    bower validate 3.3.1 against git://github.com/twbs/bootstrap.git#* bower cached git://github.com/jquery/jquery.git#2.1.3 ... bootstrap#3.3.1 bower_components/bootstrap └── jquery#2.1.3 jquery#2.1.3 bower_components/jquery
  27. Inject assets

  28. Create blade template $ mv app/views app/templates $ echo "/app/views"

    >> .gitignore $ vi app/templates/index.blade.php
  29. Styles <!-- build:css css/vendor.css --> <!-- bower:css --> <!-- endbower

    --> <!-- endbuid --> <!-- build:css css/main.css --> <link rel="stylesheet" href="styles/main.css"> <!-- endbuild --> </head>
  30. Scripts <!-- build:js js/vendor.js --> <!-- bower:js --> <!-- endbower

    --> <!-- endbuid --> <!-- build:js js/index.js --> <script src="scripts/other.js"></script> <script src="scripts/index.js"></script> <!-- endbuid --> </body>
  31. Rewrite route $ vi app/routes.php Route::get('/', function() { // render

    app/views/index.blade.php return View::make('index'); });
  32. Node modules for tasks

  33. Create package.json $ vi package.json { "name": "project-name", "private": true,

    "devDependencies": { }, "engines": { "node": ">=0.10.0" } }
  34. Install node modules $ echo "/node_modules" >> .gitignore $ npm

    install --save-dev <module-name>
  35. Task tools gulp (3.8.10) The streaming build system gulp-load-plugins (0.8.0)

    Automatically load any gulp plugins in your package.json run-sequence (1.0.2) Run a series of dependent gulp tasks in order gulp-if (1.2.5) Conditionally run a task merge-stream (0.1.6) Create a stream that emits events from multiple other streams
  36. File tools gulp-flatten (0.0.4) remove or replace relative path for

    files gulp-replace (0.5.0) A string replace plugin for gulp del (1.1.1) Delete files/folders using globs
  37. Style tools gulp-ruby-sass (0.7.1) Compile Sass to CSS with Ruby

    Sass gulp-autoprefixer (1.0.1) Prefix CSS gulp-csso (0.2.9) Minify CSS with CSSO.
  38. Script tools gulp-jshint (1.9.0) JSHint plugin for gulp jshint-stylish (1.0.0)

    Stylish reporter for JSHint gulp-uglify (1.0.2) Minify files with UglifyJS. uglify-save-license (0.4.1) License detector for UglifyJS
  39. Image tools gulp-cache (0.1.11) A cache proxy task for Gulp

    gulp-imagemin (2.0.0) Minify PNG, JPEG, GIF and SVG images
  40. Server tools gulp-livereload (3.0.2) Gulp plugin for livereload.

  41. Assets tools gulp-useref (1.0.2) Parse build blocks in HTML files

    to replace references to non-optimized scripts or stylesheets. gulp-rev (2.0.1) Static asset revisioning by appending content hash to filenames gulp-rev-replace (0.3.1) Rewrite occurences of filenames which have been renamed by gulp-rev wiredep (2.2.2) Wire Bower dependencies to your source code.
  42. Add gulp support

  43. Create gulpfile.js $ vi gulpfile.js 'use strict'; // Load gulp

    and plug-ins var gulp = require('gulp'); var del = require('del'); var path = require('path'); var runSequence = require('run-sequence'); var $ = require('gulp-load-plugins')();
  44. Common tasks for assets

  45. Inject bower components gulp.task('wiredep', function() { var wiredep = require('wiredep').stream;

    return gulp.src('app/templates/**/*.blade.php') .pipe(wiredep({ ignorePath: '../../public/' })) .pipe(gulp.dest('app/views')); });
  46. Before <!-- build:js js/vendor.js --> <!-- bower:js --> <!-- endbower

    --> <!-- endbuid --> After <!-- build:js js/vendor.js --> <!-- bower:js --> <script src="bower_components/.../jquery.js"></script> <script src="bower_components/.../bootstrap.js"></script> <!-- endbower --> <!-- endbuid -->
  47. Pre-compile Sass files assets/styles/*.scss ! public/styles/*.css $ echo "/.sass-cache" >>

    .gitignore gulp.task('styles', function() { return gulp.src('assets/styles/*.scss') .pipe($.rubySass({ ... })) .pipe($.autoprefixer({ ... })) .pipe(gulp.dest('public/styles')); });
  48. Check syntax and copy files assets/scripts/*.js ! public/scripts/*.js gulp.task('scripts', function()

    { return gulp.src('./assets/scripts/*.js') .pipe($.jshint('.jshintrc')) .pipe($.jshint.reporter('jshint-stylish')) .pipe(gulp.dest('public/scripts')); });
  49. .jshintrc $ vi .jshintrc { "node": true, "esnext": true, "bitwise":

    true, ... "trailing": true, "smarttabs": true, "white": true } http://jshint.com/docs/
  50. Optimize images assets/images/**/* ! public/images/ gulp.task('images', function() { return gulp.src('assets/images/**/*')

    .pipe($.cache($.imagemin({ ... }))) .pipe(gulp.dest('public/images')); });
  51. Copy fonts assets/fonts/**/*.* ! public/fonts/ // Fonts gulp.task('fonts', function ()

    { return gulp.src([ 'assets/fonts/*.{otf,eot,svg,ttf,woff}', 'public/bower_components/**/fonts/**/*.{otf,eot,svg,ttf,woff}' ]) .pipe($.flatten()) .pipe(gulp.dest('public/fonts')); });
  52. Tasks for development

  53. Clean temporary files // Clean gulp.task('clean:develop', function(cb) { del([ 'app/views',

    'public/styles', 'public/scripts', '.sass-cache'], cb); });
  54. Prepare for development gulp.task('prepare', function (cb) { runSequence( 'clean:develop', ['wiredep',

    'styles', 'scripts', 'images', 'fonts'], cb); });
  55. Start php built-in web server gulp.task('serve', function () { var

    spawn = require('child_process').spawn, child = spawn('php', [ 'artisan', 'serve' ], { cwd: process.cwd() }), log = function (data) { console.log(data.toString()) }, kill = function () { child.kill(); } child.stdout.on('data', log); child.stderr.on('data', log); process.on('exit', kill); process.on('uncaughtException', kill); });
  56. Livereload when destination be changed gulp.task('livereload', function () { var

    server = $.livereload; server.listen(); gulp.watch([ 'app/views/**/*', 'public/**/*', '!public/bower_components/**/*', ]).on('change', server.changed); });
  57. Watching changes of source gulp.task('watch', ['prepare'], function() { gulp.start('serve'); gulp.start('livereload');

    gulp.watch('app/templates/**/*.php', ['wiredep']); gulp.watch('assets/styles/**/*.scss', ['styles']); gulp.watch('assets/scripts/**/*.js', ['scripts']); gulp.watch('assets/images/**/*', ['images']); });
  58. Build tasks

  59. Minify & Packing & Revision gulp.task('build', ['wiredep', 'styles', 'scripts', 'images',

    'fonts'], function() { var assets = $.useref.assets({ searchPath: 'public' }); return gulp.src('app/views/**/*.blade.php') .pipe(assets) .pipe($.if('*.js', $.uglify())) .pipe($.if('*.css', $.csso())) .pipe($.rev()) .pipe(gulp.dest('public')) .pipe(assets.restore()) .pipe($.useref()) .pipe($.revReplace({ replaceInExtensions: ['.php'] })) .pipe(gulp.dest('app/views')); });
  60. Packing Before <!-- build:js js/vendor.js --> <!-- bower:js --> <script

    src="bower_components/.../jquery.js"></script> <script src="bower_components/.../bootstrap.js"></script> <!-- endbower --> <!-- endbuid --> After <script src="js/vendor.js"></script>
  61. Revision Before <script src="js/vendor.js"></script> After <script src="js/vendor-b09c8c22.js"></script>

  62. Default build gulp.task('clean', ['clean:develop', 'clean:cache'], function(cb) { del(['public/css', 'public/js', 'public/fonts',

    'public/images'], cb); }); gulp.task('clean:temporary', function (cb) { del([ 'app/views/js', 'app/views/css', 'public/scripts', 'public/styles', '.sass-cache' ], cb); }); gulp.task('default', function(cb) { runSequence('clean', 'build', 'clean:temporary', cb); });
  63. Ignore packages folder and compiled files $ vi .gitignore ...

    /app/views /public/bower_components /node_modules /public/styles /public/scripts /public/css /public/js /public/fonts /public/images /.sass-cache /.bundle Gemfile.lock
  64. Laravel 4 Skeleton with Gulp # Save your time composer

    create-project jaceju/laragulp project-name -s dev
  65. Laravel Elixir Beautiful Gulp tasks for your Laravel applications. https://github.com/laravel/elixir

  66. Laracast http://goo.gl/gdNrcc

  67. gulpfile.js elixir(function(mix) { mix.less('*.less') .stylesIn("public/css") .version('css/all.css'); });

  68. In blade template <link rel="stylesheet" href="{{ elixir("css/all.css") }}"> from public/build/rev-manifest.json

    { "css/all.css": "css/all-602a38ff.css" }
  69. Summary

  70. • Automate all what machine can handle. • Separate develop

    flow and deploy flow. • DDIY, use third-party tools wisely and well. • This should be first step of your workflow.
  71. No best practice, only better solution.

  72. Q & A