Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

Build an ambitious app in complete isolation

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

Jesus Christ. This is Hard.

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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...

Slide 9

Slide 9 text

Let’s Make a Universe

Slide 10

Slide 10 text

$ 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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

Red, Green, Refactor

Slide 13

Slide 13 text

# 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"

Slide 14

Slide 14 text

$ 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”

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

Now We Must Code

Slide 17

Slide 17 text

... But We Need Things

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

Now, We Code

Slide 20

Slide 20 text

// 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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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...

Slide 23

Slide 23 text

$ 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

Slide 24

Slide 24 text

• 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...

Slide 25

Slide 25 text

TDD w/Unit Testing

Slide 26

Slide 26 text

# 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"

Slide 27

Slide 27 text

$ 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

Slide 28

Slide 28 text

What is this Trickery?

Slide 29

Slide 29 text

1. Ensure we have the correct code is there 2. Make an HTML file 3. Add a 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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

That’s Iridium

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

Who’s Confused?