JSConf US 2014: Building Isomorphic Apps

  • Published on
    10-May-2015

  • View
    2.664

  • Download
    0

DESCRIPTION

Slides from Spike Brehm's talk at JSConf US 2014. Topics include the etymology of "Isomorphic JavaScript", examples is isomorphic apps in the wild, reasons behind the growing trend towards isomorphic apps, and how to build an isomorphic module using Browserify & NPM.

Transcript

  • 1.Building Isomorphic Apps Spike Brehm @spikebrehm

2. @spikebrehm @AirbnbNerds Spike Brehm 3. Isomorphic JavaScript. 4. WTF is Isomorphic JavaScript? 5. JavaScript code that can be shared between environments. 6. JavaScript code that can be shared between environments. 7. JavaScript code that can be shared between environments. 8. JavaScript code that can be shared between environments. 9. Backend Ruby Python Java PHP Node.js Persistence Client JavaScript Shared JavaScript DOM manipulation UX View layer Application logic Routing 10. Etymology of Isomorphic JavaScript. 11. adjective corresponding or similar in form and relations. isomorphic 12. isomorphic formsame 13. http://blog.nodejitsu.com/scaling-isomorphic-javascript-code/ 14. monomorphic heteromorphic homomorphic polymorphic Youre using it wrong! 15. Isomorphic JavaScript in the wild. 16. Flickr 17. Flickr 18. ! Yahoos Modown libraries (successor to Mojito). Flickr 19. Instagram* 20. Instagram* 21. ! Facebooks React library in a Django app. Instagram* 22. Airbnb Mobile 23. Airbnb Mobile 24. ! Airbnbs Rendr library, built on Backbone and Express. Airbnb Mobile 25. Asana 26. ! Entire App runtime synced between client & server. Asana 27. Meteor 28. ! Realtime app framework. Meteor 29. Wy go to the trouble? 30. Initial pageload speed. Performance Crawlable single-page apps. SEO* Reduce code duplication. Maintainability Run code anywhere. Flexibility 31. Isomorphic use cases. 32. Templating I18n Date & currency formatting Application logic Routing Model validation API interaction ...? Isomorphic use cases. 33. Isomorphic JavaScript is a spectrum. 34. Entire view layer and app logic shared Small bits of view layer or logic shared 35. Many abstractions Few abstractions 36. View layer shared Entire app runtime synced between client & server 37. Isomorphic JavaScript can be or shimmed per environment . environment- agnostic 38. Does not depend on browser-specic properties (window) or server-specic properties (process.env, req.cookies). Environment-agnostic 39. Example: Handlebars.js var template = ! '

  • ' ! '{{#each posts}}' ! '
  • {{title}}' ! '{{/each}}' ! '

'! ;! ! var templateFn = Handlebars.compile(template)! , html = templateFn({posts: posts}); 40. Provide shims for accessing environment-specic properties so module can expose a single API. window.location.pathname vs. req.path Shimmed per environment 41. Example: Superagent superagent! .get('/api/posts.json')! .end(function(res) {! if (res.status === 200) {! console.log("Posts:", res.body);! } else {! console.error("Error");! }! }); 42. Abstractions. 43. Abstraction: User Agent Client navigator.userAgent Server req.get('user-agent') 44. Abstraction: Cookies Client document.cookie =! 'myCookie=1; Domain=.example.org'; Server res.setHeader(! 'Set-Cookie: myCookie=1; ' +! 'Domain=.example.org'! ); 45. Abstraction: Redirects Client document.location.href = '/login';! ! window.pushState({}, '', '/login'); Server res.redirect('/login'); 46. How to isomorph. 47. Lets write a module that abstracts the setting of cookies, providing the same API for client & server. 48. setCookie('myCookie', 'the value'); 49. setCookie('myCookie', 'the value'); document.cookie = 'myCookie=the%20value'; or res.setHeader('Set-Cookie: myCookie=the%20value;'); 50. setCookie('myCookie', 'the value', {! path: '/',! domain: '.example.org',! expires: new Date(2014, 12, 31)! }); document.cookie =! 'myCookie=the%20value; Domain=.example.org; ' +! 'Path=/; Expires=Sat, 31 Jan 2015 05:00:00 GMT'; 51. Eww, that looks hard. 52. NPM & Browserify to the rescue. 53. Browserify Use CommonJS to require() modules in the browser. 54. Browserify Package dependencies from node_modules into our bundle. 55. How do we make a shimmed-per- environment module? Utilize package.json browser eld. 56. {! "name": "set-cookie",! "dependencies": {...}! }! ! ! ! 57. {! "name": "set-cookie",! "dependencies": {...},! "browser": "./lib/client.js"! }! ! ! Swap out the entire implementation. 58. {! "name": "set-cookie",! "dependencies": {...},! "browser": {! "./lib/node.js": "./lib/client.js"! }! }! Swap out specic les. 59. {! "name": "set-cookie",! "dependencies": {...},! "browser": {! "./lib/node.js": "./lib/client.js",! "cookie": "cookie-browser"! }! } Swap out dependencies. 60. Lets build `set-cookie`. https://github.com/spikebrehm/set-cookie 61. Module structure .! "## index.js! "## lib! $ %## setter! $ "## index.js! $ %## client.js! "## node_modules! $ %## cookie 62. // ./index.js! ! var cookie = require('cookie');! var setter = require('./lib/setter');! ! module.exports = function(name, value, options) {! var cookieStr = cookie.serialize(name, value, options);! setter(cookieStr, options);! }; 63. // ./lib/setter/index.js! ! module.exports = function setter(cookieStr, options) {! var res = options && options.res;! ! if (!res)! throw new Error('Must specify `res` ' +! 'when setting cookie.);! ! res.setHeader('Set-Cookie', cookieStr);! }; 64. // ./lib/setter/client.js! ! module.exports = function setter(cookieStr) {! document.cookie = cookieStr;! }; 65. // ./package.json! ! {! "name": "set-cookie",! "dependencies": {! "cookie": "^0.1.2"! },! "browser": {! "./lib/setter/index.js": "./lib/setter/client.js"! }! } 66. // ./index.js! ! var cookie = require('cookie');! var setter = require('./lib/setter');! ! module.exports = function(name, value, options) {! var cookieStr = cookie.serialize(name, value, options);! setter(cookieStr, options);! }; 67. How to isomorph in a nutshell. 68. @spikebrehm@AirbnbNerds Thanks! More resources available athttp://spike.technology 69. @spikebrehm@AirbnbNerds Thanks! More resources available athttp://spike.technology Were hiring!!!Were hiring!!!Were hiring!!!Were hiring!!!Were hiring!!!Were hiring!!!