Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥

Deal with Laravel assets by Bower & Gulp

Deal with Laravel assets by Bower & Gulp

PHP 也有 Day #11

大澤木小鐵

October 16, 2014
Tweet

More Decks by 大澤木小鐵

Other Decks in Programming

Transcript

  1. 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 ...
  2. Create assets folders $ cd project-name $ mkdir -p assets/{scripts,styles,images,fonts}

    project-name ├── ... (laravel folders) └── assets ├── scripts ├── styles ├── images └── fonts
  3. 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
  4. bower.json $ cat bower.json { name: 'project-name', version: '0.0.0', authors:

    [ 'Author <[email protected]>' ], license: 'MIT', private: true, ignore: [ ... ] }
  5. 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
  6. Create blade template $ mv app/views app/templates $ echo "/app/views"

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

    --> <!-- endbuid --> <!-- build:css css/main.css --> <link rel="stylesheet" href="styles/main.css"> <!-- endbuild --> </head>
  8. 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>
  9. Rewrite route $ vi app/routes.php Route::get('/', function() { // render

    app/views/index.blade.php return View::make('index'); });
  10. Create package.json $ vi package.json { "name": "project-name", "private": true,

    "devDependencies": { }, "engines": { "node": ">=0.10.0" } }
  11. 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
  12. 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
  13. 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.
  14. 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
  15. 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
  16. 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.
  17. 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')();
  18. 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')); });
  19. 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 -->
  20. 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')); });
  21. 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')); });
  22. .jshintrc $ vi .jshintrc { "node": true, "esnext": true, "bitwise":

    true, ... "trailing": true, "smarttabs": true, "white": true } http://jshint.com/docs/
  23. 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')); });
  24. Clean temporary files // Clean gulp.task('clean:develop', function(cb) { del([ 'app/views',

    'public/styles', 'public/scripts', '.sass-cache'], cb); });
  25. 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); });
  26. 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); });
  27. 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']); });
  28. 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')); });
  29. 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>
  30. 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); });
  31. 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
  32. Laravel 4 Skeleton with Gulp # Save your time composer

    create-project jaceju/laragulp project-name -s dev
  33. • 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.