Slide 1

Slide 1 text

A React Inspired UI framework in Pure Ruby 1

Slide 2

Slide 2 text

About Me • David Chang @zetachang (github, twitter) • Software Engineer @ ಋ಑ೌ搚 solda.io • Author of HyperReact (a.k.a reactrb) - a ReactJS wrapper. 2

Slide 3

Slide 3 text

Building UI is hard 3

Slide 4

Slide 4 text

4

Slide 5

Slide 5 text

I love JavaScript 5

Slide 6

Slide 6 text

I love JavaScript 6

Slide 7

Slide 7 text

I love CoffeeScript 7

Slide 8

Slide 8 text

I love CoffeeScript 8

Slide 9

Slide 9 text

I love TypeScript 9

Slide 10

Slide 10 text

I love TypeScript 10

Slide 11

Slide 11 text

I love ClojureScript 11

Slide 12

Slide 12 text

I love ClojureScript 12

Slide 13

Slide 13 text

Hmm.. 13

Slide 14

Slide 14 text

Tons of languages compile to JavaScript 14

Slide 15

Slide 15 text

is one of them. 15

Slide 16

Slide 16 text

Atoll A Ruby Library for Building User Interfaces 16

Slide 17

Slide 17 text

Atoll vs. React 17

Slide 18

Slide 18 text

A React Component (ES6 + JSX҂ class HelloMessage extends React.Component { render() { return
Hello {this.props.name}
; } } An Atoll Component (Plain Ruby) class HelloMessage < Atoll::Component def render h('div', nil, "Hello #{props[:name]}") end end 18

Slide 19

Slide 19 text

Built upon Ruby Idioms 1. Shorter & cleaner method name. 2. Familiar toolchain (e.g. rake, rspec, sprockets.) 19

Slide 20

Slide 20 text

Shorter & Cleaner method name • componentWillMount • componentDidMount • componentWillReceiveProps • shouldComponentUpdate 20

Slide 21

Slide 21 text

Shorter & Cleaner method name • componentWillMount before_mount • componentDidMount after_mount • componentWillReceiveProps before_receive_props • shouldComponentUpdate needs_update? 21

Slide 22

Slide 22 text

Familiar Toolchains • Sprockets • ERB • Rake • RSpec • .... • (webpack, gulp, babel, yarn, npm, browserify, rollup, jest, mocha, enzyme) 22

Slide 23

Slide 23 text

Demo 23

Slide 24

Slide 24 text

Ideas taken from React • Declarative - predictable & easier to debug. • Everything is a Component - Proper separation of concerns. • Learn Once Write Anywhere - how to render is handled by library. 24

Slide 25

Slide 25 text

Declarative UI 25

Slide 26

Slide 26 text

UI Component: 26

Slide 27

Slide 27 text

class Timer < Component def initialize @state = { second: 0 } end def after_mount $window.every(1) { set_state(sec: state[:second] + 1) } end def render h('span', nil, "Time elapsed: #{state[:second]}") end end 27

Slide 28

Slide 28 text

Mindset 1. Always re-render when data change. 2. Component returns a blueprint instead of the actual instance of UI. 3. Framework do the hard work to generate minimal UI updates. 28

Slide 29

Slide 29 text

Everything is a component 29

Slide 30

Slide 30 text

Store Profile 30

Slide 31

Slide 31 text

31

Slide 32

Slide 32 text

32

Slide 33

Slide 33 text

33

Slide 34

Slide 34 text

34

Slide 35

Slide 35 text

Why Component-Based UI? 1. A proper separation of concerns for applications. 2. Fundamental building blocks for application. 35

Slide 36

Slide 36 text

Learn Once Write Anywhere 36

Slide 37

Slide 37 text

Let's render this: h("div", nil, "Hello") 37

Slide 38

Slide 38 text

38

Slide 39

Slide 39 text

39

Slide 40

Slide 40 text

Demo 40

Slide 41

Slide 41 text

Server Side Rendering (a.k.a SSR) 41

Slide 42

Slide 42 text

Client-side rendering • initial request loads the page layout, CSS and JavaScript. • some or all of the content isn't included Server-side rendering • initial request loads the page, layout, CSS, JavaScript • and content. 42

Slide 43

Slide 43 text

Why Server Side Rendering? • Better start-up experience. • Visible to search engines (SEO.) • User might disable JavaScript. 43

Slide 44

Slide 44 text

Current Problems 1. Component state could not be preserved 2. Side-effects to make a meaningful first mount must be handled at the top level. 3. JS Runtime is required (e.g. V8, Nashorn.) 44

Slide 45

Slide 45 text

Let's fix this in Atoll! 45

Slide 46

Slide 46 text

Marshal! 46

Slide 47

Slide 47 text

Marshal class Foo attr_reader :bar def initialize @bar = "yeah" end end f = Foo.new s = Marshal.dump(f) # => "\x04\bo:\bFoo\x06:\t@barI\"\tyeah\x06:\x06ET" f = Marshal.load(s) f.bar # => "yeah" 47

Slide 48

Slide 48 text

Marshal • Serialize object to byte stream. • Supported by almost every Rubies (e.g. Opal, MRI, RubyMotion.) • Almost everything could be marshaled by default. 48

Slide 49

Slide 49 text

Demo 49

Slide 50

Slide 50 text

On server <%= atoll_component(LikeButton) %> On client
Like
50

Slide 51

Slide 51 text

What's unlocked? • Could be used with existing template toolchain. • Server side rendering for mobile app. • Pre-render for selective component. 51

Slide 52

Slide 52 text

Road ahead • Will be free & open sourced • Follow @atollrb. ! • Also follow @opalrb, @RubyMotion • It’s simply fun to build this. " 52