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

  1. Can I reuse my modules?
  2. Will my application still function if this breaks?
  3. Is it testable?
  4. 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