---
# System prepended metadata

title: '2018/11/28 How-to: Make your application real-time'

---

---
title: "2018/11/28 How-to: Make your application real-time"
type: slide
disqus: hackmd
slideOptions:
  width: 1000
---

## How-to: Make your application real-time
https://hackmd.io/p/parisjs-realtime

---

## We'll invite you to play with us!<br>Get ready to join with your phone or laptop.

---

# Join the Demo!
https://hackmd.io/parisjs-realtime-demo

---

# <i class="fa fa-file-text"></i> HackMD
Build community with open collaboration

----

<style>
.reveal section img {
  border: none;
  background: none;
}
</style>


![](https://i.imgur.com/H1OLOmh.png =80%x)
Techstars backed

----

## Helping developers to enjoy writing documentations.

:100: :book: :books: 

----

## Help open source technologies to build an active developer community.

<i class="fa fa-github fa-4x"></i>

---

<img src="https://i.imgur.com/PTbB46S.jpg" style="width:300px;height:300px;border-radius:50%"/>

## Max Wu

#### CTO of HackMD

I love great product and build them.<br>I'm developing my dream with code.

---

# What is real-time?
Enable users to receive information as soon as it is published by its authors.

----

<!-- .slide: data-background-image="https://i.imgur.com/4uEx1Ho.png" -->

----

### How fast will you consider it's real-time?

60 FPS makes a smooth video.<!-- .element: class="fragment" data-fragment-index="1" -->

**60 frames per second (FPS)**<!-- .element: class="fragment" data-fragment-index="2" -->

1000 millisecond / 60 frames<!-- .element: class="fragment" data-fragment-index="3" -->
~= 16.67 ms/frame

----

<!-- .slide: data-background-image="https://media.giphy.com/media/3owzW5c1tPq63MPmWk/giphy.gif" -->
# 16.67 ms
# for such a computation

----

## The average network latency is<br>70 ms

----

<!-- .slide: data-background-image="https://i.imgur.com/dd30BnK.png" -->

----

### Hard to feel it's real-time
if it only shows when data arrives

----

# So you fake it! :stuck_out_tongue_winking_eye: 
that's what most modern web app does

----

### Optimistic lock

- Show as soon as user inputs it<!-- .element: class="fragment" data-fragment-index="1" -->
- Put the operation into buffer and send later<!-- .element: class="fragment" data-fragment-index="2" -->
- Rollback if it fails later<!-- .element: class="fragment" data-fragment-index="3" -->

---

## What makes web real-time?
- You need to connect network <!-- .element: class="fragment" data-fragment-index="1" --> :stuck_out_tongue_closed_eyes:
- So that server can receive your changes<!-- .element: class="fragment" data-fragment-index="2" -->
- And other clients are able to receive updates<!-- .element: class="fragment" data-fragment-index="3" -->
- Let's see how HTTP works<!-- .element: class="fragment" data-fragment-index="4" -->

----

## traditional HTTP model
1. client sends request to server<!-- .element: class="fragment" data-fragment-index="1" --> 
2. server responses data to client<!-- .element: class="fragment" data-fragment-index="2" --> 

----

<!-- .slide: data-background-image="https://i.imgur.com/tYJZNdr.png" -->

----

## It's one way communication

server can't actively push data to client<!-- .element: class="fragment" data-fragment-index="3" --> 

real-time requires to send updates to client
<!-- .element: class="fragment" data-fragment-index="4" --> 

:cry: <!-- .element: class="fragment" data-fragment-index="4" --> 

----

## long-polling HTTP model
1. client sends request to server<!-- .element: class="fragment" data-fragment-index="1" -->
2. keeps the connection open<!-- .element: class="fragment" data-fragment-index="2" -->
3. client waits until server sends data<!-- .element: class="fragment" data-fragment-index="3" -->

----

<!-- .slide: data-background-image="https://i.imgur.com/yLV2Mim.png" -->

----

## Still one way communication
- But it works!<!-- .element: class="fragment" data-fragment-index="1" --> :triumph: (and for a long time)
- HTTP 1.1 is half-duplex,
  traffic flows only go one direction at a time<!-- .element: class="fragment" data-fragment-index="2" -->
- HTTP is stateless,
  reduntant information sent with every request and response<!-- .element: class="fragment" data-fragment-index="3" -->

:tired_face: <!-- .element: class="fragment" data-fragment-index="4" -->

----

## WebSocket comes to rescue!
:thumbsup: :thumbsup: :thumbsup: 

----

# WebSocket
- bidirectional communication <!-- .element: class="fragment" data-fragment-index="1" --> :tada: 
- smaller data frame (~1/3 than HTTP) <!-- .element: class="fragment" data-fragment-index="2" --> :package: 
- lower latency (~4x faster than HTTP) <!-- .element: class="fragment" data-fragment-index="3" --> :zap: 

[ref.](https://blog.feathersjs.com/http-vs-websockets-a-performance-comparison-da2533f13a77)<!-- .element: class="fragment" data-fragment-index="3" -->

----

<!-- .slide: data-background-image="https://i.imgur.com/vGkUyko.png" -->

----

### Efficiency

|  | HTTP | WebSocket |
| -------- | -------- | -------- |
| Overhead | 100s bytes | 2-6 bytes |
| Latency (traditional) | New connection every time | None: use existing connection |
| Latency (long-polling) | Time to set up next request | No waiting |
<!-- .element: class="fragment" data-fragment-index="1" -->

[ref.](https://www.slideshare.net/peterlubbers/html5-real-time-and-websocket/47-WebSocket_Efficiency_HTTP_WebSocketOverhead_100s)
<!-- .element: class="fragment" data-fragment-index="1" -->

---

## What can you build with WebSocket?

see some examples<!-- .element: class="fragment" data-fragment-index="1" -->

----

### Collaborative text editor

## <i class="fa fa-file-text"></i> HackMD

:sparkles: https://hackmd.io :sparkles: 

----

## `Agar.io`
An online multipleplayer game

<!-- .slide: data-background-image="https://media.giphy.com/media/kwaJMnc18hDFu/giphy.gif" -->

----

## <span style="color: black;"> Online chat room</span>
https://socketio-chat-example.now.sh/

<!-- .slide: data-background-video="https://i.cloudup.com/transcoded/J4xwRU9DRn.mp4" -->

----

# <i class="fa fa-github"></i> GitHub
also uses it to update pages
- When other people comment on the issue
- When issue has been closed
- When pull request have more commits
- etc...

----

### There's always a catch

![](https://i.imgur.com/gPH7VBw.png =800x)
https://caniuse.com/#search=websocket

---

## Time for `Socket.IO` :rocket: 

----

## `Socket.IO` :star2: 
1. Establishes long-polling connection first<!-- .element: class="fragment" data-fragment-index="1" --> 
2. Tries to upgrade to WebSocket transports<!-- .element: class="fragment" data-fragment-index="2" --> 
3. If it fails will fallback to use long-polling<!-- .element: class="fragment" data-fragment-index="3" --> 

Everyone now is happy<!-- .element: class="fragment" data-fragment-index="4" --> :smirk: 

----

## `Socket.IO` :stars: 
- Intuitive APIs<!-- .element: class="fragment" data-fragment-index="1" --> 
- Easy to broadcast multiple clients<!-- .element: class="fragment" data-fragment-index="2" --> 
- Built-in logic for rooms and namespaces<!-- .element: class="fragment" data-fragment-index="3" --> 

:yellow_heart: <!-- .element: class="fragment" data-fragment-index="4" --> 

---

## Let's make a chat room with `Socket.IO`

----

## Installation

<div>

Client

```htmlmixed=
<script src="/socket.io/socket.io.js"></script>
```

<small>Include `socket.io-client` script in the html.</small>

</div>
<!-- .element: class="fragment" data-fragment-index="1" --> 

----

## Installation

<div>

Server

```
npm install --save socket.io
```

<small>Install `socket.io` from npm</small>

</div>
<!-- .element: class="fragment" data-fragment-index="1" -->

<div>

```javascript=
const server = require('http').createServer()
const io = require('socket.io')(server)
server.listen(3000)
```
<small>Create HTTP server and bind with `socket.io` in the node.js app.</small>

</div>

<!-- .element: class="fragment" data-fragment-index="2" -->

----

## Client establishes connection

```javascript=
const socket = io()
```
<!-- .element: class="fragment" data-fragment-index="1" -->

<small>Client tries to connect chat room</small>
<!-- .element: class="fragment" data-fragment-index="1" -->

----

## Server listens on connection

```javascript=
io.on('connection', socket => {
  console.log('a user connected')
  socket.on('disconnect', () => {
    console.log('user disconnected')
  })
})
```
<!-- .element: class="fragment" data-fragment-index="1" -->

<small>Server accepts client connection</small>
<!-- .element: class="fragment" data-fragment-index="1" -->

----

## Server broadcasts to everyone

```javascript=
io.emit('room message', 'room is ready')
```
<!-- .element: class="fragment" data-fragment-index="1" -->

<small>Server broadcasts room status</small>
<!-- .element: class="fragment" data-fragment-index="1" -->

----

## Client emits event

```javascript=
socket.emit('chat message', 'hello world!')
```
<!-- .element: class="fragment" data-fragment-index="1" -->

<small>Client emits chat message to room</small>
<!-- .element: class="fragment" data-fragment-index="1" -->

----

## Server listens on event

```javascript=
socket.on('chat message', msg => {
  console.log('message: ' + msg)
})
```
<!-- .element: class="fragment" data-fragment-index="1" -->

<small>Server receives the message</small>
<!-- .element: class="fragment" data-fragment-index="1" -->

----

## Server sends to everyone
excepts for a certain socket

```javascript=
io.on('connection', socket => {
  socket.on('chat message', msg => {
    console.log('message: ' + msg)
    socket.broadcast.emit(msg)
  })
})
```
<!-- .element: class="fragment" data-fragment-index="1" -->

<small>Server broadcasts chat message to other clients</small>
<!-- .element: class="fragment" data-fragment-index="1" -->

[read more](https://socket.io/get-started/chat)
[emit cheatsheet](https://socket.io/docs/emit-cheatsheet/)
<!-- .element: class="fragment" data-fragment-index="1" -->

----

<!-- .slide: data-background-image="https://cdn-images-1.medium.com/max/1600/1*H0mCDTWdcO_rmNZTUI8fmw.jpeg" data-background-size="80%" -->

---

## Server-Sent Events

an alternative for sending from server to client

----

## Server-Sent Events
- It's one way - server pushes to client<!-- .element: class="fragment" data-fragment-index="1" -->
- Part of HTML5 standard<!-- .element: class="fragment" data-fragment-index="2" -->
- Good with HTTP/2 (which is full-duplex)<!-- .element: class="fragment" data-fragment-index="3" -->
- Automatic reconnection and event binding<!-- .element: class="fragment" data-fragment-index="4" -->

----

<!-- .slide: data-background-image="https://i.imgur.com/AfmQl7t.png" -->

----

### There's always a catch, again

![](https://i.imgur.com/vtCKu94.png =800x)
<small>Can be easily polyfilled!</small>
https://caniuse.com/#search=server%20sent

---

### Comparsion

|  | HTTP | WebSocket | SSE |
| -------- | -------- | -------- | ----- |
| Direction | Client to Server | Bidirectional | Server to Client |
| Native support | 100% | 90% | 84% |
| Overhead | High | Low | Medium |
| Latency | 1-2s | < 1s | 1s |
<!-- .element: class="fragment" data-fragment-index="1" -->

---

## TL;DR
- You can fake the real-time experience
- long-polling is the old way to be real-time
- WebSocket is the real bidirectional communication
- `Socket.IO` is the one for all
- Server-Sent Events with HTTP/2 can be an alternative

---

# Thanks for listening!
Do you have any question?

<i class="fa fa-github"></i> <i class="fa fa-twitter"></i> @jackycute

<i class="fa fa-file-text"></i> HackMD.io

---

## References
- [Why are movies shown in 24fps while 60fps looks more real?](https://www.quora.com/Why-are-movies-shown-in-24fps-while-60fps-looks-more-real)
- [An Introduction to WebSockets](https://blog.teamtreehouse.com/an-introduction-to-websockets)
- [Engine.IO: the realtime engine](https://github.com/socketio/engine.io#goals)
- [What Socket.IO is](https://socket.io/docs/#What-Socket-IO-is)

----

## References
- [Ultra fast applications using Node.js](https://openclassrooms.com/en/courses/2504541-ultra-fast-applications-using-node-js/2505653-socket-io-let-s-go-to-real-time)
- [Building a Node.js WebSocket Chat App with Socket.io and React](https://itnext.io/building-a-node-js-websocket-chat-app-with-socket-io-and-react-473a0686d1e1)
- [How JavaScript works: Deep dive into WebSockets and HTTP/2 with SSE + how to pick the right path](https://blog.sessionstack.com/how-javascript-works-deep-dive-into-websockets-and-http-2-with-sse-how-to-pick-the-right-path-584e6b8e3bf7)
- [Polling vs SSE vs WebSocket— How to choose the right one
](https://codeburst.io/polling-vs-sse-vs-websocket-how-to-choose-the-right-one-1859e4e13bd9)
