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

Automation for Site Performance - Web Directions 2015

Automation for Site Performance - Web Directions 2015

Automating for site performance, presented at Web Directions South 2015 in Sydney, NSW, Australia on October 29th.

Kitt Hodsden

October 29, 2015
Tweet

More Decks by Kitt Hodsden

Other Decks in Technology

Transcript

  1. Kitt Hodsden • @kitt • http://ki.tt/wd15 1 Automation for Site

    Performance Kitt Hodsden / @kitt slides here
  2. Kitt Hodsden • @kitt • http://ki.tt/wd15 2 Me.

  3. Kitt Hodsden • @kitt • http://ki.tt/wd15 3 You.

  4. Kitt Hodsden • @kitt • http://ki.tt/wd15 4

  5. Kitt Hodsden • @kitt • http://ki.tt/wd15 5 Performance is everybody’s

    problem.
  6. Kitt Hodsden • @kitt • http://ki.tt/wd15 6 “What does FAST

    even mean?”
  7. Kitt Hodsden • @kitt • http://ki.tt/wd15 7 Determine key metrics

  8. Kitt Hodsden • @kitt • http://ki.tt/wd15 8 Determine key metrics

    Establish a baseline
  9. Kitt Hodsden • @kitt • http://ki.tt/wd15 9 Determine key metrics

    Establish a baseline Make a change
  10. Kitt Hodsden • @kitt • http://ki.tt/wd15 10 Determine key metrics

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

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

  13. Kitt Hodsden • @kitt • http://ki.tt/wd15 13 40% will abandon

    a website that takes more than 3 seconds to load.
  14. Kitt Hodsden • @kitt • http://ki.tt/wd15 14 https://blog.kissmetrics.com/loading-time/ Not quite

  15. Kitt Hodsden • @kitt • http://ki.tt/wd15 15 https://blog.kissmetrics.com/loading-time/ Not quite

  16. Kitt Hodsden • @kitt • http://ki.tt/wd15 16 Performance Budgets

  17. Kitt Hodsden • @kitt • http://ki.tt/wd15 17 http://timkadlec.com/2013/01/setting-a-performance-budget/ http://timkadlec.com/2014/11/performance-budget-metrics/ http://danielmall.com/articles/how-to-make-a-performance-budget/

  18. Kitt Hodsden • @kitt • http://ki.tt/wd15 18 http://timkadlec.com/2013/01/setting-a-performance-budget/ http://timkadlec.com/2014/11/performance-budget-metrics/ http://danielmall.com/articles/how-to-make-a-performance-budget/

  19. Kitt Hodsden • @kitt • http://ki.tt/wd15 19 http://timkadlec.com/2013/01/setting-a-performance-budget/ http://timkadlec.com/2014/11/performance-budget-metrics/ http://danielmall.com/articles/how-to-make-a-performance-budget/

  20. Kitt Hodsden • @kitt • http://ki.tt/wd15 20

  21. Kitt Hodsden • @kitt • http://ki.tt/wd15 21 Determine key metrics

  22. Kitt Hodsden • @kitt • http://ki.tt/wd15 22 Establish a baseline

  23. Kitt Hodsden • @kitt • http://ki.tt/wd15 23 How fast is

    our site?
  24. Kitt Hodsden • @kitt • http://ki.tt/wd15 24

  25. Kitt Hodsden • @kitt • http://ki.tt/wd15 25 No.

  26. Kitt Hodsden • @kitt • http://ki.tt/wd15 26 The simplest way?

  27. Kitt Hodsden • @kitt • http://ki.tt/wd15 27 Your browser

  28. Kitt Hodsden • @kitt • http://ki.tt/wd15 28 Firefox

  29. Kitt Hodsden • @kitt • http://ki.tt/wd15 29 Safari

  30. Kitt Hodsden • @kitt • http://ki.tt/wd15 30 IE

  31. Kitt Hodsden • @kitt • http://ki.tt/wd15 31 Chrome

  32. Kitt Hodsden • @kitt • http://ki.tt/wd15 32 Chrome

  33. Kitt Hodsden • @kitt • http://ki.tt/wd15 33 https://developer.chrome.com/devtools/docs/network

  34. Kitt Hodsden • @kitt • http://ki.tt/wd15 34

  35. Kitt Hodsden • @kitt • http://ki.tt/wd15 35

  36. Kitt Hodsden • @kitt • http://ki.tt/wd15 http://wpotools.github.io/perfBar/ 36

  37. Kitt Hodsden • @kitt • http://ki.tt/wd15 https://raw.githubusercontent.com/WPOTools/perfBar/master/build/perfbar.js 37

  38. Kitt Hodsden • @kitt • http://ki.tt/wd15 <script src="js/perfbar.js"></script> <script>perfBar.init({});</script> 38

  39. Kitt Hodsden • @kitt • http://ki.tt/wd15 39

  40. Kitt Hodsden • @kitt • http://ki.tt/wd15 40

  41. Kitt Hodsden • @kitt • http://ki.tt/wd15 But… but… 41

  42. Kitt Hodsden • @kitt • http://ki.tt/wd15 My network! 42

  43. Kitt Hodsden • @kitt • http://ki.tt/wd15 My browsers! 43

  44. Kitt Hodsden • @kitt • http://ki.tt/wd15 44

  45. Kitt Hodsden • @kitt • http://ki.tt/wd15 Automation! 45

  46. Kitt Hodsden • @kitt • http://ki.tt/wd15 46

  47. Kitt Hodsden • @kitt • http://ki.tt/wd15 47

  48. Kitt Hodsden • @kitt • http://ki.tt/wd15 npm 48 Node Package

    Manager for installing node packages
  49. Kitt Hodsden • @kitt • http://ki.tt/wd15 49

  50. Kitt Hodsden • @kitt • http://ki.tt/wd15 npm install -g grunt-cli

    50
  51. Kitt Hodsden • @kitt • http://ki.tt/wd15 51 package.json Gruntfile.js The

    two files grunt uses
  52. Kitt Hodsden • @kitt • http://ki.tt/wd15 npm init 52

  53. Kitt Hodsden • @kitt • http://ki.tt/wd15 53 $ npm init

    This utility will walk you through creating a package.json file. It only covers the most common items, and tries to guess sane defaults. See `npm help json` for definitive documentation on these fields and exactly what they do. Use `npm install <pkg> --save` afterwards to install a package and save it as a dependency in the package.json file. Press ^C at any time to quit. name: (dev) performance version: (1.0.0) description: Automating front-end performance metrics and improvements entry point: (index.js) test command: git repository: keywords: author: license: (ISC) About to write to .../e4e/dev/package.json: ...
  54. Kitt Hodsden • @kitt • http://ki.tt/wd15 54 $ npm init

    This utility will walk you through creating a package.json file. It only covers the most common items, and tries to guess sane defaults. See `npm help json` for definitive documentation on these fields and exactly what they do. Use `npm install <pkg> --save` afterwards to install a package and save it as a dependency in the package.json file. Press ^C at any time to quit. name: (dev) performance version: (1.0.0) description: Automating front-end performance metrics and improvements entry point: (index.js) test command: git repository: keywords: author: license: (ISC) About to write to .../e4e/dev/package.json: ...
  55. Kitt Hodsden • @kitt • http://ki.tt/wd15 55 { "name": "performance",

    "version": "1.0.0", "description": "Automating front-end performance”, "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC" } This is what a package.json file looks like
  56. Kitt Hodsden • @kitt • http://ki.tt/wd15 Just download them. https://github.com/search?q=Gruntfile.js

    https://github.com/kitt/grunt-perf-template 56
  57. Kitt Hodsden • @kitt • http://ki.tt/wd15 57 { "engines": {

    "node": ">= 4.1.0" }, "devDependencies": { "grunt": "~0.4.5", "grunt-contrib-jshint": "~0.11.3", "grunt-contrib-watch": "~0.6.1", } } This is what a package.json file looks like
  58. Kitt Hodsden • @kitt • http://ki.tt/wd15 58 { "engines": {

    "node": ">= 4.1.0" }, "devDependencies": { "grunt": "~0.4.5", "grunt-contrib-jshint": "~0.11.3", "grunt-contrib-watch": "~0.6.1", } } This is what a package.json file looks like
  59. Kitt Hodsden • @kitt • http://ki.tt/wd15 59 $ npm install

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

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

    README.txt fonts node_modules tpl Gemfile.lock config.rb img package.json widgets Gruntfile.js css js scss
  62. Kitt Hodsden • @kitt • http://ki.tt/wd15 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 62 Total sidebar on checking dependencies into the repo or not
  63. Kitt Hodsden • @kitt • http://ki.tt/wd15 63 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']); };
  64. Kitt Hodsden • @kitt • http://ki.tt/wd15 64 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
  65. Kitt Hodsden • @kitt • http://ki.tt/wd15 65 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
  66. Kitt Hodsden • @kitt • http://ki.tt/wd15 66 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
  67. Kitt Hodsden • @kitt • http://ki.tt/wd15 67 grunt.loadNpmTasks('grunt-aws-s3'); grunt.loadNpmTasks('grunt-cafe-mocha'); grunt.loadNpmTasks('grunt-contrib-clean');

    grunt.loadNpmTasks('grunt-contrib-concat'); grunt.loadNpmTasks('grunt-contrib-copy');
  68. Kitt Hodsden • @kitt • http://ki.tt/wd15 68 grunt.loadNpmTasks('grunt-aws-s3'); grunt.loadNpmTasks('grunt-cafe-mocha'); grunt.loadNpmTasks('grunt-contrib-clean');

    grunt.loadNpmTasks('grunt-contrib-concat'); grunt.loadNpmTasks('grunt-contrib-copy'); grunt.loadNpmTasks('grunt-contrib-csslint'); grunt.loadNpmTasks('grunt-contrib-cssmin'); grunt.loadNpmTasks('grunt-contrib-jade'); grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-contrib-imagemin');
  69. Kitt Hodsden • @kitt • http://ki.tt/wd15 69 grunt.loadNpmTasks('grunt-aws-s3'); grunt.loadNpmTasks('grunt-cafe-mocha'); grunt.loadNpmTasks('grunt-contrib-clean');

    grunt.loadNpmTasks('grunt-contrib-concat'); grunt.loadNpmTasks('grunt-contrib-copy'); grunt.loadNpmTasks('grunt-contrib-csslint'); grunt.loadNpmTasks('grunt-contrib-cssmin'); grunt.loadNpmTasks('grunt-contrib-jade'); grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-contrib-imagemin'); grunt.loadNpmTasks('grunt-contrib-sass'); grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-env'); grunt.loadNpmTasks('grunt-favicons'); grunt.loadNpmTasks('grunt-html-validation'); grunt.loadNpmTasks('grunt-mkdir');
  70. Kitt Hodsden • @kitt • http://ki.tt/wd15 70 $ npm install

    load-grunt-tasks --save-dev
  71. Kitt Hodsden • @kitt • http://ki.tt/wd15 71 $ npm install

    load-grunt-tasks --save-dev
  72. Kitt Hodsden • @kitt • http://ki.tt/wd15 72 module.exports = function(grunt)

    { // load grunt tasks matching ['grunt-*', '@*/grunt-*'] patterns require('load-grunt-tasks')(grunt); grunt.initConfig({ ...
  73. Kitt Hodsden • @kitt • http://ki.tt/wd15 73 module.exports = function(grunt)

    { // load grunt tasks matching ['grunt-*', '@*/grunt-*'] patterns require('load-grunt-tasks')(grunt); grunt.initConfig({}); grunt.registerTask('default', []); }
  74. Kitt Hodsden • @kitt • http://ki.tt/wd15 74 https://www.flickr.com/photos/dandechiaro/4151566643

  75. Kitt Hodsden • @kitt • http://ki.tt/wd15 npm install grunt-devperf --save-dev

    75
  76. Kitt Hodsden • @kitt • http://ki.tt/wd15 76 https://github.com/macbre/phantomas

  77. Kitt Hodsden • @kitt • http://ki.tt/wd15 77 devperf: { options:

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

  79. Kitt Hodsden • @kitt • http://ki.tt/wd15 79 … devperf: {

    options: { urls: [ 'http://grunt.wtf/' ], numberOfRuns: 5, openResults: true, resultsFolder: './devperf', phantomasOptions: { 'film-strip': true } } } … grunt.registerTask('pe', ['devperf']);
  80. Kitt Hodsden • @kitt • http://ki.tt/wd15 80

  81. Kitt Hodsden • @kitt • http://ki.tt/wd15 81

  82. Kitt Hodsden • @kitt • http://ki.tt/wd15 82

  83. Kitt Hodsden • @kitt • http://ki.tt/wd15 83

  84. Kitt Hodsden • @kitt • http://ki.tt/wd15 84

  85. Kitt Hodsden • @kitt • http://ki.tt/wd15 85

  86. Kitt Hodsden • @kitt • http://ki.tt/wd15 86 https://www.flickr.com/photos/ndrwfgg/8072089187

  87. Kitt Hodsden • @kitt • http://ki.tt/wd15 87 http://www.devobjective.com/

  88. Kitt Hodsden • @kitt • http://ki.tt/wd15 88 http://www.devobjective.com/

  89. Kitt Hodsden • @kitt • http://ki.tt/wd15 Remove HTML Comments 89

    https://github.com/gruntjs/grunt-contrib-htmlmin
  90. Kitt Hodsden • @kitt • http://ki.tt/wd15 npm install grunt-contrib-htmlmin —save-dev

    90 https://github.com/gruntjs/grunt-contrib-htmlmin
  91. Kitt Hodsden • @kitt • http://ki.tt/wd15 91 … 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']);
  92. Kitt Hodsden • @kitt • http://ki.tt/wd15 92 Determine key metrics

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

    Establish a baseline Make a change Measure effects
  94. Kitt Hodsden • @kitt • http://ki.tt/wd15 Concatenate and Minify CSS

    files 94
  95. Kitt Hodsden • @kitt • http://ki.tt/wd15 npm install grunt-contrib-cssmin --save-dev

    95 Minimize CSS files
  96. Kitt Hodsden • @kitt • http://ki.tt/wd15 Remove duplicate CSS? 96

  97. Kitt Hodsden • @kitt • http://ki.tt/wd15 npm install grunt-csscss --save-dev

    97 Report duplicate CSS in files
  98. Kitt Hodsden • @kitt • http://ki.tt/wd15 Remove unused CSS? 98

  99. Kitt Hodsden • @kitt • http://ki.tt/wd15 npm install grunt-uncss --save-dev

    99 Remove unused CSS
  100. Kitt Hodsden • @kitt • http://ki.tt/wd15 npm install grunt-phantomcss —save-dev

    100 Make sure you haven’t removed things you need
  101. Kitt Hodsden • @kitt • http://ki.tt/wd15 npm install grunt-phantomcss —save-dev

    101 Make sure you haven’t removed things you need
  102. Kitt Hodsden • @kitt • http://ki.tt/wd15 npm install @micahgodbolt/grunt-phantomcss --save-dev

    https://github.com/micahgodbolt/grunt-phantomcss https://github.com/Huddle/PhantomCSS 102 Make sure you haven’t removed things you need
  103. Kitt Hodsden • @kitt • http://ki.tt/wd15 npm install @micahgodbolt/grunt-phantomcss --save-dev

    https://github.com/micahgodbolt/grunt-phantomcss https://github.com/Huddle/PhantomCSS 103 We can install from github
  104. Kitt Hodsden • @kitt • http://ki.tt/wd15 104 Make sure you

    haven’t removed things you need
  105. Kitt Hodsden • @kitt • http://ki.tt/wd15 105 grunt-cssstats configuration https://github.com/cssstats/grunt-cssstats

    phantomcss: { desktop: { options: { screenshots: 'test/visual/desktop/', results: 'results/visual/desktop', viewportSize: [1024, 768] }, src: [ 'test/visual/**.js' ] }, mobile: { options: { screenshots: 'test/visual/mobile/', results: 'results/visual/mobile', viewportSize: [320, 480] }, src: [ 'test/visual/**.js' ] } }
  106. Kitt Hodsden • @kitt • http://ki.tt/wd15 106 grunt-cssstats configuration https://github.com/cssstats/grunt-cssstats

    phantomcss: { desktop: { options: { screenshots: 'test/visual/desktop/', results: 'results/visual/desktop', viewportSize: [1024, 768] }, src: [ 'test/visual/**.js' ] }, mobile: { options: { screenshots: 'test/visual/mobile/', results: 'results/visual/mobile', viewportSize: [320, 480] }, src: [ 'test/visual/**.js' ] } }
  107. Kitt Hodsden • @kitt • http://ki.tt/wd15 107 grunt-cssstats configuration https://github.com/cssstats/grunt-cssstats

    casper.thenOpen('http://grunt.wtf/web-directions') .then(function() { phantomcss.screenshot('#region-branding', 'region-branding'); }) .then(function now_check_the_screenshots() { phantomCSS.compareAll(); });
  108. Kitt Hodsden • @kitt • http://ki.tt/wd15 npm install grunt-cssstats --save-dev

    108 https://github.com/cssstats/grunt-cssstats Look at the site’s CSS statistics
  109. Kitt Hodsden • @kitt • http://ki.tt/wd15 109 https://github.com/cssstats/cssstats

  110. Kitt Hodsden • @kitt • http://ki.tt/wd15 110

  111. Kitt Hodsden • @kitt • http://ki.tt/wd15 111

  112. Kitt Hodsden • @kitt • http://ki.tt/wd15 112

  113. Kitt Hodsden • @kitt • http://ki.tt/wd15 113

  114. Kitt Hodsden • @kitt • http://ki.tt/wd15 114

  115. Kitt Hodsden • @kitt • http://ki.tt/wd15 115 grunt-cssstats configuration https://github.com/cssstats/grunt-cssstats

    cssstats: { dev: { options: {}, files: { 'stats/css-stats.json': ['css/example.css'] }, } } … grunt.registerTask('stats', ['cssstats']);
  116. Kitt Hodsden • @kitt • http://ki.tt/wd15 116 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'] } } }
  117. Kitt Hodsden • @kitt • http://ki.tt/wd15 117 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'] } } }
  118. Kitt Hodsden • @kitt • http://ki.tt/wd15 https://github.com/cssstats/cssstats 118

  119. Kitt Hodsden • @kitt • http://ki.tt/wd15 Aggregate and Minify JavaScript?

    119
  120. Kitt Hodsden • @kitt • http://ki.tt/wd15 npm install grunt-contrib-uglify --save-dev

    120 Minimize javascript files
  121. Kitt Hodsden • @kitt • http://ki.tt/wd15 121 Determine key metrics

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

    Establish a baseline Make a change Measure effects
  123. Kitt Hodsden • @kitt • http://ki.tt/wd15 Too many small images?

    123
  124. Kitt Hodsden • @kitt • http://ki.tt/wd15 npm install grunt-montage --save-dev

    124 Making things easier with sprites!
  125. Kitt Hodsden • @kitt • http://ki.tt/wd15 125 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
  126. Kitt Hodsden • @kitt • http://ki.tt/wd15 npm install grunt-contrib-imagemin --save-dev

    126 Make pages load faster by reducing image sizes
  127. Kitt Hodsden • @kitt • http://ki.tt/wd15 127 imagemin: { prod:

    { files: [{ expand: true, cwd: 'imgs-src/', src: ['**/*.{png,jpg,gif}'], dest: 'imgs/' }] } }
  128. Kitt Hodsden • @kitt • http://ki.tt/wd15 npm install grunt-svgmin --save-dev

    128 Reduce SVG sizes, too
  129. Kitt Hodsden • @kitt • http://ki.tt/wd15 129 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
  130. Kitt Hodsden • @kitt • http://ki.tt/wd15 130

  131. Kitt Hodsden • @kitt • http://ki.tt/wd15 npm install grunt-responsive-images --save-dev

    131 Responsive images by resizing https://github.com/andismith/grunt-responsive-images
  132. Kitt Hodsden • @kitt • http://ki.tt/wd15 132 grunt.initConfig({ responsive_images: {

    myTask: { options: { sizes: [{ width: 320, height: 240 },{ name: 'medium', width: 640 },{ name: "large", width: 1024, suffix: "_x2", quality: 60 }] }, files: [{ expand: true, src: ['original/**.{jpg,gif,png}'], cwd: 'images/', custom_dest: 'images/{%= width %}/' }] } }, }); Sample grunt-responsive-images configuration
  133. Kitt Hodsden • @kitt • http://ki.tt/wd15 133 <img src="/images/medium/cat.jpg" alt="cat"

    srcset="/images/small/cat.jpg 320w, /images/large/cat.jpg 1024w"> Using img srcset
  134. Kitt Hodsden • @kitt • http://ki.tt/wd15 134 <img src="/images/medium/cat.jpg" alt="cat"

    srcset="/images/small/cat.jpg 320w, /images/medium/cat.jpg 640w, /images/large/cat.jpg 1024w"> Using img srcset
  135. Kitt Hodsden • @kitt • http://ki.tt/wd15 npm install grunt-grunticon --save-dev

    135 SVG with PNG fallbacks https://github.com/filamentgroup/grunticon
  136. Kitt Hodsden • @kitt • http://ki.tt/wd15 ? 136

  137. Kitt Hodsden • @kitt • http://ki.tt/wd15 webfonts! 137

  138. Kitt Hodsden • @kitt • http://ki.tt/wd15 Him: “Hey, I have

    two megs of webfonts…” Me: “…” Him: “Is this okay?” 138
  139. Kitt Hodsden • @kitt • http://ki.tt/wd15 No. 139

  140. Kitt Hodsden • @kitt • http://ki.tt/wd15 140

  141. Kitt Hodsden • @kitt • http://ki.tt/wd15 npm install grunt-ziti —save-dev

    https://github.com/caiguanhao/grunt-ziti 141 Reduce font file sizes
  142. Kitt Hodsden • @kitt • http://ki.tt/wd15 142 grunt.initConfig({ ziti: {

    subset_only: { options: { font: { chars: '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', }, convert: false }, files: { ‘assets/fonts/my.ttf': [ ‘src/fonts/original.ttf' ] } } } }); grunt.loadNpmTasks('grunt-ziti'); grunt.registerTask('fontsubset', ['ziti']); Sample grunt-ziti configuration
  143. Kitt Hodsden • @kitt • http://ki.tt/wd15 Wait… again… 143

  144. Kitt Hodsden • @kitt • http://ki.tt/wd15 Dependent on my network?

    144
  145. Kitt Hodsden • @kitt • http://ki.tt/wd15 Yep. 145

  146. Kitt Hodsden • @kitt • http://ki.tt/wd15 How about not? 146

  147. Kitt Hodsden • @kitt • http://ki.tt/wd15 147

  148. Kitt Hodsden • @kitt • http://ki.tt/wd15 148 Request an API

    key.
  149. Kitt Hodsden • @kitt • http://ki.tt/wd15 149

  150. Kitt Hodsden • @kitt • http://ki.tt/wd15 150 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
  151. Kitt Hodsden • @kitt • http://ki.tt/wd15 151 Need more?

  152. Kitt Hodsden • @kitt • http://ki.tt/wd15 152 Set up your

    own WebPageTest server.
  153. Kitt Hodsden • @kitt • http://ki.tt/wd15 npm install grunt-perfbudget --save-dev

    153 https://github.com/tkadlec/grunt-perfbudget
  154. Kitt Hodsden • @kitt • http://ki.tt/wd15 154 perfbudget: { default:

    { options: { url: ‘http://example.io/', key: 'PUT_YOUR_API_KEY_HERE' } } } … grunt.registerTask('budg', ['perfbudget']);
  155. Kitt Hodsden • @kitt • http://ki.tt/wd15 155 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 } } }
  156. Kitt Hodsden • @kitt • http://ki.tt/wd15 156 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 } } }
  157. Kitt Hodsden • @kitt • http://ki.tt/wd15 157 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 } } }
  158. Kitt Hodsden • @kitt • http://ki.tt/wd15 158

  159. Kitt Hodsden • @kitt • http://ki.tt/wd15 159 perfbudget: { default:

    { options: { url: 'http://fromthemiddle.io/', … connectivity: '3G', timeout: 240, budget: { render: '3000', SpeedIndex: '7500', visualComplete: '6000' } } } }
  160. Kitt Hodsden • @kitt • http://ki.tt/wd15 160

  161. Kitt Hodsden • @kitt • http://ki.tt/wd15 161

  162. Kitt Hodsden • @kitt • http://ki.tt/wd15 Scripting! 162

  163. Kitt Hodsden • @kitt • http://ki.tt/wd15 Now what? 163 https://sites.google.com/a/webpagetest.org/docs/using-webpagetest/scripting

  164. Kitt Hodsden • @kitt • http://ki.tt/wd15 164 // bring up

    the login screen navigate https://grunt.wtf/user // log in setValue name=user testuser setValue name=password testpassword submitFormname=user-login
  165. Kitt Hodsden • @kitt • http://ki.tt/wd15 Now what? 165

  166. Kitt Hodsden • @kitt • http://ki.tt/wd15 npm install grunt-shell --save-dev

    166 http://example.com/ Installing the grunt shell package to get to everything else
  167. Kitt Hodsden • @kitt • http://ki.tt/wd15 167 function log(err, stdout,

    stderr, cb) { console.log(stdout); cb(); } grunt.initConfig({ shell: { dirListing: { command: 'ls', options: { callback: log } } } });
  168. Kitt Hodsden • @kitt • http://ki.tt/wd15 npm install grunt-mocha --save-

    dev 168 http://example.com/ Running client side tests
  169. Kitt Hodsden • @kitt • http://ki.tt/wd15 npm install grunt-mocha-test --

    save-dev 169 http://example.com/ Running server side tests
  170. Kitt Hodsden • @kitt • http://ki.tt/wd15 Integrate into CI builds

    170
  171. Kitt Hodsden • @kitt • http://ki.tt/wd15 171

  172. Kitt Hodsden • @kitt • http://ki.tt/wd15 Tracking over time 172

  173. Kitt Hodsden • @kitt • http://ki.tt/wd15 Tracking over time 173

    http://www.wptmonitor.org/home
  174. Kitt Hodsden • @kitt • http://ki.tt/wd15 npm install grunt-wpt --save-dev

    174 https://github.com/sideroad/grunt-wpt https://github.com/sideroad/grunt-wpt-page
  175. Kitt Hodsden • @kitt • http://ki.tt/wd15 175 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']);
  176. Kitt Hodsden • @kitt • http://ki.tt/wd15 176

  177. Kitt Hodsden • @kitt • http://ki.tt/wd15 177 https://github.com/trulia/webpagetest-charts-ui https://github.com/trulia/webpagetest-charts-api

  178. Kitt Hodsden • @kitt • http://ki.tt/wd15 178 Oh boy!

  179. Kitt Hodsden • @kitt • http://ki.tt/wd15 179 webpagetest-mapper

  180. Kitt Hodsden • @kitt • http://ki.tt/wd15 180 webpagetest-api

  181. Kitt Hodsden • @kitt • http://ki.tt/wd15 npm install webpagetest-api -g

    npm install webpagetest-mapper -g 181
  182. Kitt Hodsden • @kitt • http://ki.tt/wd15 182 $ cat tests.json

    [ { "name": "From the Middle", "url": "http://fromthemiddle.io/", "type": "home" }, { "name": "Kitt Hodsden", "url": "https://kitt.hodsden.org/", "type": "away" } ]
  183. Kitt Hodsden • @kitt • http://ki.tt/wd15 183

  184. Kitt Hodsden • @kitt • http://ki.tt/wd15 184

  185. Kitt Hodsden • @kitt • http://ki.tt/wd15 185 https://github.com/trulia/webpagetest-charts-ui https://github.com/trulia/webpagetest-charts-api

  186. Kitt Hodsden • @kitt • http://ki.tt/wd15 186 Determine key metrics

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

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

    Establish a baseline Make a change Measure effects Announce effects
  189. Kitt Hodsden • @kitt • http://ki.tt/wd15 189

  190. Kitt Hodsden • @kitt • http://ki.tt/wd15 190 sitespeed.io

  191. Kitt Hodsden • @kitt • http://ki.tt/wd15 191 http://run.sitespeed.io/

  192. Kitt Hodsden • @kitt • http://ki.tt/wd15 192

  193. Kitt Hodsden • @kitt • http://ki.tt/wd15 193

  194. Kitt Hodsden • @kitt • http://ki.tt/wd15 194

  195. Kitt Hodsden • @kitt • http://ki.tt/wd15 195

  196. Kitt Hodsden • @kitt • http://ki.tt/wd15 196

  197. Kitt Hodsden • @kitt • http://ki.tt/wd15 197

  198. Kitt Hodsden • @kitt • http://ki.tt/wd15 198 Automation!

  199. Kitt Hodsden • @kitt • http://ki.tt/wd15 199 https://speakerdeck.com/soulislove/monitoring- web-performance-using-open-source-tools-san- francisco-and-silicon-valley-web-performance-group

    Peter Hedenskog / @soulislove
  200. Kitt Hodsden • @kitt • http://ki.tt/wd15 200 https://speakerdeck.com/soulislove/monitoring- web-performance-using-open-source-tools-san- francisco-and-silicon-valley-web-performance-group

    snk.ms/sswpt
  201. Kitt Hodsden • @kitt • http://ki.tt/wd15 201 https://docs.docker.com/installation/

  202. Kitt Hodsden • @kitt • http://ki.tt/wd15 202 Start docker (osx)

  203. Kitt Hodsden • @kitt • http://ki.tt/wd15 203 docker pull sitespeedio/graphite

    docker pull grafana/grafana docker pull sitespeedio/sitespeed.io
  204. Kitt Hodsden • @kitt • http://ki.tt/wd15 204 start graphite

  205. Kitt Hodsden • @kitt • http://ki.tt/wd15 205 https://www.sitespeed.io/documentation/performance-dashboard/ $ sudo

    mkdir -p /data/graphite/storage/whisper $ sudo htpasswd -c /path/to/.htpasswd YOUR_USERNAME $ sudo docker run -d \ --name graphite \ -p 8080:80 \ -p 2003:2003 \ --restart="always" \ -v /data/graphite/storage/whisper:/opt/graphite/storage/whisper \ -v /path/to/.htpasswd:/etc/nginx/.htpasswd \ sitespeedio/graphite
  206. Kitt Hodsden • @kitt • http://ki.tt/wd15 206 start grafana

  207. Kitt Hodsden • @kitt • http://ki.tt/wd15 207 $ sudo mkdir

    -p /data/grafana $ sudo docker run -d -p 3000:3000 \ -v /data/grafana:/var/lib/grafana \ -e "GF_SECURITY_ADMIN_USER=myuser" \ -e "GF_SECURITY_ADMIN_PASSWORD=MY_SUPER_STRONG_PASSWORD" \ --name grafana \ --restart="always" \ grafana/grafana
  208. Kitt Hodsden • @kitt • http://ki.tt/wd15 208

  209. Kitt Hodsden • @kitt • http://ki.tt/wd15 209 $ sudo mkdir

    -p /data/grafana $ sudo docker run -d -p 3000:3000 \ -v /data/grafana:/var/lib/grafana \ -e "GF_SECURITY_ADMIN_USER=myuser" \ -e "GF_SECURITY_ADMIN_PASSWORD=MY_SUPER_STRONG_PASSWORD" \ --name grafana \ --restart="always" \ grafana/grafana
  210. Kitt Hodsden • @kitt • http://ki.tt/wd15 210 seed a single

    metric run
  211. Kitt Hodsden • @kitt • http://ki.tt/wd15 211 # ifconfig docker0

    Link encap:Ethernet HWaddr 02:42:62:d5:83:18 inet addr:172.17.42.1 Bcast:0.0.0.0 Mask:255.255.0.0 inet6 addr: fe80::42:62ff:fed5:8318/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:419578 errors:0 dropped:0 overruns:0 frame:0 TX packets:399294 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:66734551 (66.7 MB) TX bytes:834474594 (834.4 MB)
  212. Kitt Hodsden • @kitt • http://ki.tt/wd15 212 $ docker run

    --privileged --rm -v /sitespeed.io:/sitespeed.io sitespeedio/sitespeed.io sitespeed.io -u http://fromthemiddle.io -b firefox -n 1 --graphiteHost 172.17.42.1 --graphiteNamespace sitespeed.io
  213. Kitt Hodsden • @kitt • http://ki.tt/wd15 213 $ docker run

    --privileged --rm -v /sitespeed.io:/sitespeed.io sitespeedio/sitespeed.io sitespeed.io -u http://fromthemiddle.io -b firefox -n 1 --graphiteHost 172.17.42.1 --graphiteNamespace sitespeed.io
  214. Kitt Hodsden • @kitt • http://ki.tt/wd15 214 $ docker run

    --privileged --rm -v /sitespeed.io:/sitespeed.io sitespeedio/sitespeed.io sitespeed.io -u http://fromthemiddle.io -b firefox -n 1 --graphiteHost 172.17.42.1 --graphiteNamespace sitespeed.io
  215. Kitt Hodsden • @kitt • http://ki.tt/wd15 215

  216. Kitt Hodsden • @kitt • http://ki.tt/wd15 216

  217. Kitt Hodsden • @kitt • http://ki.tt/wd15 217

  218. Kitt Hodsden • @kitt • http://ki.tt/wd15 218

  219. Kitt Hodsden • @kitt • http://ki.tt/wd15 219

  220. Kitt Hodsden • @kitt • http://ki.tt/wd15 220

  221. Kitt Hodsden • @kitt • http://ki.tt/wd15 221

  222. Kitt Hodsden • @kitt • http://ki.tt/wd15 222

  223. Kitt Hodsden • @kitt • http://ki.tt/wd15 223

  224. Kitt Hodsden • @kitt • http://ki.tt/wd15 224

  225. Kitt Hodsden • @kitt • http://ki.tt/wd15 225

  226. Kitt Hodsden • @kitt • http://ki.tt/wd15 226

  227. Kitt Hodsden • @kitt • http://ki.tt/wd15 227

  228. Kitt Hodsden • @kitt • http://ki.tt/wd15 228 SHELL=/bin/bash PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin 0,15,30,45

    * * * * docker run --privileged --rm -v /sitespeed.io:/ sitespeed.io sitespeedio/sitespeed.io sitespeed.io -f urls.txt -b firefox -n 11 --connection cable -r /tmp/ --graphiteHost YOUR_GRAPHITE_HOST --seleniumServer http://127.0.0.1:4444/wd/hub >> /tmp/sitespeed-run.txt 2>&1 # YOUR_GRAPHITE_HOST = likely your IP address if you docker’d # -f urls.txt = list of URLs to analyze # -n 11 = depth to go, use -n for single page
  229. Kitt Hodsden • @kitt • http://ki.tt/wd15 Phew! 229

  230. Kitt Hodsden • @kitt • http://ki.tt/wd15 http://tiny.run:3000/ myuser / MY_SUPER_STRONG_PASSWORD

    hi / hihihi 230
  231. Kitt Hodsden • @kitt • http://ki.tt/wd15 Worth looking at: https://github.com/andyshora/grunt-yslow

    https://github.com/jrcryer/grunt-pagespeed https://github.com/addyosmani/psi/ http://perf-tooling.today/tools 231
  232. Kitt Hodsden • @kitt • http://ki.tt/wd15 232

  233. Kitt Hodsden • @kitt • http://ki.tt/wd15 Questions? 233

  234. Kitt Hodsden • @kitt • http://ki.tt/wd15 Thanks! Kitt Hodsden http://ki.tt/

    @kitt
  235. Kitt Hodsden • @kitt • http://ki.tt/wd15 235 Wait a second…

  236. Kitt Hodsden • @kitt • http://ki.tt/wd15 236

  237. Kitt Hodsden • @kitt • http://ki.tt/wd15 237

  238. Kitt Hodsden • @kitt • http://ki.tt/wd15 238 Set up your

    own WebPageTest server.
  239. Kitt Hodsden • @kitt • http://ki.tt/wd15 239 https://aws.amazon.com/ Login In

    to Amazon AWS
  240. Kitt Hodsden • @kitt • http://ki.tt/wd15 240 Click on EC2

  241. Kitt Hodsden • @kitt • http://ki.tt/wd15 241 Click on Launch

    Instance
  242. Kitt Hodsden • @kitt • http://ki.tt/wd15 242 Click on Community

    AMIs
  243. Kitt Hodsden • @kitt • http://ki.tt/wd15 243

  244. Kitt Hodsden • @kitt • http://ki.tt/wd15 244

  245. Kitt Hodsden • @kitt • http://ki.tt/wd15 245

  246. Kitt Hodsden • @kitt • http://ki.tt/wd15 246

  247. Kitt Hodsden • @kitt • http://ki.tt/wd15 247

  248. Kitt Hodsden • @kitt • http://ki.tt/wd15 248

  249. Kitt Hodsden • @kitt • http://ki.tt/wd15 249

  250. Kitt Hodsden • @kitt • http://ki.tt/wd15 250

  251. Kitt Hodsden • @kitt • http://ki.tt/wd15 251

  252. Kitt Hodsden • @kitt • http://ki.tt/wd15 252

  253. Kitt Hodsden • @kitt • http://ki.tt/wd15 253

  254. Kitt Hodsden • @kitt • http://ki.tt/wd15 254

  255. Kitt Hodsden • @kitt • http://ki.tt/wd15 255

  256. Kitt Hodsden • @kitt • http://ki.tt/wd15 256

  257. Kitt Hodsden • @kitt • http://ki.tt/wd15 257

  258. Kitt Hodsden • @kitt • http://ki.tt/wd15 258

  259. Kitt Hodsden • @kitt • http://ki.tt/wd15 259

  260. Kitt Hodsden • @kitt • http://ki.tt/wd15 260

  261. Kitt Hodsden • @kitt • http://ki.tt/wd15 261

  262. Kitt Hodsden • @kitt • http://ki.tt/wd15 262

  263. Kitt Hodsden • @kitt • http://ki.tt/wd15 263

  264. Kitt Hodsden • @kitt • http://ki.tt/wd15 264 $ ssh -i

    downloaded.pem ubuntu@ec2
  265. Kitt Hodsden • @kitt • http://ki.tt/wd15 265 $ ssh -i

    downloaded.pem ubuntu@ec2
  266. Kitt Hodsden • @kitt • http://ki.tt/wd15 266 $ vi ~/.ssh/authorized_keys

    dd # delete the first line [esc] # trigger the vi command sequence :wq # save the file and quit
  267. Kitt Hodsden • @kitt • http://ki.tt/wd15 267 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 #
  268. Kitt Hodsden • @kitt • http://ki.tt/wd15 268 sudo vi /var/www/webpage/test/www/settings/keys.ini

    [server] secret=addarandomstringhere key=addakeyhere [addakeyhere] description=Web UI ;contact=me@me.com limit=0 [thisisyourapikey] description=API Key ;contact=me@me.com limit=0
  269. Kitt Hodsden • @kitt • http://ki.tt/wd15 269 $ 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
  270. Kitt Hodsden • @kitt • http://ki.tt/wd15 270 $ sudo service

    nginx restart
  271. Kitt Hodsden • @kitt • http://ki.tt/wd15 271 Set up testing

    instances
  272. Kitt Hodsden • @kitt • http://ki.tt/wd15 272 EC2 server key

    in settings.ini (more complicated to set up, better automation management)
  273. Kitt Hodsden • @kitt • http://ki.tt/wd15 273 OR

  274. Kitt Hodsden • @kitt • http://ki.tt/wd15 274 Manual Setup

  275. Kitt Hodsden • @kitt • http://ki.tt/wd15 275 Click on Launch

    Instance
  276. Kitt Hodsden • @kitt • http://ki.tt/wd15 276

  277. Kitt Hodsden • @kitt • http://ki.tt/wd15 277 wpt_server=ec2.us-west-2.amazonaws.com wpt_key=YOURKEY wpt_location=us-west-2

  278. Kitt Hodsden • @kitt • http://ki.tt/wd15 278 Wait a few

    minutes…
  279. Kitt Hodsden • @kitt • http://ki.tt/wd15 279 … maybe a

    few more.
  280. Kitt Hodsden • @kitt • http://ki.tt/wd15 280

  281. Kitt Hodsden • @kitt • http://ki.tt/wd15 281

  282. Kitt Hodsden • @kitt • http://ki.tt/wd15 282

  283. Kitt Hodsden • @kitt • http://ki.tt/wd15 Questions? 283

  284. Kitt Hodsden • @kitt • http://ki.tt/wd15 Thanks! Kitt Hodsden http://ki.tt/

    @kitt slides here