Using Ruby for Integrated Javascript Development: Introducing Iridium

Using Ruby for Integrated Javascript Development: Introducing Iridium

There are many problems doing modern javascript development. Its hard to get up and running, it's hard to organize code. It's hard to do a lot of things. I show you how we created an integrated solution using ruby to make developing complete JS applications so much easier.

I presented this at @cgnjs (Cologne JS) in Germany.

94378c403019af23a28b08447a34b8e0?s=128

Adam Hawkins

August 14, 2012
Tweet

Transcript

  1. Using Ruby for Integrated Javascript Development Introducing Iridium Wednesday, August

    15, 12
  2. var Me = { }; • Ich heiße Adam Hawkins

    • @adman65 • https://github.com/twinturbo • Lead Code Monkey at Radium • Primarily Ruby guy, now focused on JS Wednesday, August 15, 12
  3. Goal: Build an Ambitious Ember App Wednesday, August 15, 12

  4. Ambitious (n) / Ambitioniert (h) • Organized: Directory structure reflects

    code’s responsibility • Testable: Headless and Automated • Compilable: Coffeescript, Handlebars, and SCSS • Reloadable: Develop in the Browser • Completely separate from any other code. Separate repos. Separate servers. Separate everything--allow per project optimizations. Wednesday, August 15, 12
  5. • We all have our own native language • Independent

    frontend and backend • We meet at the API • More frontend guys then backend guys Our Team Wednesday, August 15, 12
  6. Our Tools Wednesday, August 15, 12

  7. Javascript ... Verdammt Wednesday, August 15, 12

  8. • How can we write our code in Coffeescript? •

    How can we write our CSS in SCSS? • How can we organize & require our code? • How can we unit test? • How can we run integration tests? Wednesday, August 15, 12
  9. Hard Problems mit Lösungen Wednesday, August 15, 12

  10. • Organized code has boundaries • Organized code is reusable

    • Organized code is split into many source files • Organized code can be required or imported • Now you’re thinking.... Organization ... lolwut Wednesday, August 15, 12
  11. thought = "I’ll just use #{[ "commonjs", "AMD", "requirejs", "E6

    Modules" ].rand}!" Wednesday, August 15, 12
  12. Code Loading Comparison Language Example Uses HTML C #include<stdio.h> No

    :) Ruby require ‘socket’ No :) Python import fibo No :) JavaScript <script src=”foo.js”></script> Yes :( Wednesday, August 15, 12
  13. Solutions ? • Accept it sucks & use a module

    loader • Wait for ES6 Modules. This will only take 5 lifetimes. • Use a Polyfill • Approach the problem from a new angle Wednesday, August 15, 12
  14. Loading JS: Minispade • <script> tags...<script> tag’s everywhere • Works

    when you have a small number of files • Blows up when you have hundreds or thousands • Use Minispade to wrap all individual source files in functions and dump them into a single file during compilation Wednesday, August 15, 12
  15. Compilation Wednesday, August 15, 12

  16. $ cat **/*.coffee | coffescript > application.js Wednesday, August 15,

    12
  17. That Was Easy Right? • ... but I need to

    combine them into one file • ... but I need to load extra JS depending on environment (test/development/production) • ... but I want to minify it in production • ... but I only want something when I’m developing • ... but what about images and other assets? Wednesday, August 15, 12
  18. Coffeescript Concatenation Minification Compression application.js Wednesday, August 15, 12

  19. Rake::Pipeline • I know Ruby. Let’s use Rake::Pipeline to compile

    the application • It’s a series of tubes • Input files mapped to output files • It can do everything we need Wednesday, August 15, 12
  20. Rake::Pipeline.build input "app" output "site" match "javascripts/**/*.coffee" do coffeescript end

    match "stylesheets/**/*.scss" do scss end match "**/*.js" do contact "application.js" uglify if production? end match "**/*.css" do contact "application.css" yui_css if production? end end Wednesday, August 15, 12
  21. What About Red, Green, Refactor? Wednesday, August 15, 12

  22. // simplest possible test test("true", function() { ok(true, "True is

    true"); }); Let’s just fire this test up... Wednesday, August 15, 12
  23. 1. Ensure we have the correct application.js loadable 2. Make

    an HTML file 3. Add a <script> tag for qunit 4. Add a <script> tag for our test(s) 5. Write <script> tags for any other files we need 6. Human opens the HTML file using a browser 7. Human verifies results After We Do All This: Wednesday, August 15, 12
  24. Integration Tests • Use a server to serve and boot

    the app • Use something to simulate user activity...no seriously what do you use? • Report Results Wednesday, August 15, 12
  25. What’s the Problem • We need HTML (this makes me

    sad) • Humans are involved • No unified test runner from the command line • How does this process map to CI? • Hard to run individual tests Wednesday, August 15, 12
  26. #77 - Iridium (It’s an Element) Wednesday, August 15, 12

  27. Iridium: Dev Faster • Unified test runner for integration and

    unit tests -- all from CLI • Sensible defaults for asset compilation with Rake::Pipeline • Code “modularization” with Minispade • Configurable based on environment (development, test, production) • Make it all work seamlessly Wednesday, August 15, 12
  28. Architecture • Written in Ruby & designed for Javascript •

    Rake::Pipeline for asset compilation • PhantomJS, CasperJS + Patches for automated tests • Minispade for JS module loading • Preload jQuery and Handlebars • Preload Qunit and Sinon for testing • Not framework specific. Can use Ember, Backbone, etc Wednesday, August 15, 12
  29. $ cd projects/todos $ iridium server >> Thin web server

    (v1.4.1 codename Chromeo) >> Maximum connections set to 1024 >> Listening on 0.0.0.0:9292, CTRL+C to stop Relodable ... now hit Refresh Wednesday, August 15, 12
  30. // app.js - loads all the code Todos = Ember.Application.create({

    VERSION: '1.0', storeNamespace: 'todos-emberjs', }); require('todos/router'); // app/javascripts/router.js|coffee require('todos/models'); // app/javascripts/models.js|coffee require('todos/controllers'); // you get require('todos/views'); // the point require('todos/templates'); // by now Organized Wednesday, August 15, 12
  31. $ iridium test Testable Wednesday, August 15, 12

  32. $ iridium test integration/todo.coffee # integration test with CasperJS #

    test/integration/todo.coffee casper.start 'http://localhost:7777/', -> @test.assertExists('#new-todo', 'todo form found') casper.run -> @test.done() Fullstack Tests Wednesday, August 15, 12
  33. $ iridium test test/model_test.coffee # test/models_test.coffee test "should default to

    not done", -> equal Models.todo.get('isDone'), false, "todo is not done" test "should set todo title", -> Models.todo.set 'title', "A todo" equal Models.todo.get('title'), "A todo", "todo title is set" test "should be able to signify isdone", -> Models.todo.set 'isDone', true ok Models.todo.get('isDone'), "Todo is done" Unit Tests Wednesday, August 15, 12
  34. class Todos < Iridium::Application config.load :minispade config.load :jquery config.load :handlebars

    config.load :ember end Dependency Management Wednesday, August 15, 12
  35. $ iridium compile # production $ iridium compile ENV=staging Compilable

    Wednesday, August 15, 12
  36. $ iridium lint If You Have OCD Wednesday, August 15,

    12
  37. github.com/ radiumsoftware/iridium git clone Wednesday, August 15, 12