Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Once you go PRPL - FullStackFest
Search
Houssein Djirdeh
September 07, 2017
46
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Once you go PRPL - FullStackFest
Houssein Djirdeh
September 07, 2017
Transcript
65 slides
XKCD/Installing
Once you go PRPL… @hdjirdeh
PUSH critical resources RENDER initial route PRE-CACHE resources LAZY LOAD
remaining routes P R L P
None
None
None
None
CSS
JS
PNG
<link rel="preload" as="script" href="script.js"> <link rel="preload" as="script" href="script.js"> <html lang="en">
<head> <link rel="stylesheet" href="styles.css"> </head> <body> <!--(>'-')> <('-'<)--> <script src="script.js"></script> </body> </html>
JS JS
<link rel="preload" as="script" href="script.js"> as="script" <link rel="preload" as="style" href="styles.css"> as="style"
as="font" as="audio" as="image" as="video"
<link rel="prefetch">
preload-webpack-plugin <link rel="preload" href="chunk.cf7bd8260d685f704bd0.js" as="script"> <link rel="prefetch" href="chunk.cf7bd8260d685f704bd0.js">
CAN I HAZ? Partial Support
HTTP/2 Server Push
None
None
Link: </app/style.css>; rel=preload; as=style Link: </app/script.js>; rel=preload; as=script
None
Link: </app/style.css>; rel=preload; as=style; nopush Link: </app/script.js>; rel=preload; as=script
A Comprehensive Guide To HTTP/2 Server Push - Jeremy Wagner
https://rebrand.ly/http2
Pushing too much
Pushing unused assets
Cache?
PUSH critical resources
None
Service workers
A service worker is a script that runs in the
background of your browser when you view a webpage.
ADDING A SERVICE WORKER 1. Create the file and write
the logic yourself 2. Use a library
None
npm install workbox-cli --global workbox-cli generate:sw
None
<script> if ('serviceWorker' in navigator) { window.addEventListener('load', function () {
navigator.serviceWorker.register('/service-worker.js').then(function(){ // Registration was successful console.log('ServiceWorker registration successful!'); }).catch(function(err) { // registration failed :( console.log('ServiceWorker registration failed: ', err); }); }); } </script> if ('serviceWorker' in navigator) { window.addEventListener('load', function () { navigator.serviceWorker.register('/service-worker.js') <script> if ('serviceWorker' in navigator) { window.addEventListener('load', function () { navigator.serviceWorker.register('/service-worker.js').then(function(){ // Registration was successful console.log('ServiceWorker registration successful!'); }).catch(function(err) { // registration failed :( console.log('ServiceWorker registration failed: ', err); }); }); } </script> <script> if ('serviceWorker' in navigator) { window.addEventListener('load', function () { navigator.serviceWorker.register('/service-worker.js').then(function(){ // Registration was successful console.log('ServiceWorker registration successful!'); }).catch(function(err) { // registration failed :( console.log('ServiceWorker registration failed: ', err); }); }); } </script>
None
APPLICATION SHELL
APPLICATION SHELL CONTENT
module.exports = { globDirectory: 'dist/', globPatterns: ['**/*.{js,png,svg,html,json}'], swDest: 'dist/service-worker.js', navigateFallback:
'/index.html' }; module.exports = { globDirectory: 'dist/', globPatterns: ['**/*.{js,png,svg,html,json}'], swDest: 'dist/service-worker.js', navigateFallback: '/index.html', }; module.exports = { globDirectory: 'dist/', globPatterns: ['**/*.{js,png,svg,html,json}'], swDest: 'dist/service-worker.js', navigateFallback: '/index.html' }; globDirectory: 'dist/' globPatterns: ['**/*.{js,png,svg,html,json}'] swDest: 'dist/service-worker.js' navigateFallback: '/index.html'
npm install workbox-cli --save-dev // package.json "scripts": { //... "build":
"{build} && workbox-cli generate:sw" }
workbox-webpack-plugin
DYNAMIC CONTENT
module.exports = { globDirectory: 'dist/', globPatterns: ['**/*.{js,png,svg,html,json}'], swDest: 'dist/service-worker.js', navigateFallback:
'/index.html', runtimeCaching: [ { urlPattern: /^https:\/\/your.api.com\/.*/, handler: 'networkFirst' } ] }; runtimeCaching: [ { urlPattern: /^https:\/\/your.api.com\/.*/, handler: 'networkFirst' } ] module.exports = { globDirectory: 'dist/', globPatterns: ['**/*.{js,png,svg,html,json}'], swDest: 'dist/service-worker.js', navigateFallback: '/index.html', runtimeCaching: [ { urlPattern: /^https:\/\/your.api.com\/.*/, handler: 'networkFirst' } ] }; networkFirst cacheFirst fastest cacheOnly networkOnly runtimeCaching: [ { urlPattern: /^https:\/\/your.api.com\/.*/, handler: 'networkFirst' } ]
runtimeCaching: [ { urlPattern: /^https:\/\/your.api.com\/.*/, handler: 'networkFirst' } ] module.exports
= { globDirectory: 'dist/', globPatterns: ['**/*.{js,png,svg,html,json}'], swDest: 'dist/service-worker.js', navigateFallback: '/index.html', runtimeCaching: [ { urlPattern: /^https:\/\/your.api.com\/.*/, handler: 'networkFirst' } ] }; runtimeCaching: [ { urlPattern: /^https:\/\/your.api.com\/.*/, handler: 'networkFirst' } ] networkFirst
networkFirst
networkFirst cacheFirst fastest cacheOnly networkOnly
APP SHELL + DYNAMIC CACHING
OFFLINE SUPPORT + FASTER REPEAT VISITS
CAN I HAZ? Under development
Service Worker H2 Push
PRE-CACHE resources
BUNDLES
4KB - 200KB Size of JS frameworks, gzipped Restuta/framework-sizes.md GIST
CODE SPLITTING
export const routes: Routes = [ { path: '', redirectTo:
'main', pathMatch: 'full' }, { path: 'main', component: MainComponent }, { path: 'details', loadChildren: 'details/details.module#DetailsModule' } ]; export const routes: Routes = [ { path: '', redirectTo: 'main', pathMatch: 'full' }, { path: 'main', component: MainComponent }, { path: 'details', loadChildren: 'details/details.module#DetailsModule' } ]; loadChildren: 'details/details.module#DetailsModule'
export const routes: Routes = [ { path: '', redirectTo:
'main', pathMatch: 'full' }, { path: 'main', component: MainComponent }, { path: 'details', loadChildren: 'details/details.module#DetailsModule' } ]; loadChildren: 'details/details.module#DetailsModule'
import Loadable from 'react-loadable'; import Loading from './loading.component'; const LoadableComponent
= Loadable({ loader: () => import('./details.component'), loading: Loading, });
None
WEBPACK BUNDLE ANALYZER
bundlesize
LAZY LOAD remaining routes
PRPL PUSH critical resources RENDER initial route PRE-CACHE resources LAZY
LOAD remaining routes
TIME TO INTERACTIVE FIRST PAINT
None
@hdjirdeh
More Decks by Houssein Djirdeh
See All by Houssein Djirdeh
Performance Empathy
housseindjirdeh
0
220
The Art of Lazy Loading
housseindjirdeh
0
590
GitPoint - Lunch and Learn
housseindjirdeh
0
140
Progressive Web Apps - fullStackTO/FITC Web Unleashed
housseindjirdeh
0
230
Once you go PRPL: SeattleJS
housseindjirdeh
0
200
Featured
See All Featured
Data-driven link building: lessons from a $708K investment (BrightonSEO talk)
szymonslowik
1
1.4k
SERP Conf. Vienna - Web Accessibility: Optimizing for Inclusivity and SEO
sarafernandez
2
1.7k
The #1 spot is gone: here's how to win anyway
tamaranovitovic
4
1.2k
Fantastic passwords and where to find them - at NoRuKo
philnash
53
4k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
16k
Navigating Team Friction
lara
192
16k
Practical Orchestrator
shlominoach
192
12k
Evolving SEO for Evolving Search Engines
ryanjones
0
360
My Coaching Mixtape
mlcsv
0
390
The Illustrated Guide to Node.js - THAT Conference 2024
reverentgeek
1
610
We Analyzed 250 Million AI Search Results: Here's What I Found
joshbly
2
2.1k