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

1st class web development with lineman

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest. →
Avatar for Justin Searls Justin Searls
November 08, 2013

1st class web development with lineman

As was presented at Øredev 2013. This talk is more fun in video form: http://blog.testdouble.com/posts/2013-11-12-1st-class-web-development-with-lineman.html

Check out Lineman at http://linemanjs.com

Avatar for Justin Searls

Justin Searls

November 08, 2013

More Decks by Justin Searls

Other Decks in Programming

Transcript

  1. 1

  2. 1 2

  3. HTML UI ! app ├── controllers │ └── items_controller.rb ├──

    models │ └── item.rb └── views └── items └── index.html.erb
  4. HTML UI ! app ├── controllers │ └── items_controller.rb ├──

    models │ └── item.rb ├── views │ └── items │ └── index.html.erb └── assets └── javascripts └── application.js
  5. HTML UI + JS UI ! app ├── controllers │

    └── items_controller.rb ├── models │ └── item.rb ├── views │ └── items │ └── index.html.erb └── assets └── javascripts └── more_app ├── controllers │ └── items_controller.js ├── models │ └── item.js └── views └── items └── index.jst.ejs
  6. HTML UI + JS UI ! app ├── controllers │

    └── items_controller.rb ├── models │ └── item.rb ├── views │ └── items │ └── index.html.erb └── assets └── javascripts └── more_app ├── controllers │ └── items_controller.js ├── models │ └── item.js └── views └── items └── index.jst.ejs
  7. HTML UI + JS UI ! app ├── controllers │

    └── items_controller.rb ├── models │ └── item.rb ├── views │ └── items │ └── index.html.erb └── assets └── javascripts └── more_app ├── controllers │ └── items_controller.js ├── models │ └── item.js └── views └── items └── index.jst.ejs
  8. HTML UI + JS UI ! app ├── controllers │

    └── items_controller.rb ├── models │ └── item.rb ├── views │ └── items │ └── index.html.erb └── assets └── javascripts └── more_app ├── controllers │ └── items_controller.js ├── models │ └── item.js └── views └── items └── index.jst.ejs
  9. JSON API + JS UI ! app ├── controllers │

    └── items_controller.rb ├── models │ └── item.rb │ │ │ └── assets └── javascripts └── more_app ├── controllers │ └── items_controller.js ├── models │ └── item.js └── views └── items └── index.jst.ejs
  10. JSON API + JS UI ! app ├── controllers │

    └── items_controller.rb ├── models │ └── item.rb │ │ │ └── assets └── javascripts └── more_app ├── controllers │ └── items_controller.js ├── models │ └── item.js └── views └── items └── index.jst.ejs vestigial appendage
  11. ap

  12. ap

  13. When you see this: ! <script> user = <%= user.to_json

    %> time = <%= Time.now.to_i %> </script>
  14. When you see this: ! <script> user = <%= user.to_json

    %> time = <%= Time.now.to_i %> items = <%= items.to_json %> </script>
  15. When you see this: ! <script> user = <%= user.to_json

    %> time = <%= Time.now.to_i %> items = <%= items.to_json %> token = "<%= @token %>" </script>
  16. When you see this: ! <script> user = <%= user.to_json

    %> time = <%= Time.now.to_i %> items = <%= items.to_json %> token = "<%= @token %>" </script> your API is broken
  17. Do the Simplest Thing 1. Show data in a table

    2. Now render it as a graph
  18. Do the Simplest Thing 1. Show data in a table

    2. Now render it as a graph 3. (ͮŇ㷩㷩Ň)ͮ
  19. Do the Simplest Thing 1. Show data in a table

    2. Now render it as a graph 3. (ͮŇ㷩㷩Ň)ͮ 4. Now add filters, sliders, & zoom to the graph!
  20. Do the Simplest Thing 1. Show data in a table

    2. Now render it as a graph 3. (ͮŇ㷩㷩Ň)ͮ 4. Now add filters, sliders, & zoom to the graph! 5. (ಠ_ಠ)
  21. Rails Rails Railsy Rake App Framework Convention & Config Build

    Automation Backbone Ember Angular ᵇ(´-ʆ)ᵃ

  22. Rails Rails Railsy Rake App Framework Convention & Config Build

    Automation Grunt (Node.js) Backbone Ember Angular ᵇ(´-ʆ)ᵃ

  23. Rails Rails Railsy Rake App Framework Convention & Config Build

    Automation Grunt (Node.js) Lineman Backbone Ember Angular ᵇ(´-ʆ)ᵃ

  24. ;?

  25. Easy peasy ! $ cat tasks/hello.js ! module.exports = function(grunt)

    { grunt.registerTask("hello",function(){ }); };
  26. Easy peasy ! $ cat tasks/hello.js ! module.exports = function(grunt)

    { grunt.registerTask("hello",function(){ grunt.log.writeln("Hello!"); }); };
  27. Easy peasy ! $ grunt hello ! Running "hello" task

    Hello! ! Done, without errors.
  28. hi() code % save loadTask = (module) -> if fs.existsSync("#{process.cwd()}/node_modules/#{module}")

    grunt.loadNpmTasks(module) else grunt.loadTasks("#{__dirname}/../node_modules/#{module}/ tasks") npmTasks = grunt.util._(linemanNpmTasks).chain(). union("grunt-contrib-sass" if config.enableSass). union(config.loadNpmTasks). compact().value() loadTask task for task in npmTasks grunt.renameTask "copy", "images" loadTask "grunt-contrib-copy" # load again so webfonts can use it grunt.renameTask "copy", "webfonts" loadTask "grunt-contrib-copy" # load again to make available in userland compile
  29. hi() code % save loadTask = (module) -> if fs.existsSync("#{process.cwd()}/node_modules/#{module}")

    grunt.loadNpmTasks(module) else grunt.loadTasks("#{__dirname}/../node_modules/#{module}/ tasks") npmTasks = grunt.util._(linemanNpmTasks).chain(). union("grunt-contrib-sass" if config.enableSass). union(config.loadNpmTasks). compact().value() loadTask task for task in npmTasks grunt.renameTask "copy", "images" loadTask "grunt-contrib-copy" # load again so webfonts can use it grunt.renameTask "copy", "webfonts" loadTask "grunt-contrib-copy" # load again to make available in userland compile loadTask task for task in npmTasks grunt.renameTask "copy", "images" loadTask "grunt-contrib-copy" # load again so webfonts can use it grunt.renameTask "copy", "webfonts" loadTask "grunt-contrib-copy" # load again to make available in userland loadTask = (module) -> if fs.existsSync("#{process.cwd()}/node_modules/#{module}") grunt.loadNpmTasks(module) else grunt.loadTasks("#{__dirname}/../node_modules/#{module}/tasks") npmTasks = grunt.util._(linemanNpmTasks).chain(). union("grunt-contrib-sass" if config.enableSass). union(config.loadNpmTasks). compact().value() concat
  30. hi() code % save loadTask = (module) -> if fs.existsSync("#{process.cwd()}/node_modules/#{module}")

    grunt.loadNpmTasks(module) else grunt.loadTasks("#{__dirname}/../node_modules/#{module}/ tasks") npmTasks = grunt.util._(linemanNpmTasks).chain(). union("grunt-contrib-sass" if config.enableSass). union(config.loadNpmTasks). compact().value() loadTask task for task in npmTasks grunt.renameTask "copy", "images" loadTask "grunt-contrib-copy" # load again so webfonts can use it grunt.renameTask "copy", "webfonts" loadTask "grunt-contrib-copy" # load again to make available in userland compile loadTask task for task in npmTasks grunt.renameTask "copy", "images" loadTask "grunt-contrib-copy" # load again so webfonts can use it grunt.renameTask "copy", "webfonts" loadTask "grunt-contrib-copy" # load again to make available in userland loadTask = (module) -> if fs.existsSync("#{process.cwd()}/node_modules/#{module}") grunt.loadNpmTasks(module) else grunt.loadTasks("#{__dirname}/../node_modules/#{module}/tasks") npmTasks = grunt.util._(linemanNpmTasks).chain(). union("grunt-contrib-sass" if config.enableSass). union(config.loadNpmTasks). compact().value() concat hello world! play
  31. < 100ms hi() code % save loadTask = (module) ->

    if fs.existsSync("#{process.cwd()}/node_modules/#{module}") grunt.loadNpmTasks(module) else grunt.loadTasks("#{__dirname}/../node_modules/#{module}/ tasks") npmTasks = grunt.util._(linemanNpmTasks).chain(). union("grunt-contrib-sass" if config.enableSass). union(config.loadNpmTasks). compact().value() loadTask task for task in npmTasks grunt.renameTask "copy", "images" loadTask "grunt-contrib-copy" # load again so webfonts can use it grunt.renameTask "copy", "webfonts" loadTask "grunt-contrib-copy" # load again to make available in userland compile loadTask task for task in npmTasks grunt.renameTask "copy", "images" loadTask "grunt-contrib-copy" # load again so webfonts can use it grunt.renameTask "copy", "webfonts" loadTask "grunt-contrib-copy" # load again to make available in userland loadTask = (module) -> if fs.existsSync("#{process.cwd()}/node_modules/#{module}") grunt.loadNpmTasks(module) else grunt.loadTasks("#{__dirname}/../node_modules/#{module}/tasks") npmTasks = grunt.util._(linemanNpmTasks).chain(). union("grunt-contrib-sass" if config.enableSass). union(config.loadNpmTasks). compact().value() concat hello world! play
  32. < 100ms hi() code % save loadTask = (module) ->

    if fs.existsSync("#{process.cwd()}/node_modules/#{module}") grunt.loadNpmTasks(module) else grunt.loadTasks("#{__dirname}/../node_modules/#{module}/ tasks") npmTasks = grunt.util._(linemanNpmTasks).chain(). union("grunt-contrib-sass" if config.enableSass). union(config.loadNpmTasks). compact().value() loadTask task for task in npmTasks grunt.renameTask "copy", "images" loadTask "grunt-contrib-copy" # load again so webfonts can use it grunt.renameTask "copy", "webfonts" loadTask "grunt-contrib-copy" # load again to make available in userland compile loadTask task for task in npmTasks grunt.renameTask "copy", "images" loadTask "grunt-contrib-copy" # load again so webfonts can use it grunt.renameTask "copy", "webfonts" loadTask "grunt-contrib-copy" # load again to make available in userland loadTask = (module) -> if fs.existsSync("#{process.cwd()}/node_modules/#{module}") grunt.loadNpmTasks(module) else grunt.loadTasks("#{__dirname}/../node_modules/#{module}/tasks") npmTasks = grunt.util._(linemanNpmTasks).chain(). union("grunt-contrib-sass" if config.enableSass). union(config.loadNpmTasks). compact().value() concat hello world! play
  33. hi() code % save loadTask = (module) -> if fs.existsSync("#{process.cwd()}/node_modules/#{module}")

    grunt.loadNpmTasks(module) else grunt.loadTasks("#{__dirname}/../node_modules/#{module}/ tasks") npmTasks = grunt.util._(linemanNpmTasks).chain(). union("grunt-contrib-sass" if config.enableSass). union(config.loadNpmTasks). compact().value() loadTask task for task in npmTasks grunt.renameTask "copy", "images" loadTask "grunt-contrib-copy" # load again so webfonts can use it grunt.renameTask "copy", "webfonts" loadTask "grunt-contrib-copy" # load again to make available in userland compile loadTask task for task in npmTasks grunt.renameTask "copy", "images" loadTask "grunt-contrib-copy" # load again so webfonts can use it grunt.renameTask "copy", "webfonts" loadTask "grunt-contrib-copy" # load again to make available in userland loadTask = (module) -> if fs.existsSync("#{process.cwd()}/node_modules/#{module}") grunt.loadNpmTasks(module) else grunt.loadTasks("#{__dirname}/../node_modules/#{module}/tasks") npmTasks = grunt.util._(linemanNpmTasks).chain(). union("grunt-contrib-sass" if config.enableSass). union(config.loadNpmTasks). compact().value() concat test < 100ms
  34. ! $ lineman build ! $ tree dist ! dist

    ├── css │ └── app.css ├── index.html └── js └── app.js
  35. Add a dependency ! $ npm install --save-dev grunt-typescript !

    $ cat package.json ... "devDependencies": { ... "grunt-typescript": "0.1.6" }
  36. ! loadNpmTasks: ['grunt-typescript'], ! prependTasks: { common: ['typescript'] }, !

    typescript: { compile: { src: 'app/js/**/*.ts', dest: 'generated/js/app.ts.js' } } config/application.js
  37. ! $ lineman run ! ... Running "typescript:compile" (typescript) task

    js: 0 files, map: 0 files, declaration: 0 files ... ! Run the task
  38. noun project attribution Yarn designed by Marie Coons from The

    Noun Project! ! Scale designed by Ritika Khasgiwale from The Noun Project! ! Business Man designed by Piotrek Chuchla from The Noun Project! ! Business Man designed by Toke Thieden from The Noun Project! ! Airplane designed by Sven Gabriel from The Noun Project! ! Brick Wall designed by Juan Pablo Bravo from The Noun Project