Javascript Workshop
Stepan Suvorov
CTO @ Studytube
`${new Date().getFullYear() - 2005} years with Javascript`
Agenda
- Development tools
- Classes, properties and subtypes
- Inheritance
- async/await
- Iteration / Async Iterators
- Memory management
- Service Workers
- Event loop
- Architecture scale
- V8 Engine
Tools
- Package management(npm and yarn)
- Transpiling (babel, repl)
- Linting (eslint)
- Building (webpack)
- Testing (Jasmine, Jest)
- UI Framework (Angular, React, Vue, Ember)
- State Management (Redux)
- Styling (SCSS)
- Code scaffolding (Framework-cli, schematics)
- IDE (WebStrorm, VSCode +plugins)
- Documentation tool
- Security tools
- Performance (..., perfume.js)
- Debugging (Chrom Web Dev Tools)
Modern Classes
Classes
to create Objects
Methods and Properties
Method/property subtypes
Inheritance
some points
- super must be first
- inheritance for static properties
- how to call static method from normal?
Symbol
async/await
Promise
Promise.finally()
async/await
also async class methods
fetch()
+abortcontroller
Iteration
Symbol.iterator
Generators*
Async Iterators
for/await/of
for await (const doc of asyncIterable) {
console.log(doc.name);
}
Memory management
Map
is a collection of keyed data items, just like an Object. But the main difference is that Map allows keys of any type.
let john = { name: "John" };
let map = new Map();
map.set(john, "...");
john = null;
console.log(map.size); //1
WeakMap
is a collection of keyed data items, just like an Object. But the main difference is that Map allows keys of any type.
let john = { name: "John" };
let map = new WeakMap();
map.set(john, "...");
john = null;
console.log(map.size); //undefined
!WeakMap does not support iteration and methods keys(), values(), entries(), so there’s no way to get all keys or values from it.
Set & WeakSet
Service Workers
What are Service Workers?
- can't access the DOM directly
- control how network requests from your page
- It's terminated when not in use (no own state)
- extensive use of promises
- HTTPS required
- Reliability
- Performance
- Push Notifications
SW Life Cycle
Offline
Updates
Push Notifications
navigator.serviceWorker.register("/sw.js")
const version = "1.3.1";
const cacheName = `my-app-name-${version}`;
self.addEventListener('install', e => {
const timeStamp = Date.now();
e.waitUntil(
caches.open(cacheName).then(cache => {
return cache.addAll([
`/`,
`/index.html`,
`/app.js`,
...
]).then(() => self.skipWaiting());
})
);
});
self.addEventListener('activate', event => {
event.waitUntil(self.clients.claim());
});
self.addEventListener('fetch', event => {
event.respondWith(
caches.open(cacheName)
.then(cache => cache.match(event.request, {ignoreSearch: true}))
.then(response => {
return response || fetch(event.request);
})
);
});
NotificationApi
Event Loop
Definitions
- JS Engine
- Runtime Environment
- Event Queue
- Call Stack
One Thread
Why loop?
while (queue.waitForMessage())
queue.processNextMessage();
Never blocking
What will be the output?
console.log('START')
setTimeout(_ => console.log('setTimeout'));
Promise.resolve().then(_ => console.log('Promise'));
requestAnimationFrame(_ => console.log('RAF'))
console.log('FINISH')
while (eventLoop.waitForTask()) {
const taskQueue = eventLoop.selectTaskQueue()
if (taskQueue.hasNextTask()) {
taskQueue.processNextTask()
}
const microtaskQueue = eventLoop.microTaskQueue
while (microtaskQueue.hasNextMicrotask()) {
microtaskQueue.processNextMicrotask()
}
}
Microtask queue
So
- macrotasks: setTimeout, setInterval, setImmediate, requestAnimationFrame, I/O, UI rendering
- microtasks: process.nextTick, Promises, Object.observe, MutationObserver
and what about Rendering?
while (eventLoop.waitForTask()) {
const taskQueue = eventLoop.selectTaskQueue()
if (taskQueue.hasNextTask()) {
taskQueue.processNextTask()
}
const microtaskQueue = eventLoop.microTaskQueue
while (microtaskQueue.hasNextMicrotask()) {
microtaskQueue.processNextMicrotask()
}
if (shouldRender()) {
applyScrollResizeAndCSS()
runAnimationFrames()
render()
}
}
In Addition
Architecture scale
What is a Large JavaScript App?
- 100,000+ LoC?
- Xmb+ size?
- Lots of files?
- Hard to maintain
A large JavaScript application is a non-trivial application that requires significant effort to maintain and where most of the data manipulation takes place in the browser.
Addy Osmani
Modularise
- Break the large application up.
- Think of logical components
- Different sections on the screen?
4 Questions
- Can I reuse my modules?
- Will my application still function if this breaks?
- Is it testable?
- Does it depend on anything else?
Common Pitfalls
- Tight coupling
- Event webs
- Lack of tests
Tight Coupling
- Modules depends on each other
- What happens if another module breaks?
- Can we reuse this module?
- Can you test it?
Event Webs
Chat
Messages
Menu
Search
Loosen up!
- Loosely coupled modules
- They can be reused
- They don't depend on others
- They are easy to test
How to Achieve?
Facade & Mediator
Facade
Menu
Chat
Messages
- Abstracts complexity
- Exposes a simple interface
- bind/trigger
- Modules only communicate with the facade
Mediator
- The "brains" of the application
- Performs application specific actions based on the events
- Controls what the facade listens for
- Controls what the facade sends where
Micro-services / Micro-frontends
Core Ideas behind
- Development speed
- Small Autonomous Teams
- Technology Agnostic
- Isolate Team Code
- Establish Team Prefixes
How?
- Links
- iFrame
- WebComponents
Monorepo
Advantages
- Everyone uses the latest versions
- No version conflicts
- No burden with distributing libs
- Creating new libs: Adding folder
- Proved: used at Google, Facebook
Which way to go?
V8 Engine
only one of many
- V8 — open source, developed by Google, written in C++
- Rhino — managed by the Mozilla Foundation, open source, developed entirely in Java
- SpiderMonkey — the first JavaScript engine, which back in the days powered Netscape Navigator, and today powers Firefox
- JavaScriptCore — open source, marketed as Nitro and developed by Apple for Safari
- KJS — KDE’s engine originally developed by Harri Porten for the KDE project’s Konqueror web browser
- Chakra (JScript9) — Internet Explorer
- Chakra (JavaScript) — Microsoft Edge
- Nashorn, open source as part of OpenJDK, written by Oracle Java Languages and Tool Group
- JerryScript — is a lightweight engine for the Internet of Things.
V8 flow
- AST Parser
- Full-Codegen Compiler
- Crankshaft Compiler
- Hydrogen Compiler
- Lithium Compiler
Problems with Crankshaft
- Could not support new language features
- V8 supported them, but not directly in optimised code
- Too many guesses causes performance cliffs
- No clear separations between compilation phases
- Too much code to support 9 architectures
- so too much output code
new V8 flow
- AST Parser
- Interpreter Ignition
- TurboFan Compiler
V8 optimization
- Inlining
- Canonicalization
- Dead Code Elimination
- Dynamic Type Feedback
- Hidden Classes
-
Inline Caching
- Monomorphic
- Polymorphic
- On-Stack Replacement
- Compilation to machine code
- Garbage collection
- Ignition and TurboFan
Optimization killers
- Generators and async function
- for-of and destructing
- try-catch and try-finally
- Compound let or const assignment
- Object literals that contain __proto__
- get or set declarations
- debugger or with statements
- Literal calls to eval()
TurboFan changed the rules!
from Google IO
How to write better JS
- Order of object properties
- Dynamic properties
- Methods
- Arrays
- Tagged values
Insides with d8
Hvala vam na pažnji
Advanced Javascript
By Stepan Suvorov
Advanced Javascript
- 1,132