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

Painless Javascript Development

Painless Javascript Development

How to seriously level up your JS development using Iridium. Presented in totally awesome and wonder Helsinki for @HelsinkiJS

Adam Hawkins

August 29, 2012
Tweet

More Decks by Adam Hawkins

Other Decks in Programming

Transcript

  1. Painless Javascript
    Development*
    *Almost
    Made with Love for Helsinki JS

    View Slide

  2. var Me = { };
    • Adam Hawkins
    • @adman65
    • https://github.com/twinturbo
    • https://speakerdeck.com/u/twinturbo
    • Lead Code Monkey at Radium
    • Primarily Ruby guy, now focused on JS &
    Ember

    View Slide

  3. Build an ambitious
    app in complete isolation

    View Slide

  4. View Slide

  5. View Slide

  6. Jesus Christ.
    This is Hard.

    View Slide

  7. “If you want to make a JS
    app from scratch, you must
    first create the universe.”
    - Carl Sagan on modern JS development

    View Slide

  8. Our Javascript Universe
    1. Figure out how to split code into multiple files and
    deliver it as a single file
    2. Do #1 while using Coffeescript, SCSS, and friends
    3. Do #1 and #2 while being able to hit Refresh in the
    browser
    4. Do #1, #2 and #3 while supporting different
    environments (dev, test, production, staging)
    5. Do #1, #2, #3, and #4 while doing TDD
    6. Do all of the above without creating an HTML files
    7. Think of all the tools you need to do any of these...

    View Slide

  9. Let’s Make a Universe

    View Slide

  10. $ iridium app todos
    create app
    create app/images
    create app/javascripts/app.coffee
    create app/javascripts/boot.coffee
    create app/javascripts/models
    create app/javascripts/views
    create app/javascripts/controllers
    create app/javascripts/templates
    create app/initializers
    create app/locales/en.yml
    create app/public
    create app/public/index.html.erb
    create app/stylesheets/app.scss
    create app/vendor/javascripts
    create app/vendor/javascripts/handlebars.js
    create app/vendor/javascripts/jquery.js
    create app/vendor/javascripts/minispade.js
    create app/vendor/javascripts/i81n.js
    create app/vendor/stylesheets
    create site
    create test
    create test/integration/navigation_test.coffee
    create test/unit/truth_test.coffee
    create test/models
    create test/views
    create test/controllers
    create test/templates
    create test/support/sinon.js
    create application.rb

    View Slide

  11. That’s Quick Universe
    • New skeleton generated for us
    • Born from enterprise Ember requirements,
    but not framework specific
    • Integration and unit tests ready
    • jQuery, Handlebars, Qunit, and Sinon
    preloaded
    • Let’s build something

    View Slide

  12. Red, Green, Refactor

    View Slide

  13. # test/integration/hello_test.coffee
    # straight up javascript - runs in any browser
    test "the app says hello", ->
    # Direct access to app code
    Todos.reset()
    Todos.userName = 'Adam'
    Todos.boot()
    assertEqual $("hello-world").text, "Adam"

    View Slide

  14. $ iridium test test/integration/hello_test.coffee
    Run options: --seed 17630
    # Running Tests:
    F
    1 Test(s), 1 Assertion(s), 0 Passed, 0 Error(s), 1 Failure(s)
    test/integration/hello_test.coffee: App says hello
    Cannot call “text” on “undefined”

    View Slide

  15. Wait ... How?
    • CasperJS + PhantomJS + a bunch of h4x
    • Make your app available
    • Inject any test env specific code
    • Yes that is a full stack integration test
    • Great, it fails. Let’s keep going

    View Slide

  16. Now We Must Code

    View Slide

  17. ... But We Need Things

    View Slide

  18. # application.rb
    class Todos < Iridium::Application
    # Dependency Management
    config.load :minispade
    config.load :jquery
    config.load :handlebars
    config.load :ember # added
    end

    View Slide

  19. Now, We Code

    View Slide

  20. // app.coffee - 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

    View Slide

  21. // boot.coffee - require app and start it
    require ‘todos/app’
    Todos.initialize()

    View Slide

  22. That’s Not Vanilla JS
    • Minispade to require files
    • Module names generated from file names
    • Can be Coffeescript or Javascript
    • All files compiled into a single application.js
    • Let’s what our app looks like...

    View Slide

  23. $ cd 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
    ... now hit Refresh

    View Slide

  24. • We haven’t written any HTML
    • We haven’t needed to configure how load
    our code
    • We’ve run a full stack integration test
    without any configuration
    • ... But we have no functionality
    So Far...

    View Slide

  25. TDD w/Unit Testing

    View Slide

  26. # test/models/todo_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"

    View Slide

  27. $ be iridium test test/models/todo_test.coffee
    Run options: --seed 14903
    # Running Tests:
    EEE
    3 Test(s), 3 Assertion(s), 0 Passed, 3 Error(s), 3 Failure(s)
    should default to not done
    TypeError: 'undefined' is not an object (evaluating 'Models.todo.get')
    # Backtrace
    /Users/adam/radium/iridium_tests/todos/test/support/qunit.js:340
    /unit/models/todo_test.coffee:17
    /unit/models/todo_test.coffee:29
    should set todo title
    TypeError: 'undefined' is not an object (evaluating 'Models.todo.set')
    # Backtrace
    /Users/adam/radium/iridium_tests/todos/test/support/qunit.js:340
    /unit/models/todo_test.coffee:22
    /unit/models/todo_test.coffee:29
    should be able to complete
    TypeError: 'undefined' is not an object (evaluating 'Models.todo.set')
    # Backtrace
    /Users/adam/radium/iridium_tests/todos/test/support/qunit.js:340
    /unit/models/todo_test.coffee:27
    /unit/models/todo_test.coffee:29

    View Slide

  28. What is this Trickery?

    View Slide

  29. 1. Ensure we have the correct code is there
    2. Make an HTML file
    3. Add a tag for QUnit<br/>4. Write <script> tags for support files<br/>5. Add a <script> tag for our test(s)<br/>6. Opens the HTML file using a browser<br/>7. Verify results<br/>It’s All the Stuff You<br/>Used to Do<br/>

    View Slide

  30. Headless with
    PhantomJS
    • Open your app with your app code loaded
    • Inject test framework
    • Inject support code
    • Inject tests in Coffeescript or JS
    • Run a single test file
    • Repeat for all test files

    View Slide

  31. Integrated Test Runner
    • Execute individual tests from the CLI
    • Unified runner for integration and unit
    tests
    • QUnit by default, Jasmine support possible
    • File in test/support/**/*.{js,coffee}
    automatically loaded for you
    • Report test results in real time
    • Individual test files completely isolated

    View Slide

  32. $ iridium test
    Run options: --seed 35635
    # Running Tests:
    ..................................
    34 Test(s), 33 Assertion(s), 34 Passed, 0
    Error(s), 0 Failure(s)

    View Slide

  33. Tests Pass, Time to Deploy
    • Need to compile everything to a static
    directory
    • Various build steps in involved
    • How do we do this?

    View Slide

  34. $ iridium compile # production
    $ iridium compile build/path
    $ iridium compile -e staging

    View Slide

  35. Coffeescript
    Concatenation
    Minification
    GZip
    application.js | application.jz.gz

    View Slide

  36. Rake::Pipeline
    • Enter Rake::Pipeline
    • It’s a series of tubes
    • Input files mapped to output files
    • It can do everything we need

    View Slide

  37. Rake::Pipeline.build
    input "app"
    output "site"
    match "javascripts/**/*.coffee" do
    coffeescript
    end
    match "stylesheets/**/*.scss" do
    scss
    end
    match "**/*.js" do
    concat "application.js"
    uglify if production?
    end
    match "**/*.css" do
    concat "application.css"
    yui_css if production?
    end
    end

    View Slide

  38. $ iridium generate rackup
    $ git add -A
    $ git commit -m “Deployable”
    $ git push heroku master
    $ heroku open # goliath online!

    View Slide

  39. That’s Iridium

    View Slide

  40. It’s like Yeoman, but ya
    know, available now
    without private beta.
    This is open source
    right?
    http://yeoman.io/

    View Slide

  41. git clone git://github.com/
    radiumsoftware/iridium.git

    View Slide

  42. Iridium - Architecture
    • Convention over Configuration
    • Rake::Pipeline to compile, compress, and minify all
    application files into a single static directory
    • Test runner built on top of PhantomJS and
    CasperJS
    • Served through a custom middleware stack ending
    with Rack::Directory in development and
    production ... or
    • Serve with any language or webserver (Apache/
    Nginx) in production

    View Slide

  43. Fun Facts
    • Generates an HTML5 cache manifest
    • Works with Gaurd (modify a file, run its tests)
    • $ iridium lint
    • Proxies available to get around CORS or hide
    authentication tokens from Javascript
    • Use your own Assetfile if you like
    • i18n support built in
    • Automatically caches assets in production

    View Slide

  44. What’s Next
    • $ gem install iridium-ember
    • $ iridium deploy:cloudflare
    • $ iridium deploy:heroku
    • $ iridium test -b safari
    • $ iridium test -b IE7
    • ES6 Polyfill build step

    View Slide

  45. Want More?
    • http://www.thesoftwaresimpleton.com/
    blog/2012/08/10/iridium/ by @dagda1
    • https://github.com/radiumsoftware/iridium

    View Slide

  46. Who’s Confused?

    View Slide