Independent Consultant & Software Architect
Trainer, Speaker, JS/TS Expert
ArchitekturaNaFroncie.pl (ANF)
Warsaw, PL
tomasz (at) ducin.dev
@tomasz_ducin
Digest Cycle
Service
Digest Cycle
async task ⚙️
async task ⚙️
async task ⚙️
Zone.js-based Change Detection
<body>
<div>
<div>
<span>
<div>
<img>
<h1>
<p>
in browsers
<body>
<div>
<div>
<span>
<div>
<img>
<h1>
<p>
in React
export const Heading = (props) =>
<div>
<h1>{ props.heading }</h1>
<img src={ props.imageURL } />
</div>
function Heading(props) {
return React.createElement("div", null,
React.createElement("h1", null, props.heading),
React.createElement("img", {
src: props.imageURL
})
);
};
render phase (virtual) + commit phase (DOM repaint)
Pre-compiled instructions updating the DOM straight away
No virtual representation, no runtime overhead
Pre-compiled instructions updating the DOM straight away
No virtual representation, no runtime overhead
<script>
const sendLog = console.log
let amount = 100000;
let rate = 4.0;
$: exchange = amount / rate
$: sendLog(exchange)
</script>
...
<div>exchange: {exchange}</div>
let div2, t6, t7, ...
c(){ // create
...
div2 = element("div");
t6 = text("exchange: ");
t7 = text(/*exchange*/ ctx[2]);
},
m(target, anchor) { // mount
...
append(div3, div2);
append(div2, t6);
append(div2, t7);
}, ...
View as a Function of State
new object reference == change => need to refresh UI
const object = { name: "John Lennon", age: 39 }
// native
const newOne = { ...object, age: object.age + 1 }
// immer.js
const newOne = produce(object, draft => {
draft.age += 1
})
with stable references
Cutting off renders of entire subtree
@Component({
selector: 'listing',
changeDetection: ChangeDetectionStrategy.OnPush,
template: `...`
})
export class ListingComponent {
...
}
(Imperative) vs (Declarative, Inversion of Control)
let rate = 3.94;
let amount = 1000;
let exchange = amount / rate; // 253.80
rate = 3.97;
exchange // 🔥 DESYNC, sync manually! INVARIANT BROKEN
let rate$ = 3.94;
let amount$ = 1000;
let exchange$ = amount$ / rate$; // 253.80
rate$ = 3.97;
exchange$ // 251.89
let rate$ = 3.94;
let amount$ = 1000;
let exchange$ = combineLatest(amount$, rate$,
(amount, rate) => amount / rate);
let rate$ = 3.94;
let amount$ = 1000;
let exchange$ = combineLatest(amount$, rate$,
(amount, rate) => amount / rate);
// rate$ == 3.97 ---> exchange$ == 251.89
RxJS, heavily used in Angular
const rate = signal(3.94);
const amount = signal(1000);
const exchange = computed(() => amount() / rate()); // 253.80
rate.set(3.97);
rate.update(old => old + 0.03);
effect(() => sendLog(`exchange: ${exchange()}`)) // 251.89
New Reactivity Model: Signals replacing RxJS in Angular
<script>
const sendLog = console.log
let amount = 1000;
let rate = 3.94;
$: exchange = amount / rate
$: sendLog(exchange)
</script>
<input bind:value="{amount}" />
<input bind:value="{rate}" />
<div>exchange: {exchange}</div>
<script>
const sendLog = console.log
let amount = 1000;
let rate = 3.94;
$: exchange = amount / rate
$: sendLog(exchange)
</script>
Fundamental in Svelte
const [amount, setAmount] = useState(1000);
const [rate, setRate] = useState(3.94);
const exchange = useMemo(
() => amount / rate, [amount, rate])
useEffect(() => {
sendLog(`exchange: ${exchange}`)
}, [exchange])
FP-based, highly declarative new paradigm in React
private component state or shared
Publisher-Subscriber pattern, Centralized, in-memory Event Sourcing
Publisher-Subscriber pattern, Centralized
Stale While Revalidate pattern (refreshing data in the background)
MPA: Multi-Page Apps
(historical, thin client or no client)
SPA: Single-Page Apps
(status quo, client runs everything)
SSR: Server-Side Rendering
(request-time + Hydration)
SSG: Static Site Generation
(build-time + Hydration)
(R)SC: (React) Server Components
(Partial Hydration: interactive UI + non-interactive UI)
Qwik: Progressive Hydration / No Hydration
TypeScript is widely acclaimed, finally
Angular is being drastically simplified, finally
Entry-level for FE development gets higher
Partial Hydration / Progressive Hydration
will probably revolutionize Webapps Architecture
React/Next.js introduces cutting-edge solutions
hence, increases complexity
Svelte & Qwik implement bleeding-edge solutions
but are rather unlikely to become massively adapted