Majid Hajian
Majid Hajian is a passionate software developer with years of developing and architecting complex web and mobile applications. He is passionate about web platform especially flutter, IoT, PWAs, and performance.
Majid Hajian
mhadaily
service workers can do more than caching
mhadaily
MaterialApp(
ThemeData(
name: "Majid Hajian",
location: "Oslo, Norway",
description: '''
Passionate Software engineer,
Community Leader, Author and international Speaker
''',
main: "Flutter/Dart, PWA, Performance",
homepage: "https://www.majidhajian.com",
socials: {
twitter: "https://www.twitter.com/mhadaily",
github: "https://www.github.com/mhadaily"
},
author: {
Pluralsight: "www.pluralsight.com/authors/majid-hajian",
Apress: "Progressive Web App with Angular, Book",
PacktPub: "PWA development, 7 hours video course",
Udemy: "PWA development, 7 hours video course",
}
founder: "Softiware As (www.Softiware.com)"
devDependencies: {
tea: "Ginger",
mac: "10.14+",
},
community: {
MobileEraConference: "Orginizer",
FlutterVikings: "Orginizer",
FlutterDartOslo: "Orginizer",
GDGOslo: "Co-Orginizer",
DevFestNorway: "Orginizer",
...more
})
);
Find me on the internet by
The Streams API
mhadaily
https://developer.mozilla.org/en-US/docs/Web/API/Streams_API
Core Cocenpt
Readable streams (ReadableStream)
Writable streams (WritableStream)
mhadaily
https://web.dev/streams/
import GrayscalePNGTransformer from './png-lib';
(async () => {
const image = document.getElementById('target');
// Fetch the original image
const response = await fetch('turtle.png');
// Retrieve its body as ReadableStream
const body = response.body;
// Create a gray-scaled PNG stream out of the original
const rs = body.pipeThrough(new TransformStream(new GrayscalePNGTransformer()));
// Create a new response out of the stream
const newResponse = new Response(rs);
// Create an object URL for the response
const blob = await newResponse.blob();
// create URL
const url = URL.createObjectURL(blob);
// Update image
image.src = url;
})();
addEventListener("fetch", event => {
event.respondWith(fetchAndStream(event.request))
})
async function fetchAndStream(request) {
// Fetch from origin server.
let response = await fetch(request)
// Create an identity TransformStream (a.k.a. a pipe).
// The readable side will become our new response body.
let { readable, writable } = new TransformStream()
// Start pumping the body. NOTE: No await!
response.body.pipeTo(writable)
// ... and deliver our Response while that’s running.
return new Response(readable, response)
}
This allows you to minimize:
mhadaily
import * from './transformstream.js';
import * from './JSONTransformer.js';
const dial = document.querySelector("progressbar");
fetch('./tweets.json')
.then(async resp => {
if (resp.status != 200) {
//Don't try to parse non JSON responses, such as a 404 error...
return;
}
const bytesTotal = parseInt(resp.headers.get('Content-Length'), 10);
const jsonStream = resp.body.pipeThrough(new TransformStream(new JSONTransformer()));
const reader = jsonStream.getReader();
let bytesCounted = 0;
while(true) {
const {value, done} = await reader.read();
if(done) {
dial.percentage = 1;
return;
}
bytesCounted += value.length;
dial.percentage = bytesCounted / bytesTotal;
}
});
mhadaily
PRECACHE
mhadaily
PRECACHE
shell_header.html
shell_footer.html
mhadaily
Dynamically changes
mhadaily
https://www.youtube.com/watch?v=25aCD5XL1Jk
import {precache} from 'workbox-precaching';
precache([
{url: '/shell_header.html', revision: SHELL_HEADER_REV},
{url: '/shell_footer.html', revision: SHELL_FOOTER_REV},
// Additional resources to precache...
]);
mhadaily
const contentStrategy = workbox.strategies.staleWhileRevalidate({
cacheName: API_CACHE_NAME,
plugins: [
new workbox.expiration.Plugin({maxEntries: 50}),
],
});
const cacheStrategy = workbox.strategies.cacheFirst({
cacheName: workbox.core.cacheNames.precache,
});
registerRoute(/\.html$/,
workbox.streams.strategy([
// Get from cache
() => cacheStrategy.handle({
request: new Request(getCacheKeyForURL("/shell_header.html")),
}),
// Get the body from the network
({request}) => contentStrategy.handle({
request: `${request.url}?content=true`
});
// Get from cache
() => cacheStrategy.handle({
request: new Request(getCacheKeyForURL("/shell_footer.html")),
}),
]);
);
mhadaily
mhadaily
The web platform today is way more powerful than what we think!
let's embrace it!
Majid Hajian
mhadaily
Slides and link to source code
slides.com/mhadaily
majid[at]softiware[dot]com
SVG icons credited to undraw.co
By Majid Hajian
The Streams API provides an interface for reading or writing asynchronous chunks of data, only a subset of which might be available in memory at any given time. The API helps to enhance UX both in a SPA or MPA (Multi-page) architecture. Using the Streams API within our service worker makes that possible. Workbox Streams abstracts the details of how streaming works. In this short talk, you will learn how to leverage the powerful Stream to enhance UX and boost the web page's performance.
Majid Hajian is a passionate software developer with years of developing and architecting complex web and mobile applications. He is passionate about web platform especially flutter, IoT, PWAs, and performance.