1st class web development with lineman

E6c6e133e74c3b83f04d2861deaa1c20?s=47 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

E6c6e133e74c3b83f04d2861deaa1c20?s=128

Justin Searls

November 08, 2013
Tweet

Transcript

  1. 4.

    1

  2. 5.

    1 2

  3. 6.
  4. 7.
  5. 21.
  6. 25.
  7. 29.
  8. 30.
  9. 36.
  10. 38.
  11. 42.

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

    models │ └── item.rb └── views └── items └── index.html.erb
  12. 43.

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

    models │ └── item.rb ├── views │ └── items │ └── index.html.erb └── assets └── javascripts └── application.js
  13. 44.

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

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

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

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

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

    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
  19. 51.
  20. 52.
  21. 53.
  22. 54.
  23. 55.

    ap

  24. 56.

    ap

  25. 57.
  26. 62.
  27. 63.
  28. 64.
  29. 66.
  30. 67.
  31. 68.
  32. 69.
  33. 70.
  34. 71.
  35. 72.
  36. 77.

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

    %> time = <%= Time.now.to_i %> </script>
  37. 78.

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

    %> time = <%= Time.now.to_i %> items = <%= items.to_json %> </script>
  38. 79.

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

    %> time = <%= Time.now.to_i %> items = <%= items.to_json %> token = "<%= @token %>" </script>
  39. 80.

    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
  40. 81.
  41. 83.
  42. 85.
  43. 94.
  44. 97.

    Do the Simplest Thing 1. Show data in a table

    2. Now render it as a graph
  45. 98.

    Do the Simplest Thing 1. Show data in a table

    2. Now render it as a graph 3. (ͮŇ㷩㷩Ň)ͮ
  46. 99.

    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!
  47. 100.

    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. (ಠ_ಠ)
  48. 107.
  49. 108.
  50. 109.
  51. 118.

    Rails Rails Railsy Rake App Framework Convention & Config Build

    Automation Backbone Ember Angular ᵇ(´-ʆ)ᵃ

  52. 119.

    Rails Rails Railsy Rake App Framework Convention & Config Build

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

  53. 120.

    Rails Rails Railsy Rake App Framework Convention & Config Build

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

  54. 123.
  55. 124.
  56. 125.
  57. 126.
  58. 127.
  59. 128.
  60. 129.
  61. 130.
  62. 131.
  63. 132.
  64. 133.
  65. 134.
  66. 135.
  67. 136.
  68. 137.
  69. 138.

    ;?

  70. 139.
  71. 142.
  72. 143.
  73. 147.

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

    { grunt.registerTask("hello",function(){ }); };
  74. 148.

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

    { grunt.registerTask("hello",function(){ grunt.log.writeln("Hello!"); }); };
  75. 150.

    Easy peasy ! $ grunt hello ! Running "hello" task

    Hello! ! Done, without errors.
  76. 151.
  77. 152.
  78. 154.
  79. 158.
  80. 159.
  81. 169.
  82. 178.
  83. 180.
  84. 181.
  85. 188.
  86. 189.
  87. 191.

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

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

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

    < 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
  91. 195.
  92. 196.

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

    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
  94. 198.
  95. 202.

    ! $ lineman build ! $ tree dist ! dist

    ├── css │ └── app.css ├── index.html └── js └── app.js
  96. 215.

    Add a dependency ! $ npm install --save-dev grunt-typescript !

    $ cat package.json ... "devDependencies": { ... "grunt-typescript": "0.1.6" }
  97. 218.

    ! loadNpmTasks: ['grunt-typescript'], ! prependTasks: { common: ['typescript'] }, !

    typescript: { compile: { src: 'app/js/**/*.ts', dest: 'generated/js/app.ts.js' } } config/application.js
  98. 219.

    ! $ lineman run ! ... Running "typescript:compile" (typescript) task

    js: 0 files, map: 0 files, declaration: 0 files ... ! Run the task
  99. 221.
  100. 223.

    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