Vue.js
Service workers going Realtime
#infoshare / Blake Newman / @blakenewman
Text
slides.com/blakenewman
Agenda:
Background and features of Vue.js
Reactivity Systems
Templates, are they bad?
Service Workers in Realtime
So, Vue.
Where did vue come from?
DOB: ~ July 2013
Birthname: Seed
Father: Evan You
@youyuxi
> 25 team members
> 12 languages
~ 50 repos/plugins
> 160 backers
> 20 companies
> $10,000 monthly
Plus much more from alternative avenues
Financially viable OSS
> 110k ⭐ in organisation
http://githubstats.lip.is/
14th most starred organisation
http://githubstats.lip.is/
11th most starred repository
Vue.js (core)
http://githubstats.lip.is/
> 1.6 billion npm downloads
The
JavaScript Framework
Progressive
Like JQuery?
<body>
<div id="app">
{{ message }}
</div>
<script src="https://unpkg.com/vue"></script>
<script>
new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
});
</script>
</body>
(ish)
Reactivity
Single File Components
Asynchronous Components
Dynamic Components
Hot Reloading
vue-router
Vuex
Virtual DOM
SSR
Devtools
Ava.js
Jest
Nuxt.js
Streaming
Pre-processors
JSX
Caching
Render Functions
Weex
Scoped CSS
CSS Modules
Beautiful Documenation
Transition Effects
Template Engine
Slots
Scoped Slots
Functional Components
TypeScript
Critical CSS
Provide & Inject
PWA
Single File Component
<template>
<p class="red">
{{ message }}
</p>
</template>
<script>
module.exports = {
data: function () {
return {
message: 'Hello world!'
};
}
};
</script>
<style>
.red {
colour: red;
}
</style>
Pre-Processing
<template lang="pug">
p.red {{ message }}
</template>
<script lang="ts">
import Vue from 'vue'
import Component from 'vue-class-component'
@Component
export default class MyComponent extends Vue {
message: string = 'Hello world!'
}
</script>
<style lang="styl">
.red
colour red
</style>
Scoped CSS
<template>
<p class="red"></p>
</template>
<style scoped>
.red {
colour: red;
}
</style>
<p class="red" data-v-f3f3eg9></p>
<style>
.red[data-v-f3f3eg9] {
color: red;
}
</style>
CSS Modules
<template>
<p :class="$style.red"></p>
</template>
<style module>
.red {
colour: red;
}
</style>
<div class="_1VyoJ-uZOjlOxP7jWUy19_0"></div>
<style>
._1VyoJ-uZOjlOxP7jWUy19_0 {
color: red;
}
</style>
Hot reloading
Scaffolding Templates
https://github.com/vuejs-templates
CLI
https://github.com/vuejs/vue-cli
Reactivity
Pull Reactivity system
Push Reactivity system
Pull
Explicit pull signal from developer
Manual optimisation hints from developer
Simplified with immutable data
Push
Memory overhead, proportional to dataset size
Improved by skipping observation of immutable data
Improved by reducing computation granularity
Frameworks
Silver bullet
Angular 2 onPush with Observables
React + MobX
Vue 2 + Immutable data
Templates
Render Functions (JSX)
<template>
<p>{{ message }}</p>
</template>
function render() {
var _vm = this
var _h = _vm.$createElement
var _c = _vm._self._c || _h
return _c('p', [
_vm._v(_vm._s(_vm.message))
])
}
Representation
function render() {
return (
<div>{ this.message }</div>
)
}
{
class: {
foo: true,
bar: false
},
style: {
color: 'red',
fontSize: '14px'
},
attrs: {
id: 'foo'
},
props: {
myProp: 'bar'
},
on: {
click: this.clickHandler
},
// ...
}
Virtual DOM Node
function render() {
return React.createElement(
"div",
null,
this.items.map(function (item) {
return React.createElement("p", null, item);
}),
React.createElement("p", null, this.message)
)
}
Normalisation
function render() {
return (
<div>
{ this.items.map(item => <p>{ item }</p>) }
<p>{ this.message }</p>
</div>
)
}
[node, [node, ...], node]
<template>
<div>
<p v-for="item in items">{{ item }}</p>
<p>{{ message }}</p>
</div>
</template>
function render() {
var _vm = this
var _h = _vm.$createElement
var _c = _vm._self._c || _h
return _c('div', [_vm._l((_vm.items), function(item) {
return _c('p', [_vm._v(_vm._s(item))])
}), _c('p', [_vm._v(_vm._s(_vm.message))])], 2)
}
<template>
<div>
<span>Static content</span>
<span>More static content</span>
</div>
</template>
Static nodes
function render() {
return (
<div>
<h2>Static content</h2>
<p>More static content</p>
</div>
)
}
function render() {
var _vm = this
var _h = _vm.$createElement
var _c = _vm._self._c || _h
return _vm._m(0)
}
function render() {
return React.createElement(
"div",
null,
React.createElement("span", null, "Static content"),
React.createElement("span", null, "More static content")
)
}
Further Optimisations
Render (JSX)
Templates
Declarative with JSX
Presentational
Logical
HTML + small DSL
Child normalization
Declarative
Power of JavaScript
No DSL?
Static node hoisting
Progressive code updates
Closer to compiler
Service Workers and going Realtime
Service Workers
Web Workers
Server
Service Worker
Cache
Client
WebSockets
WebSocket
Server
Client
Combined
Server
Service Worker
Client
WebSocket
WTF?!?
HELP
Client to server messaging system
Server
Service Worker
Cache
Client
WebSocket
Server
Service Worker
Cache
Client
WebSocket
self.addEventListener('fetch', event => {
const { request } = event;
const url = new URL(request.url);
// Ignore not GET request or is is different origin.
if (request.method !== 'GET' || url.origin !== self.location.origin) return;
event.respondWith(async () => {
try {
// If not online and cache available then use cache
if (!navigator.onLine) {
const cache = await caches.match(request);
if (cache) return cache;
}
// Request message
const response = await self.fetch(request);
// If not 'ok' then do not cache
if (!response.ok) return response;
// Add response to cache
const openCache = await caches.open(CACHE_NAME);
await openCache.put(request, response.clone());
return response;
} catch (error) {
// User is landing on a page.
return request.mode === 'navigate' ? caches.match('./') : '';
}
});
});
Server
Service Worker
Cache
Client
WebSocket
const socketIO = require('socket.io');
const express = require('express');
const app = express();
const io = socketIO(app);
app.post('/api/user', () => {
io.emit('USER_COUNT_UPDATED');
});
app.get('/api/user/count', (req, res) => {
res.json({ count: 99283374 }).end();
});
Server
Service Worker
Cache
Client
WebSocket
import io from 'socket.io-client';
export default store => {
const socket = io.connect();
socket.on('connect', () => store.dispatch('app/connect'));
socket.on('disconnect', () => store.dispatch('app/disconnect'));
socket.on('USER_COUNT_UPDATED', () => store.dispatch('user/getCount'));
};
// Load Socket layer asynchronously in separate chunk
import('./socket').then(socket => socket.default(store));
// Setup service worker
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('service-worker.js', { scope: './' });
}
Server
Service Worker
Cache
Client
WebSocket
Twitter: @blakenewman
Github: @blake-newman
Feedback: goo.gl/1dc6i9
Slides: slides.com/blakenewman
Q&A
Vue.js and Service workers going Realtime
By Blake Newman
Vue.js and Service workers going Realtime
Slides for infoshare.pl 'Vue.js and Service Workers going realtime'. What is Vue.js where did it come from? We will take an overview look at the new kid on the block. Exploring the workings of a `Progressive Framework’ and where it sits in the industry. While discovering Vue.js we will explore the infamous PWA’s (Progressive Web Applications), which will take the spot light in majority of application in the web. Extending the PWA platform we will look how Sockets and Service Workers can coexist together, a PRA (Progressive Realtime Application), allowing platforms to improve the user experience without affecting the critical download chain.
- 5,288