Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Once you go PRPL - FullStackFest
Search
Houssein Djirdeh
September 07, 2017
45
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
More Decks by Houssein Djirdeh
See All by Houssein Djirdeh
Performance Empathy
housseindjirdeh
0
210
The Art of Lazy Loading
housseindjirdeh
0
570
GitPoint - Lunch and Learn
housseindjirdeh
0
130
Progressive Web Apps - fullStackTO/FITC Web Unleashed
housseindjirdeh
0
230
Once you go PRPL: SeattleJS
housseindjirdeh
0
200
Featured
See All Featured
For a Future-Friendly Web
brad_frost
183
10k
Money Talks: Using Revenue to Get Sh*t Done
nikkihalliwell
0
280
The Curious Case for Waylosing
cassininazir
1
420
The browser strikes back
jonoalderson
0
1.4k
Statistics for Hackers
jakevdp
799
230k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
49
10k
Fireside Chat
paigeccino
42
4k
Primal Persuasion: How to Engage the Brain for Learning That Lasts
tmiket
0
380
Skip the Path - Find Your Career Trail
mkilby
1
160
Unsuck your backbone
ammeep
672
58k
Code Review Best Practice
trishagee
74
20k
Max Prin - Stacking Signals: How International SEO Comes Together (And Falls Apart)
techseoconnect
PRO
0
200
Transcript
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