Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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

More Decks by Adam Hawkins

Other Decks in Programming

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