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

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. 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
  2. “If you want to make a JS app from scratch,

    you must first create the universe.” - Carl Sagan on modern JS development
  3. 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...
  4. $ 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
  5. 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
  6. # 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"
  7. $ 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”
  8. 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
  9. # application.rb class Todos < Iridium::Application # Dependency Management config.load

    :minispade config.load :jquery config.load :handlebars config.load :ember # added end
  10. // 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
  11. 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...
  12. $ 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
  13. • 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...
  14. # 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"
  15. $ 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
  16. 1. Ensure we have the correct code is there 2.

    Make an HTML file 3. Add a <script> tag for QUnit 4. Write <script> tags for support files 5. Add a <script> tag for our test(s) 6. Opens the HTML file using a browser 7. Verify results It’s All the Stuff You Used to Do
  17. 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
  18. 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
  19. $ iridium test Run options: --seed 35635 # Running Tests:

    .................................. 34 Test(s), 33 Assertion(s), 34 Passed, 0 Error(s), 0 Failure(s)
  20. Tests Pass, Time to Deploy • Need to compile everything

    to a static directory • Various build steps in involved • How do we do this?
  21. Rake::Pipeline • Enter Rake::Pipeline • It’s a series of tubes

    • Input files mapped to output files • It can do everything we need
  22. 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
  23. $ iridium generate rackup $ git add -A $ git

    commit -m “Deployable” $ git push heroku master $ heroku open # goliath online!
  24. It’s like Yeoman, but ya know, available now without private

    beta. This is open source right? http://yeoman.io/
  25. 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
  26. 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
  27. 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