$30 off During Our Annual Pro Sale. View Details »

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.

Adam Hawkins

August 14, 2012
Tweet

More Decks by Adam Hawkins

Other Decks in Programming

Transcript

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

    View Slide

  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

    View Slide

  3. Goal: Build an
    Ambitious Ember App
    Wednesday, August 15, 12

    View Slide

  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

    View Slide

  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

    View Slide

  6. Our Tools
    Wednesday, August 15, 12

    View Slide

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

    View Slide

  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

    View Slide

  9. Hard Problems mit
    Lösungen
    Wednesday, August 15, 12

    View Slide

  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

    View Slide

  11. thought = "I’ll just
    use #{[
    "commonjs",
    "AMD",
    "requirejs",
    "E6 Modules"
    ].rand}!"
    Wednesday, August 15, 12

    View Slide

  12. Code Loading
    Comparison
    Language Example Uses HTML
    C #include No :)
    Ruby require ‘socket’ No :)
    Python import fibo No :)
    JavaScript Yes :(
    Wednesday, August 15, 12

    View Slide

  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

    View Slide

  14. Loading JS: Minispade
    • tags...<script> tag’s everywhere<br/>• Works when you have a small number of<br/>files<br/>• Blows up when you have hundreds or<br/>thousands<br/>• Use Minispade to wrap all individual source<br/>files in functions and dump them into a<br/>single file during compilation<br/>Wednesday, August 15, 12<br/>

    View Slide

  15. Compilation
    Wednesday, August 15, 12

    View Slide

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

    View Slide

  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

    View Slide

  18. Coffeescript
    Concatenation
    Minification
    Compression
    application.js
    Wednesday, August 15, 12

    View Slide

  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

    View Slide

  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

    View Slide

  21. What About Red,
    Green, Refactor?
    Wednesday, August 15, 12

    View Slide

  22. // simplest possible test
    test("true", function() {
    ok(true, "True is true");
    });
    Let’s just fire this test up...
    Wednesday, August 15, 12

    View Slide

  23. 1. Ensure we have the correct application.js loadable
    2. Make an HTML file
    3. Add a tag for qunit<br/>4. Add a <script> tag for our test(s)<br/>5. Write <script> tags for any other files we need<br/>6. Human opens the HTML file using a browser<br/>7. Human verifies results<br/>After We Do All This:<br/>Wednesday, August 15, 12<br/>

    View Slide

  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

    View Slide

  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

    View Slide

  26. #77 - Iridium
    (It’s an Element)
    Wednesday, August 15, 12

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  31. $ iridium test
    Testable
    Wednesday, August 15, 12

    View Slide

  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

    View Slide

  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

    View Slide

  34. class Todos < Iridium::Application
    config.load :minispade
    config.load :jquery
    config.load :handlebars
    config.load :ember
    end
    Dependency Management
    Wednesday, August 15, 12

    View Slide

  35. $ iridium compile # production
    $ iridium compile ENV=staging
    Compilable
    Wednesday, August 15, 12

    View Slide

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

    View Slide

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

    View Slide