Save 37% off PRO during our Black Friday Sale! »

Volt & Opal (Vilnius.rb)

Volt & Opal (Vilnius.rb)

Slide deck from my Vilnius.rb talk about Volt and Opal.

Efd2550fb5f3059d815e731ecd61b701?s=128

Bozhidar Batsov

November 20, 2015
Tweet

Transcript

  1. Volt: Ruby Web Development Recharged by Bozhidar Batsov

  2. Sveiki!

  3. @bbatsov

  4. Joan

  5. None
  6. Sveiki!

  7. None
  8. Sasha, our beloved leader/CTO

  9. I’m an Emacs fanatic

  10. I love Ruby

  11. I don’t like JavaScript

  12. None
  13. None
  14. None
  15. None
  16. Why am I here?

  17. None
  18. Ruby (2005)

  19. None
  20. None
  21. None
  22. Ruby (2006)

  23. OMG, Rails is amazing!

  24. Ruby (2008)

  25. OMG, Rails is amazing & useful!

  26. Ruby (today)

  27. Rails is somewhat boring…

  28. Rails is the new JEE!

  29. Aren’t all the cool devs doing Clojure now?

  30. Hell, yeah!!!

  31. Rails innovation (2005-2008) • Convention over configuration • Interactive development

    • Scaffolding • ActiveRecord • REST
  32. Rails innovation (today) • new Turbolinks • new Sprockets •

    foreign keys • background jobs • web sockets
  33. None
  34. None
  35. 4% 96% Web Development Other

  36. 10% 90% Rails Other

  37. None
  38. Ruby 2.2 includes many new features and improvements for the

    increasingly diverse and expanding demands for Ruby. For example, Ruby’s Garbage Collector is now able to collect Symbol type objects. This reduces memory usage of Symbols; because GC was previously unable to collect them before 2.2. Since Rails 5.0 will require Symbol GC, it will support only Ruby 2.2 or later. (See Rails 4.2 release post for details.) Also, a reduced pause time thanks to the new Incremental Garbage Collector will be helpful for running Rails applications. Recent developments mentioned on the Rails blog suggest that Rails 5.0 will take advantage of Incremental GC as well as Symbol GC.
  39. Ruby 2.2 includes many new features and improvements for the

    increasingly diverse and expanding demands for Ruby. For example, Ruby’s Garbage Collector is now able to collect Symbol type objects. This reduces memory usage of Symbols; because GC was previously unable to collect them before 2.2. Since Rails 5.0 will require Symbol GC, it will support only Ruby 2.2 or later. (See Rails 4.2 release post for details.) Also, a reduced pause time thanks to the new Incremental Garbage Collector will be helpful for running Rails applications. Recent developments mentioned on the Rails blog suggest that Rails 5.0 will take advantage of Incremental GC as well as Symbol GC.
  40. Ruby 2.2 includes many new features and improvements for the

    increasingly diverse and expanding demands for Ruby. For example, Ruby’s Garbage Collector is now able to collect Symbol type objects. This reduces memory usage of Symbols; because GC was previously unable to collect them before 2.2. Since Rails 5.0 will require Symbol GC, it will support only Ruby 2.2 or later. (See Rails 4.2 release post for details.) Also, a reduced pause time thanks to the new Incremental Garbage Collector will be helpful for running Rails applications. Recent developments mentioned on the Rails blog suggest that Rails 5.0 will take advantage of Incremental GC as well as Symbol GC.
  41. Ruby 2.2 includes many new features and improvements for the

    increasingly diverse and expanding demands for Ruby. For example, Ruby’s Garbage Collector is now able to collect Symbol type objects. This reduces memory usage of Symbols; because GC was previously unable to collect them before 2.2. Since Rails 5.0 will require Symbol GC, it will support only Ruby 2.2 or later. (See Rails 4.2 release post for details.) Also, a reduced pause time thanks to the new Incremental Garbage Collector will be helpful for running Rails applications. Recent developments mentioned on the Rails blog suggest that Rails 5.0 will take advantage of Incremental GC as well as Symbol GC.
  42. Ruby 2.2 includes many new features and improvements for the

    increasingly diverse and expanding demands for Ruby. For example, Ruby’s Garbage Collector is now able to collect Symbol type objects. This reduces memory usage of Symbols; because GC was previously unable to collect them before 2.2. Since Rails 5.0 will require Symbol GC, it will support only Ruby 2.2 or later. (See Rails 4.2 release post for details.) Also, a reduced pause time thanks to the new Incremental Garbage Collector will be helpful for running Rails applications. Recent developments mentioned on the Rails blog suggest that Rails 5.0 will take advantage of Incremental GC as well as Symbol GC.
  43. Ruby 2.2 includes many new features and improvements for the

    increasingly diverse and expanding demands for Ruby. For example, Ruby’s Garbage Collector is now able to collect Symbol type objects. This reduces memory usage of Symbols; because GC was previously unable to collect them before 2.2. Since Rails 5.0 will require Symbol GC, it will support only Ruby 2.2 or later. (See Rails 4.2 release post for details.) Also, a reduced pause time thanks to the new Incremental Garbage Collector will be helpful for running Rails applications. Recent developments mentioned on the Rails blog suggest that Rails 5.0 will take advantage of Incremental GC as well as Symbol GC.
  44. That’s sick!

  45. JRuby

  46. RubyMotion

  47. Rails, Rails, Rails

  48. And what about JavaScript?

  49. Things people are doing with JavaScript • Client-side apps •

    Server-side apps - Node.js • iOS & Android apps (using React Native) • Windows Phone apps • Desktop app (e.g. for Windows & GNOME)
  50. WOW!

  51. None
  52. Development Complexity

  53. 0 25 50 75 100 1999 2000 2001 2002 2003

    2004 2005 2006 2007 2009 2011 2015
  54. Web development (2005) Power to the server! Model View Controller

    Routing Server Client
  55. Web development (2006) Model View Controller Routing Server Client AJAX

    RandomJS
  56. Web development (2010) Model View Controller Routing Server Client AJAX

    REST Assets RandomJS
  57. Model View Controller Routing Server Client AJAX REST Model View

    Controller Routing Assets Assets Present Days
  58. None
  59. Is there a solution?

  60. Yes!

  61. What’s the solution?

  62. VBScript!

  63. Isomorphic Development

  64. Isomorphic?

  65. Isomorphic being of identical or similar form, shape, or structure

  66. Same code runs on the client & the server

  67. Model View Controller Routing Server Client AJAX REST Model View

    Controller Routing Assets Assets Shared Auto Sync
  68. Meteor.js

  69. JS makes me sad!

  70. Ruby is better than JavaScript

  71. None
  72. None
  73. Ruby’s advantages • Doesn’t have this • Sane boolean semantics

    • No need for a book called “Ruby: The Good Parts” • No wtfruby.com • Solid core library • Extensive standard library • Do you really need more?
  74. Meet Volt

  75. Volt is a web framework

  76. Volt is isomorphic

  77. Models, views, controllers & routing are shared between the client

    and the server
  78. One more thing…

  79. They are all written in Ruby

  80. WOW!!!

  81. Ruby on the server-side, Ruby on the client-side

  82. Ruby on the server-side, Ruby on the client-side

  83. Ruby on the server-side

  84. Ruby on the client-side

  85. Fuck this shit!!!

  86. Opal.rb http://opalrb.org/

  87. The Value Proposition

  88. Ruby to JavaScript source-to-source compiler

  89. Ruby Opal JavaScript

  90. No new VM

  91. No bytecode

  92. No translation layers

  93. An implementation of Ruby’s corelib and stdlib

  94. But we already have CoffeeScript!

  95. CoffeeScript’s shortfalls • Same (spartan) core library • No standard

    library • It’s not Ruby
  96. A basic example

  97. def hello(name) puts "Hello, #{name.capitalize}!" end hello("bruce")

  98. /* Generated by Opal 0.7.0 */ (function(Opal) { Opal.dynamic_require_severity =

    "error"; var self = Opal.top, $scope = Opal, nil = Opal.nil, $breaker = Opal.breaker, $slice = Opal.slice; Opal.add_stubs(['$puts', '$capitalize', '$hello']); Opal.Object.$$proto.$hello = function(name) { var self = this; return self.$puts("Hello, " + (name.$capitalize()) + "!"); }; return self.$hello("bruce"); })(Opal);
  99. Opal.Object.$$proto.$hello = function(name) { var self = this; return self.$puts("Hello,

    " + (name.$capitalize()) + "!"); }; return self.$hello("bruce");
  100. The magic happens in Opal.compile

  101. Opal.compile( "puts 'Hi, Vilnius!’" )

  102. "/* Generated by Opal 0.7.2 */ \n(function(Opal) {\n Opal.dynamic_require_severity =

    \"error\";\n var self = Opal.top, $scope = Opal, nil = Opal.nil, $breaker = Opal.breaker, $slice = Opal.slice;\n\n Opal.add_stubs(['$puts']);\n return self.$puts(\"Hi, Vilnius!\")\n})(Opal); \n"
  103. /* Generated by Opal 0.7.2 */ (function(Opal) { Opal.dynamic_require_severity =

    "error"; var self = Opal.top, $scope = Opal, nil = Opal.nil, $breaker = Opal.breaker, $slice = Opal.slice; Opal.add_stubs(['$puts']); return self.$puts("Hi, Vilnius!") })(Opal);
  104. Ruby to JS mapping • self -> this (mostly) •

    Ruby method/block -> JS function • Ruby string -> JS string • Ruby number -> JS number • Ruby array -> JS array • Ruby hash -> custom JS type
  105. JavaScript interop

  106. >> `"bozhidar".toUpperCase()` => "BOZHIDAR"

  107. class Array def length `this.length` end end

  108. `window.title` # => "Opal: Ruby to JavaScript compiler" %x{ console.log("Opal

    version is:"); console.log(#{RUBY_ENGINE_VERSION}); } # => Opal version is: # => 0.8.0
  109. Alternative JS interop (coming in Opal 0.9)

  110. # JavaScript: foo.bar(1, "a") foo.JS.bar(1, :a) foo.JS.bar 1, :a

  111. # JavaScript: # ($a = foo) # .bar # .apply($a,

    [1].concat([2, 3])) foo.JS.bar(1, *[2, 3]) foo.JS.bar 1, *[2, 3]
  112. # JavaScript: # ($a = (TMP_1 = function(arg){ # var

    self = TMP_1.$$s || this; # if (arg == null) arg = nil; # return "" + (arg.method()) + " " + (self.$baz(3)) # }, # TMP_1.$$s = self, TMP_1), # foo.bar)(1, 2, $a); foo.JS.bar(1, 2) { |arg| arg.JS.method + baz(3) }
  113. # JavaScript: foo["bar"] foo.JS[:bar] # JavaScript: foo[2] foo.JS[2] # JavaScript:

    foo["bar"] = 1 foo.JS[:bar] = 1 # JavaScript: foo[2] = "a" foo.JS[2] = :a
  114. require 'js' # new foo(bar) JS.new(foo, bar) # delete foo["bar"]

    JS.delete(foo, :bar) # "bar" in foo JS.in(:bar, foo) # foo instanceof bar JS.instanceof(foo, bar) # typeof foo JS.typeof(foo)
  115. require 'js' # parseFloat("1.1") JS.call(:parseFloat, '1.1') JS.parseFloat('1.1')

  116. Ruby from JavaScript

  117. class Foo def bar puts 'Called Foo#bar' end end

  118. Opal.Foo.$new().$bar(); // => “Called Foo#bar”

  119. Is Opal any good?

  120. Very basic corelib No stdlib Semicolons Misc WTFs JavaScript Complexity

  121. Performance Debugging Ruby Compatibility Ruby WTFs Opal’s Perceived Complexity File

    Size
  122. Very basic corelib No stdlib Semicolons Misc WTFs JavaScript Performance

    Debugging Ruby Compatibility Ruby WTFs Opal File Size
  123. Performance

  124. File Size

  125. opal.min.js =~ 259 kb opal.min.js.gz =~ 49 kb

  126. Debugging

  127. It’s just JavaScript

  128. Opal has source maps

  129. None
  130. None
  131. Ruby Compatibility

  132. Ruby compatibility • Mostly compatible with Ruby 2.0 • Tested

    against RubySpec • Implements most of the Ruby corelib • Implements some of the stdlib (e.g. Set)
  133. Notable differences • true and false are translated to JavaScript’s

    booleans • All numbers are JavaScript floats • Strings are immutable • Symbols are strings • No dynamic requires • No threads • No frozen objects • All methods are public
  134. Performance is key

  135. Performance Debugging Ruby Compatibility Ruby WTFs Opal Complexity

  136. Very basic corelib No stdlib Semicolons Misc WTFs JavaScript Complexity

    Performance Debugging Ruby Compatibility Ruby WTFs Opal Complexity
  137. Epic!!!

  138. Diving in

  139. opal-irb

  140. opal-rails

  141. opal-browser

  142. $document.ready do alert 'yo folks, I'm all loaded up in

    here' end $document.body.style.apply { background color: 'black' color 'white' font family: 'Verdana' } Browser::HTTP.get '/something.json' do on :success do |res| alert res.json.inspect end end
  143. opal-jquery

  144. Element.find('#header') Element.find('#navigation li:last') Document.ready? do alert 'document is ready to

    go!' end Element.find('#header').on :click do puts 'The header was clicked!' end
  145. opal-react

  146. opal-native

  147. None
  148. opal- activesupport

  149. And what about Volt?

  150. Volt Architecture

  151. MVC Controller View Model

  152. MVVM Controller/ViewModel View Model

  153. Volt is reactive

  154. Web Sockets FTW

  155. Components

  156. Universal

  157. Batteries Included

  158. <:Body> <h1>Todo List</h1> <form e-submit="add_todo" role="form"> <div class="form-group"> <label>Todo</label> <input

    class="form-control" type="text" value="{{ page._new_todo }}" /> </div> </form>
  159. def add_todo page._todos << { name: page._new_todo } page._new_todo =

    '' end
  160. <:Body> <h1>Todo List</h1> <table class="todo-table"> {{ page._todos.each do |todo| }}

    <tr> <td>{{ todo._name }}</td> </tr> {{ end }} </table>
  161. None
  162. Demo

  163. Volt’s not perfect • Opal isn’t quite there yet •

    MongoDB is the only supported datastore • Many features are work in progress • The documentation is kind of lacking
  164. Contribute to Volt!

  165. 0 25 50 75 100 1998 1999 2000 2001 2002

    2003 2004 2005 2006 2009 2011 2015
  166. 0 25 50 75 100 1998 1999 2000 2001 2002

    2003 2004 2005 2006 2009 2011 2015 2016
  167. Hell, yeah!!!

  168. Getting Started with Volt • Official docs (http://voltframework.com/ docs) •

    gitter • office hours • video tutorials • DataMelon blog (http://datamelon.io/blog/)
  169. Felina

  170. @bbatsov http://batsov.com http://emacsredux.com