When I was finishing University I thought FrontEnd is not real programming....
I wanted to do this
🔥🔥🔥
NOT THIS! 😡
but actually...
To show you that FrontEnd is not just buttons...
...let's look behind the scenes of an open-source app, and see how it's built.
CODECS
AVIF
MozJPEG
WebP
...
WEB WORKER
SERVICE WORKER
CANVAS
PREACT
CLIENT
ROLLUP
CODECS
AVIF
MozJPEG
WebP
...
WEB WORKER
SERVICE WORKER
CANVAS
PREACT
CLIENT
ROLLUP
WASM is a way to run programming languages (other than JavaScript) into the browser.
#include <iostream>
using namespace std;
int main(int argc, char** argv)
{
cout << "You have entered " << argc
<< " arguments:" << "\n";
for (int i = 0; i < argc; ++i)
cout << argv[i] << "\n";
return 0;
}
hello.wasm
hello.js
✔️ Squoosh.app encodes images to different formats using C++ code converted to Web Assembly.
CODECS
AVIF
MozJPEG
WebP
...
WEB WORKER
SERVICE WORKER
CANVAS
PREACT
CLIENT
ROLLUP
JavaScript code that runs independently (separate thread) from the browser.
✔️ Perfect for doing intensive work in a non-blocking fashion
// Main App
let myWorker = new Worker("worker.js");
myWorker.postMessage("Here's some data");
myWorker.addEventListener("message", (e) => {
// ...
});
// worker.js
self.addEventListener("message", (e) => {
// ...
// ...
self.postMessage(/* ... */);
});
// Main App
const worker = new Worker('math-worker.js');
worker.postMessage({
type: 'add',
values: [Math.random(), Math.random()]
});
worker.addEventListener('message', (e) => {
switch (e.data.type) {
case 'result':
console.log(`Result from Worker is: ${e.data.value}`);
break;
default:
console.warn('[addEventListener] Unknown message type', e.type);
break;
}
});
// Worker
self.addEventListener('message', (e) => {
switch (e.data.type) {
case 'add':
self.postMessage({
type: 'result',
value: sum(e.data.values)
});
break;
default:
console.warn('[self.addEventListener] Unknown message type', e.type);
break;
}
});
function sum(numbers) {
let result = 0;
numbers.forEach(x => { result += x; })
return result;
}
💡 Notice the bottom-right spinner. That indicates the image is being encoded. While that happens the rest of the website stays fully responsive.
✔️ Squoosh.app uses Web Workers to convert the images off the main thread. This way, the website stays responsive.
CODECS
AVIF
MozJPEG
WebP
...
WEB WORKER
SERVICE WORKER
CANVAS
PREACT
CLIENT
ROLLUP
Imagine an empty piece of paper where you can programmatically draw anything, pixel by pixel.
✔️ Useful for custom visualizations, maps or games.
let canvas = document.getElementById("canvas");
let ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.rect(10, 100, 50, 50);
ctx.closePath();
ctx.fill();
<body>
<canvas id="canvas"></canvas>
</body>
Animating the Canvas
window.requestAnimationFrame(onFrame);
On each frame
re-draw the canvas
function onFrame() {
drawRectangle(xPos, CONFIG.y, direction);
xPos += direction;
if (xPos === canvas.width - 50) {
direction = -1;
}
if (xPos === 0) {
direction = 1;
}
window.requestAnimationFrame(onFrame);
}
✔️ Squoosh.app uses two Canvases, one for each side of the comparison.
CODECS
AVIF
MozJPEG
WebP
...
WEB WORKER
SERVICE WORKER
CANVAS
PREACT
CLIENT
ROLLUP
Preact is a fast, 3KB alternative to React with the same modern API.
✔️ When you want actually want to use React but payload size is very important to you.
<body>
<div>
<p>
The counter is
<span id="counter">0</span>
</p>
<button id="decreaseButton" type="button">
Decrease
</button>
<button id="increaseButton" type="button">
Increase
</button>
</div>
</body>
let counterValue = 0;
const counterDisplayElement = document.getElementById("counter");
const decreaseButton = document.getElementById("decreaseButton");
const increaseButton = document.getElementById("increaseButton");
decreaseButton.addEventListener("click", decreaseCounter);
increaseButton.addEventListener("click", increaseCounter);
function decreaseCounter() {
counterValue--;
counterDisplayElement.innerHTML = counterValue;
}
function increaseCounter() {
counterValue++;
counterDisplayElement.innerHTML = counterValue;
}
When we first learn JavaScript we see code like this ☝️
<body>
<Counter />
</body>
const Counter = () => {
const [counter, setCounter] = useState(0);
return (
<div>
<p>
The counter is <span> {counter} </span>
</p>
<button type="button" onClick={() => setCounter(counter - 1)}>
Decrease
</button>
<button type="button" onClick={() => setCounter(counter + 1)}>
Increase
</button>
</div>
);
};
But in actual apps, we'd write something like this. Simpler, declarative API which increases productivity!
This why frameworks/libraries
are always used.
✔️ The most popular one is React but here Squoosh uses Preact, a much much lighter alternative.
CODECS
AVIF
MozJPEG
WebP
...
WEB WORKER
SERVICE WORKER
CANVAS
PREACT
CLIENT
ROLLUP
✔️ Apps use bundlers to increase app performance, create a better dev experience and extend with features not natively supported.
Rollup is a module bundler for JavaScript.
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
static distance(a, b) {
const dx = a.x - b.x;
const dy = a.y - b.y;
return Math.hypot(dx, dy);
}
}
const p1 = new Point(5, 5);
const p2 = new Point(10, 10);
console.log(Point.displayName);
console.log(Point.distance(p1, p2));
class Point{constructor(t,n){this.x=t,this.y=n}static distance(t,n){const o=t.x-n.x,s=t.y-n.y;return Math.hypot(o,s)}}const p1=new Point(5,5),p2=new Point(10,10);console.log(Point.distance(p1,p2));
We code like this
But why not ship like this ???
370 bytes
VS
198 bytes
Performance
<head>
<title> App </title>
<script
src="//cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
<script
src="https://raw.githubusercontent.com/lodash/lodash/4.17.15-npm/lodash.js"></script>
<!-- .... -->
</head>
<body>
<script>
// window.moment
// window.sweetAlert
// window.lodash
</script>
</body>
import Swal from 'sweetalert2';
import lodash from 'lodash';
import moment from 'moment';
// Then use as variables, not from Window
Dev Experience
Instead of importing via CDN
Use NPM packages and import where needed
New features
const Counter = () => {
const [counter, setCounter] = useState(0);
return (
<div>
<p>
The counter is <span> {counter} </span>
</p>
<button type="button" onClick={() => setCounter(counter - 1)}>
Decrease
</button>
<button type="button" onClick={() => setCounter(counter + 1)}>
Increase
</button>
</div>
);
};
const Counter = () => {
const [counter, setCounter] = useState(0);
return React.createElement(
"div",
null,
React.createElement(
"p",
null,
"The counter is ",
React.createElement(
"span",
null,
" ",
counter,
" "
)
),
React.createElement(
"button",
{ type: "button", onClick: () => setCounter(counter - 1) },
"Decrease"
),
React.createElement(
"button",
{ type: "button", onClick: () => setCounter(counter + 1) },
"Increase"
)
);
};
Use features not natively supported, like JSX
But convert to actual JS when shipping the code
✔️ Cannot think of a single non-trivial app that's not using a bundler. They literally are used EVERYWHERE!
CODECS
AVIF
MozJPEG
WebP
...
WEB WORKER
SERVICE WORKER
CANVAS
PREACT
CLIENT
ROLLUP
A worker with special powers. Unlike usual Web Workers this one runs in the background even if the app is closed.
✔️ Allows offline experiences, push notifications and app installations.
📁 index.html
📁 style.css
📁 ...
Server
📁 index.html
📁 style.css
📁 ...
squoosh.app
Offline
// Main App
navigator
.serviceWorker
.register("service-worker.js")
.then(swRegistration => {
console.log("Service worker succesfully registered!");
}, err => {
console.error(`SW installation failed: ${err}`);
});
// Service Worker
const VERSION = 1;
const CACHE_NAME = `cache-${VERSION}`;
const resourcesToCache = [
"index.html",
"src/bundle.js",
"src/styles/style.css"
];
self.addEventListener('install', event => {
event.waitUntil(
caches.open(CACHE_NAME).then(cache => {
return cache.addAll(resourcesToCache)
})
);
});
self.addEventListener('fetch', event => {
if (event.request.url.indexOf(location.origin) === 0) {
const duplicatedRequest = event.request.clone();
event.respondWith(caches.match(event.request).then(resp => {
return resp || fetch(duplicatedRequest);
}));
}
});
App Installation
✔️ Squoosh.app uses a Service Worker to work offline, and be able to install on your device.
CODECS
AVIF
MozJPEG
WebP
...
WEB WORKER
SERVICE WORKER
CANVAS
PREACT
CLIENT
ROLLUP