Upgrade to Pro — share decks privately, control downloads, hide ads and more …

devObjective Automate Your Site's Front End Per...

devObjective Automate Your Site's Front End Performance

Automating your site's front-end performance metric gathering using Grunt, grunt-based tools and Webpagetest. No devops experience needed.

Avatar for Kitt Hodsden

Kitt Hodsden

May 14, 2015
Tweet

More Decks by Kitt Hodsden

Other Decks in Technology

Transcript

  1. Kitt Hodsden • @kitt • http://ki.tt/do2015 10 Determine key metrics

    Establish a baseline Make a change Measure effects
  2. Kitt Hodsden • @kitt • http://ki.tt/do2015 11 Determine key metrics

    Establish a baseline Make a change Measure effects
  3. Kitt Hodsden • @kitt • http://ki.tt/do2015 13 40% will abandon

    a website that takes more than 3 seconds to load.
  4. Kitt Hodsden • @kitt • http://ki.tt/do2015 49 { "engines": {

    "node": ">= 0.12.0" }, "devDependencies": { "grunt": "~0.4.2", "grunt-contrib-jshint": "~0.7.2", "grunt-contrib-watch": "~0.5.3", } } This is what a package.json file looks like
  5. Kitt Hodsden • @kitt • http://ki.tt/do2015 50 { "engines": {

    "node": ">= 0.12.0" }, "devDependencies": { "grunt": "~0.4.2", "grunt-contrib-jshint": "~0.7.2", "grunt-contrib-watch": "~0.5.3", } } This is what a package.json file looks like
  6. Kitt Hodsden • @kitt • http://ki.tt/do2015 51 $ npm install

    With a package.json file, you can install the needed packages easily.
  7. Kitt Hodsden • @kitt • http://ki.tt/do2015 52 $ npm install

    No -g here! With a package.json file, you can install the needed packages easily.
  8. Kitt Hodsden • @kitt • http://ki.tt/do2015 53 $ ls Gemfile

    README.txt fonts node_modules tpl Gemfile.lock config.rb img package.json widgets Gruntfile.js css js scss
  9. Kitt Hodsden • @kitt • http://ki.tt/do2015 Check dependencies into the

    repo? http://addyosmani.com/blog/checking-in-front-end-dependencies/ http://redotheweb.com/2013/09/12/should-you-commit-dependencies.html 54 Total sidebar on checking dependencies into the repo or not
  10. Kitt Hodsden • @kitt • http://ki.tt/do2015 55 module.exports = function(grunt)

    { // Project configuration. grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), uglify: { options: { banner: '/*! <%= pkg.name %> <%="yyyy-mm-dd") %> */\n' }, build: { src: 'src/<%= pkg.name %>.js', dest: 'build/<%= pkg.name %>.min.js' } } }); // Load the plugin that provides the "uglify" task. grunt.loadNpmTasks('grunt-contrib-uglify'); // Default task(s). grunt.registerTask('default', ['uglify']); };
  11. Kitt Hodsden • @kitt • http://ki.tt/do2015 56 module.exports = function(grunt)

    { // Project configuration. grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), uglify: { options: { banner: '/*! <%= pkg.name %> <%="yyyy-mm-dd") %> */\n' }, build: { src: 'src/<%= pkg.name %>.js', dest: 'build/<%= pkg.name %>.min.js' } } }); // Load the plugin that provides the "uglify" task. grunt.loadNpmTasks('grunt-contrib-uglify'); // Default task(s). grunt.registerTask('default', ['uglify']); }; A basic Gruntfile.js file
  12. Kitt Hodsden • @kitt • http://ki.tt/do2015 57 module.exports = function(grunt)

    { // Project configuration. grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), uglify: { options: { banner: '/*! <%= pkg.name %> <%="yyyy-mm-dd") %> */\n' }, build: { src: 'src/<%= pkg.name %>.js', dest: 'build/<%= pkg.name %>.min.js' } } }); // Load the plugin that provides the "uglify" task. grunt.loadNpmTasks('grunt-contrib-uglify'); // Default task(s). grunt.registerTask('default', ['uglify']); }; A basic Gruntfile.js file
  13. Kitt Hodsden • @kitt • http://ki.tt/do2015 58 module.exports = function(grunt)

    { // Project configuration. grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), uglify: { options: { banner: '/*! <%= pkg.name %> <%="yyyy-mm-dd") %> */\n' }, build: { src: 'src/<%= pkg.name %>.js', dest: 'build/<%= pkg.name %>.min.js' } } }); // Load the plugin that provides the "uglify" task. grunt.loadNpmTasks('grunt-contrib-uglify'); // Default task(s). grunt.registerTask('default', ['uglify']); }; A basic Gruntfile.js file
  14. Kitt Hodsden • @kitt • http://ki.tt/do2015 60 ... // load

    all the grunt modules instead of one each line require("matchdep").filterDev("grunt-*").forEach(grunt.loadNpmTasks); grunt.registerTask('checkjs', ['jshint']); grunt.registerTask('watchjs', ['jshint', 'watch']); grunt.registerTask('gruntjs', ['jshint:gruntfile', 'watch']);
  15. Kitt Hodsden • @kitt • http://ki.tt/do2015 64 devperf: { options:

    { urls: [ 'http://localhost:8000' ] } } … grunt.registerTask('pe', ['devperf']);
  16. Kitt Hodsden • @kitt • http://ki.tt/do2015 66 … devperf: {

    options: { urls: [ 'http://fromthemiddle.io/' ], numberOfRuns: 5, openResults: true, resultsFolder: './devperf', phantomasOptions: { 'film-strip': true } } } … grunt.registerTask('pe', ['devperf']);
  17. Kitt Hodsden • @kitt • http://ki.tt/do2015 Remove HTML Comments? 76

    https://github.com/gruntjs/grunt-contrib-htmlmin
  18. Kitt Hodsden • @kitt • http://ki.tt/do2015 78 … htmlmin: {

    dist: { options: { removeComments: true, collapseWhitespace: true }, files: { 'dist/index.html': 'src/index.html', 'dist/contact.html': 'src/contact.html' } }, dev: { files: { 'dist/index.html': 'src/index.html', 'dist/contact.html': 'src/contact.html' } } } … grunt.registerTask(‘comments-be-gone‘, ['htmlmin']);
  19. Kitt Hodsden • @kitt • http://ki.tt/do2015 npm install grunt-cssstats --save-dev

    85 https://github.com/cssstats/grunt-cssstats Look at the site’s CSS statistics
  20. Kitt Hodsden • @kitt • http://ki.tt/do2015 92 grunt-cssstats configuration https://github.com/cssstats/grunt-cssstats

    cssstats: { dev: { options: {}, files: { 'stats/css-stats.json': ['css/example.css'] }, } } … grunt.registerTask('stats', ['cssstats']);
  21. Kitt Hodsden • @kitt • http://ki.tt/do2015 93 grunt-cssstats configuration https://github.com/cssstats/grunt-cssstats

    cssstats: { dev: { options: { safe: false }, // Barf on invalid CSS files: { 'stats/cssstats-dev.json': ['app/styles/main.css'] } }, prod: { files: { 'stats/cssstats.json': ['dist/styles.css'] } } }
  22. Kitt Hodsden • @kitt • http://ki.tt/do2015 94 grunt-cssstats configuration https://github.com/cssstats/grunt-cssstats

    cssstats: { dev: { options: { safe: false }, // Barf on invalid CSS files: { 'stats/cssstats-dev.json': ['app/styles/main.css'] } }, prod: { files: { 'stats/cssstats.json': ['dist/styles.css'] } } }
  23. Kitt Hodsden • @kitt • http://ki.tt/do2015 100 grunt.initConfig({ montage: {

    iconaroo: { files: { "images/sprites": [ "images/icons/*.png" ] }, options: { size: 32, outputImage: "sprite-icons.png", outputStylesheet: "sprite-icons.css" } } } }); Sample grunt-montage configuration
  24. Kitt Hodsden • @kitt • http://ki.tt/do2015 102 imagemin: { prod:

    { files: [{ expand: true, cwd: 'imgs-src/', src: ['**/*.{png,jpg,gif}'], dest: 'imgs/' }] } }
  25. Kitt Hodsden • @kitt • http://ki.tt/do2015 104 grunt.initConfig({ svgmin: {

    // Task options: { // Configuration that will be passed directly to SVGO plugins: [ { removeViewBox: false }, { removeUselessStrokeAndFill: false } ] }, dist: { // Target files: [{ // Dictionary of files expand: true, // Enable dynamic expansion. cwd: 'img/src', // Src matches are relative to this path. src: ['**/*.svg'], // Actual pattern(s) to match. dest: 'img/', // Destination path prefix. ext: '.min.svg' // Dest filepaths will have this extension. // ie: optimise img/src/branding/logo.svg and store it in img/branding/logo.min.svg }] } }); grunt.loadNpmTasks('grunt-svgmin'); grunt.registerTask('default', ['svgmin']); Sample grunt-svgmin configuration
  26. Kitt Hodsden • @kitt • http://ki.tt/do2015 npm install grunt-responsive-images --save-dev

    106 Responsive images by resizing https://github.com/andismith/grunt-responsive-images
  27. Kitt Hodsden • @kitt • http://ki.tt/do2015 107 grunt.initConfig({ responsive_images: {

    myTask: { options: { sizes: [{ width: 320, height: 240 },{ name: 'large', width: 640 },{ name: "large", width: 1024, suffix: "_x2", quality: 60 }] }, files: [{ expand: true, src: ['assets/**.{jpg,gif,png}'], cwd: 'test/', dest: 'resize/{%= width %}/' }] } }, }); Sample grunt-responsive-images configuration
  28. Kitt Hodsden • @kitt • http://ki.tt/do2015 npm install grunt-grunticon --save-dev

    108 SVG with PNG fallbacks https://github.com/filamentgroup/grunticon
  29. Kitt Hodsden • @kitt • http://ki.tt/do2015 117 http://www.webpagetest.org/getkey.php Limits of

    public use The API key is provisioned for up to 200 page loads per day … sufficient for most low-volume use cases and for building a proof-of- concept for larger testing
  30. Kitt Hodsden • @kitt • http://ki.tt/do2015 121 perfbudget: { default:

    { options: { url: ‘http://example.io/', key: 'PUT_YOUR_API_KEY_HERE' } } } … grunt.registerTask('budg', ['perfbudget']);
  31. Kitt Hodsden • @kitt • http://ki.tt/do2015 122 perfbudget: { default:

    { options: { url: 'http://fromthemiddle.io/', key: 'thisismykey', wptInstance: 'ec2.us-west-2.amazonaws.com', location: 'us-west-2_wptdriver', pollResults: 10, connectivity: '3G', runs: 1, timeout: 240 } } }
  32. Kitt Hodsden • @kitt • http://ki.tt/do2015 123 perfbudget: { default:

    { options: { url: 'http://fromthemiddle.io/', key: 'thisismykey', wptInstance: 'ec2.us-west-2.amazonaws.com', location: 'us-west-2_wptdriver', pollResults: 10, connectivity: '3G', runs: 1, timeout: 240 } } }
  33. Kitt Hodsden • @kitt • http://ki.tt/do2015 124 perfbudget: { default:

    { options: { url: 'http://fromthemiddle.io/', key: 'thisismykey', wptInstance: 'ec2.us-west-2.amazonaws.com', location: 'us-west-2_wptdriver', pollResults: 10, connectivity: '3G', runs: 1, timeout: 240 } } }
  34. Kitt Hodsden • @kitt • http://ki.tt/do2015 126 perfbudget: { default:

    { options: { url: 'http://fromthemiddle.io/', … connectivity: '3G', timeout: 240, budget: { render: '3000', SpeedIndex: '7500', visualComplete: '6000' } } } }
  35. Kitt Hodsden • @kitt • http://ki.tt/do2015 npm install grunt-wpt --save-dev

    134 https://github.com/sideroad/grunt-wpt https://github.com/sideroad/grunt-wpt-page
  36. Kitt Hodsden • @kitt • http://ki.tt/do2015 135 wpt: { options:

    { url: 'http://fromthemiddle.io/', server: 'ec2.us-west-2.amazonaws.com', dest: 'wpt/' }, ftm: { options: { server: 'http://ec2.us-west-2.amazonaws.com', url: ['http://fromthemiddle.io/'] }, dest: 'wpt/', } } … grunt.registerTask('wptrun', ['wpt']);
  37. Kitt Hodsden • @kitt • http://ki.tt/do2015 npm install grunt-shell --save-dev

    138 Installing the grunt shell package to get to everything else
  38. Kitt Hodsden • @kitt • http://ki.tt/do2015 139 function log(err, stdout,

    stderr, cb) { console.log(stdout); cb(); } grunt.initConfig({ shell: { dirListing: { command: 'ls', options: { callback: log } } } });
  39. Kitt Hodsden • @kitt • http://ki.tt/do2015 144 $ cat tests.json

    [ { "name": "From the Middle", "url": "http://fromthemiddle.io/", "type": "home" }, { "name": "Kitt Hodsden", "url": "https://kitt.hodsden.org/", "type": "away" } ]
  40. Kitt Hodsden • @kitt • http://ki.tt/do2015 Worth looking at: https://github.com/andyshora/grunt-yslow

    https://github.com/jrcryer/grunt-pagespeed https://github.com/addyosmani/psi/ http://www.sitespeed.io/ http://perf-tooling.today/tools 149
  41. Kitt Hodsden • @kitt • http://ki.tt/do2015 182 $ vi ~/.ssh/authorized_keys

    dd # delete the first line [esc] # trigger the vi command sequence :wq # save the file and quit
  42. Kitt Hodsden • @kitt • http://ki.tt/do2015 183 sudo vi /var/www/webpagetest/www/settings/settings.ini

    # update publishTo with ec2 hostname # update ec2 = 0 # update ec2_locations = 0 # add EC2.us-west-2.securityGroup line from sample # add EC2.us-west-2.subnetId line from sample #
  43. Kitt Hodsden • @kitt • http://ki.tt/do2015 184 sudo vi /var/www/webpage/test/www/settings/keys.ini

    [server] secret=addarandomstringhere key=addakeyhere [addakeyhere] description=Web UI ;[email protected] limit=0 [thisisyourapikey] description=API Key ;[email protected] limit=0
  44. Kitt Hodsden • @kitt • http://ki.tt/do2015 185 $ cd /var/www/webpage/test/www/settings/

    $ sudo cp locations.ini.EC2-sample locations.ini # delete extra locations # update key values to your thisisyourkey value
  45. Kitt Hodsden • @kitt • http://ki.tt/do2015 188 EC2 server key

    in settings.ini (more complicated to set up, better automation management)