Blake Newman
Frontend Engineer @ Attest
Vue.js Core Team Member
Twitter: @blakenewman
Github: @blake-newman
Agenda:
Background of Vue.js
Inbuilt features of Vue.js
Reactivity Systems
Templates, are they bad?
The future of Vue's internals
So, Vue.
Where did vue come from?
DOB: ~ July 2013
Birthname: Seed
Father: Evan You
@youyuxi
> 25 team members
> 12 languages
~ 65 repos/plugins
> 350 backers
> $18,000 monthly
Plus much more from alternative avenues
Financially viable OSS
> 163k ⭐ in organisation
http://git-awards.com/users
3rd most starred organisation
http://git-awards.com/users
6th most starred repository
Vue.js (core)
https://github.com/search?q=stars%3A%3E1&s=stars&type=Repositories
The
JavaScript Framework
Progressive
Declaritive Rendering
Component
System
Core
Routing
vue-router
State management
vuex
Build system
vue-loader
vue-cli
SSR / Native / Extensions
Ecosystem
Like JQuery?
(ish)
<body>
</body>
<body>
<div id="app">
</div>
</body>
<body>
<div id="app">
</div>
<script src="https://unpkg.com/vue"></script>
<script>
new Vue({
});
</script>
</body>
<body>
<div id="app">
</div>
<script src="https://unpkg.com/vue"></script>
<script>
new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
});
</script>
</body>
<body>
<div id="app">
</div>
<script src="https://unpkg.com/vue"></script>
</body>
<body>
<div id="app">
</div>
<script src="https://unpkg.com/vue"></script>
<script>
new Vue({
el: '#app'
});
</script>
</body>
<body>
<div id="app">
{{ message }}
</div>
<script src="https://unpkg.com/vue"></script>
<script>
new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
});
</script>
</body>
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>
<template>
<p class="red">
{{ message }}
</p>
</template>
<script>
export default {
data() {
return {
message: 'Hello world!'
};
}
};
</script>
<template>
<p class="red">
{{ message }}
</p>
</template>
<script>
export default {
data() {
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>
.red {
colour: red;
}
</style>
<p class="red" data-v-f3f3eg9></p>
<style>
.red[data-v-f3f3eg9] {
color: red;
}
</style>
<template>
<p class="red"></p>
</template>
<style scoped>
.red {
colour: red;
}
</style>
CSS Modules
<template>
<p :class="$style.red"></p>
</template>
<style>
.red {
colour: red;
}
</style>
<div class="_1VyoJ-uZOjlOxP7jWUy19_0"></div>
<style>
._1VyoJ-uZOjlOxP7jWUy19_0 {
color: red;
}
</style>
<template>
<p :class="$style.red"></p>
</template>
<style module>
.red {
colour: red;
}
</style>
HMR (Hot Module Replacement)
Compiler
HMR Server
Bundle Server
Compile
Change
code
HMR runtime
bundle
View
HMR (Hot Module Replacement)
Reactivity
class Child {
props = ['message', 'enabled'],
render() {
<div>{
this.enabled ? this.message : 'I am disabled'
}</div>
}
}
class Parent {
message = 'Hello world!'
enabled = false
render() {
return (
<div>
<Child message={this.message} enabled={!!this.message} />
<Child message={this.message} enabled={this.enabled} />
</div>
)
}
}
const vm = new Parent()
vm.message = ''
Pull Reactivity system
Pull
Explicit pull signal from developer
Manual optimisation hints from developer
Simplified with immutable data
class Child {
props = ['message', 'enabled'],
render() {
<div>{
this.enabled ? this.message : 'I am disabled'
}</div>
}
}
class Parent {
message = 'Hello world!'
enabled = false
render() {
return (
<div>
<Child message={this.message} enabled={!!this.message} />
<Child message={this.message} enabled={this.enabled} />
</div>
)
}
}
const vm = new Parent()
vm.message = ''
Push Reactivity system
Push
Memory overhead, proportional to dataset size
Asynchronous and batches updates
Improved by skipping observation of immutable data
Improved by reducing computation granularity
class Child {
props = ['message', 'enabled'],
render() {
<div>{
this.enabled ? this.message : 'I am disabled'
}</div>
}
}
class Parent {
message = 'Hello world!'
enabled = false
render() {
return (
<div>
<Child message={this.message} enabled={!!this.message} />
<Child message={this.message} enabled={this.enabled} />
</div>
)
}
}
const vm = new Parent()
vm.message = ''
Pull
Explicit pull signal from developer
Manual optimisation hints from developer
Simplified with immutable data
Push
Memory overhead, proportional to dataset size
Asynchronous and batches updates
Improved by skipping observation of immutable data
Improved by reducing computation granularity
Frameworks
Silver bullet
Angular 5 - 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
The future of Vue internals
Vue.js 2.6
Various updates and improvements
- error handling
- functional components
- SSR
Possible support for Native Map & Set types to be supported for reactivity
Vue.js 2.x-next
Will be targeting evergreen browsers only in order to leverage native ES2015 features
Reactivity system will be rewritten with Proxies with various improvements
No major breaking changes; will be maintained in parallel to 2.x with feature parity
Proxies?
The Proxy object is used to define custom behavior for fundamental operations (e.g. property lookup, assignment, enumeration, function invocation, etc).
Vue.js currently has a few caveat when tracking changes
- Array length change detection
- New property detection
- Delete property detection
Proxies allow us to detect all these type of mutations
Internal core moving to Typescript
Planned to move the internals of Vue.js to TypeScript:
- Heavily risen in popularity
- Improved code readability
- Stricter Typing
- Ensures code is as monophonic as possible
- Helps us produce better Typescript support as standard
Q&A
Vue.js - Deep dive, looking to the future
By Blake Newman
Vue.js - Deep dive, looking to the future
Slides for Frontend United 2018 - Utrecht. Vue.js is a progressive framework, we will entangle into the internals of Vue.js. Looking at the principles, benefits, caveats of many powerful features. Including Reactivity, Templates, Render Functions, Single File Components. While doing this we will look at how modern ES(X) features will evolve Vue to be an even more powerful.
- 2,648