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.

3f2f0c0fbc7be587727cdfff33c8be43?s=128

Kitt Hodsden

October 29, 2015
Tweet

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