## 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>

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://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

<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)
{"metaMigratedAt":"2023-06-14T19:09:12.361Z","metaMigratedFrom":"YAML","title":"2018/11/28 How-to: Make your application real-time","breaks":true,"disqus":"hackmd","slideOptions":"{\"width\":1000}","contributors":"[{\"id\":\"61af98f4-b303-4819-b08b-aa32cf6677a8\",\"add\":15750,\"del\":3046}]"}