| Foreword | p. xi |
| From the Editor | p. xiii |
| About the Authors | p. xv |
| Preface | p. xxvii |
| WebPagetest Internals | p. 1 |
| Function Interception | p. 2 |
| Code Injection | p. 2 |
| Resulting Browser Architecture | p. 3 |
| Get the Code | p. 4 |
| Browser Advancements | p. 4 |
| IocalStorage Read Performance | p. 5 |
| The Benchmark | p. 6 |
| What's Going On? | p. 6 |
| Optimization Strategy | p. 7 |
| Follow Up | p. 8 |
| Why Inlining Everything Is NOT the Answer | p. 11 |
| No Browser Caching | p. 11 |
| No Edge Caching | p. 12 |
| No Loading On-Demand | p. 13 |
| Invalidates Browser Look-Ahead | p. 14 |
| Flawed Solution: Inline Everything only on First Visit | p. 14 |
| Summary and Recommendations | p. 15 |
| The Art and Craft of the Async Snippet | p. 17 |
| The Facebook Plug-ins JS SDK | p. 17 |
| Design Goals | p. 19 |
| The Snippet | p. 19 |
| Appending Alternatives | p. 21 |
| Whew! | p. 22 |
| What's Missing? | p. 22 |
| First Parties | p. 22 |
| Parting Words: On the Shoulders of Giants | p. 23 |
| Carrier Networks: Down the Rabbit Hole | p. 25 |
| Variability | p. 25 |
| Latency | p. 26 |
| Transcoding | p. 26 |
| Gold in Them There Hills | p. 27 |
| 4G Won't Save Us | p. 28 |
| Where Do We Go from Here? | p. 28 |
| Light at the End of the Tunnel | p. 28 |
| The Need for Parallelism in HTTP | p. 31 |
| Introduction: Falling Down the Stairs | p. 31 |
| Current Best Practices: Working around HTTP | p. 32 |
| Experiment: Mining the HTTP Archive | p. 33 |
| Results: Serialization Abounds | p. 34 |
| Recommendations: Time to Fix the Protocols | p. 34 |
| Automating Website Performance | p. 37 |
| FrontendSPOF in Beijing | p. 39 |
| Business Insider | p. 39 |
| CNET | p. 40 |
| O'Reilly Radar | p. 42 |
| The Cause of Frontend SPOF | p. 43 |
| Avoiding Frontend SPOF | p. 44 |
| Call to Action | p. 44 |
| All about YSlow | p. 47 |
| Secrets of High Performance Native Mobile Applications | p. 51 |
| Keep an Eye on Your Waterfalls | p. 52 |
| Compress Those Resources | p. 53 |
| Don't Download the Same Content Twice | p. 53 |
| Can Too Much Adriana Lima Slow You Down? | p. 54 |
| Epilogue | p. 55 |
| Pure CSS3 Images? Hmm, Maybe Later | p. 57 |
| The Challenge | p. 57 |
| Getting My Hands Dirty with CSS3 Cooking | p. 57 |
| Cross-Browser Results | p. 58 |
| Benchmarking | p. 59 |
| Payload | p. 59 |
| Rendering | p. 60 |
| Are We There Yet? | p. 62 |
| Appendix: Code Listings | p. 63 |
| HTML | p. 64 |
| CSS | p. 65 |
| Useless Downloads of Background Images in Android | p. 71 |
| The Android Problem | p. 71 |
| And the Lack of Solution | p. 72 |
| Timing the Web | p. 73 |
| Conclusion | p. 77 |
| I See HTTP | p. 79 |
| Some details | p. 79 |
| Walkthrough | p. 79 |
| Todos | p. 83 |
| The Road Ahead | p. 88 |
| All I Want for Christmas | p. 90 |
| Using Intelligent Caching to Avoid the Bot Performance Tax | p. 95 |
| A Practical Guide to the Navigation Timing API | p. 99 |
| Why You Should Care | p. 99 |
| Collecting Navigation Timing Timestamps and Turning Them into Useful Measurements | p. 100 |
| Using Google Analytics as a Performance Data Warehouse | p. 100 |
| Reporting on Performance in Google Analytics | p. 101 |
| Limitations | p. 101 |
| Final Thoughts | p. 102 |
| How Response Times Impact Business | p. 103 |
| Mobile UI Performance Considerations | p. 107 |
| Battery Life | p. 107 |
| Latency | p. 108 |
| Embedding CSS and JS: A Best Practice? | p. 108 |
| Memory | p. 110 |
| Optimize Images | p. 111 |
| Weigh the Benefits of CSS | p. 112 |
| GPU Benefits and Pitfalls | p. 112 |
| Viewport: Out of Sight Does Not Mean Out of Mind | p. 113 |
| Minimize the DOM | p. 113 |
| UI Responsiveness | p. 113 |
| Summary | p. 114 |
| Stop Wasting Your Time Using the Google Analytics Site Speed Report | p. 115 |
| Problem: A Bug in Firefox Implementation of the Navigation Timing API | p. 115 |
| Solution: Filter Out the Firefox Timings in Google Analytics | p. 116 |
| Good News: The Bug Was Fixed in Firefox 9 | p. 116 |
| Closing Remark | p. 116 |
| Beyond Web Developer Tools: Strace | p. 119 |
| What About Other Platforms? | p. 119 |
| Getting Started | p. 120 |
| Zeroing In | p. 120 |
| Example: Local Storage | p. 120 |
| We've Only Scratched the Surface | p. 121 |
| Introducing mod_spdy: A SPDY Module for the Apache HTTP Server | p. 123 |
| Getting Started with mod_spdy | p. 123 |
| SPDY and Apache | p. 123 |
| Help to Improve mod_spdy | p. 124 |
| Lazy Evaluation of CommonJS Modules | p. 127 |
| Close Encounters of the Text/JavaScript Type | p. 127 |
| Lazy Loading | p. 128 |
| Lazy Evaluation to the Rescue | p. 129 |
| Building Lazy Evaluation into CommonJS Modules | p. 130 |
| Advice on Trusting Advice | p. 133 |
| Why You're Probably Reading Your Performance Measurement Results Wrong (At Least You're in Good Company) | p. 137 |
| The Methodology | p. 138 |
| The Results | p. 138 |
| Conclusions | p. 139 |
| Why Does This Matter? | p. 139 |
| Takeaways | p. 139 |
| Lossy Image Compression | p. 141 |
| Lossy Compression | p. 142 |
| Performance Testing with Selenium and JavaScript | p. 145 |
| Recording Data | p. 145 |
| Collecting and Analyzing the Data | p. 147 |
| Sample Results | p. 148 |
| Benefits | p. 149 |
| Closing Words | p. 149 |
| Credits | p. 149 |
| A Simple Way to Measure Website Performance | p. 151 |
| Concept | p. 151 |
| Advantages | p. 152 |
| Limitation | p. 152 |
| Conclusion | p. 153 |
| Beyond Bandwidth: Ul Performance | p. 155 |
| Introduction | p. 155 |
| After the Page Loads: The UI Layer | p. 155 |
| UI Profilers | p. 156 |
| CSS Stress Test | p. 156 |
| CSS Profilers | p. 157 |
| CSS Lint | p. 157 |
| DOM Monster | p. 158 |
| Perception of Speed | p. 158 |
| Tidbits | p. 159 |
| Call for a Focus on UI Performance | p. 159 |
| CSS Selector Performance Has Changed! (For the Better) | p. 161 |
| Style Sharing | p. 162 |
| Rule Hashes | p. 162 |
| Ancestor Filters | p. 162 |
| Fast Path | p. 163 |
| What Is It Still Slow? | p. 163 |
| Losing Your Head with PhantomJS and confess.js | p. 165 |
| Performance Summaries | p. 165 |
| App Cache Manifest | p. 167 |
| Onward and Upward | p. 168 |
| Measure Twice, Cut Once | p. 169 |
| Identifying Pages/Sections | p. 170 |
| Identifying Features | p. 171 |
| Optimizing | p. 171 |
| When Good Backends Go Bad | p. 173 |
| What Is a Good Backend Time? | p. 174 |
| Figuring Out What Is Going On | p. 175 |
| Fixing It | p. 178 |
| Finally | p. 179 |
| Web Font Performance: Weighing @font-face Options and Alternatives | p. 181 |
| Font Hosting Services Versus Rolling Your Own | p. 181 |
| What the FOUT? | p. 182 |
| Removing Excess Font Glyphs | p. 183 |
| JavaScript Font Loaders | p. 184 |
| Introducing Boot.getFont: A Fast and Tiny Web Font Loader | p. 185 |
| Gentlefonts, Start Your Engines! | p. 186 |
| My Observations | p. 190 |
| Final Thoughts | p. 191 |
| Table of Contents provided by Ingram. All Rights Reserved. |