Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

ES6 in Production [JSConfUY2015]

1,172 views

Published on

Everybody is talking about ES6, but is anyone out there using it in production? Mango recently started adopting ES6 features that make our front-end code easier to write and maintain.

In this talk, I will explain why we decided to use ES6, how we started to use it in production (using npm, browserify and babel) and I'll explain what problems we found along the way and how we solved them.

Links:
https://getmango.com
https://getmango.com/blog/writing-es6-modules-with-6to5/
http://kangax.github.io/compat-table/
https://github.com/zloirock/core-js
https://github.com/mango/emitter
http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts
http://benmccormick.org/2015/04/07/es6-classes-and-backbone-js/

Published in: Technology

ES6 in Production [JSConfUY2015]

  1. 1. ES6 in Production JSConf Uruguay 2015
  2. 2. - Made in Buenos Aires, Argentina - Front-end Developer - Working at Mango @pazguille (twitter / github) Guille Paz
  3. 3. #ES6inProd Your feedback is welcome!
  4. 4. ES6
  5. 5. Hi! https://getmango.com
  6. 6. Why?
  7. 7. Why?
  8. 8. Future Why?
  9. 9. Why? Code
  10. 10. Why? ● Write expressive code
  11. 11. Why? ● Write expressive code ● Easier to understand
  12. 12. Why? ● Write expressive code ● Easier to understand ● Standardizes commons practices
  13. 13. Why? ES6 Modules
  14. 14. define('Slideout', // Deps ['inherit', 'Emitter'], // Slideout function(inherit, Emitter) { function Slideout(options) { … } // Export return Slideout; }); Why? AMD
  15. 15. // Deps var inherit = require('inherit'); var Emitter = require('emitter'); // Slideout function Slideout(options) { … } // Export module.exports = Slideout; Why? CommonJS
  16. 16. Why? ES6 Modules // Deps import inherit from 'inherit'; import Emitter from 'emitter'; // Slideout function Slideout(options) { … } // Export export default Slideout;
  17. 17. Why? Classes
  18. 18. // Slideout function Slideout(options) { … } // Inherit from Emitter inherit(Slideout, Emitter); // Extend prototype Slideout.prototype.open = function() { … }; Why? Classes
  19. 19. // Slideout class Slideout extends Emitter { constructor(options={}) { … } open() { … } } Why? Classes
  20. 20. // Deps var inherit = require('inherit'); var Emitter = require('emitter'); // Slideout function Slideout(options) { … } // Inherit from Emitter inherit(Slideout, Emitter); // Extend prototype Slideout.prototype.open = function() { … }; // Export module.exports = Slideout; Why?
  21. 21. // Deps var inherit = require('inherit'); var Emitter = require('emitter'); // Slideout function Slideout(options) { … } // Inherit from Emitter inherit(Slideout, Emitter); // Extend prototype Slideout.prototype.open = function() { … }; // Export module.exports = Slideout; Why? // Deps import Emitter from 'emitter'; // Slideout class Slideout extends Emitter { constructor(options={}) { … } open() { … } } // Export export default Slideout;
  22. 22. Why? Classes arrow = > functions Module Syntax let/const Rest Parameters Templates Strings Default Parameters
  23. 23. getmango.com/blog https://getmango.com/blog/writing-es6-modules-with-6to5/
  24. 24. How?
  25. 25. Transpilers How?
  26. 26. How? ES6 ES5
  27. 27. How?
  28. 28. How?
  29. 29. Build Process How?
  30. 30. How?
  31. 31. browserify({'entries': opts.entries, 'debug': true}) .plugin('factor-bundle', {'outputs': opts.bundles}) .on('error', function(err) { … }) .bundle() .pipe(fs.createWriteStream(opts.output)); How?
  32. 32. How? Babelify
  33. 33. browserify({'entries': opts.entries, 'debug': true}) .plugin('factor-bundle', {'outputs': opts.bundles}) .transform('babelify') .on('error', function(err) { … }) .bundle() .pipe(fs.createWriteStream(opts.output)); How?
  34. 34. Browser How?
  35. 35. How? http://kangax.github.io/compat-table/es5/ ES5
  36. 36. Polyfills How?
  37. 37. How? http://kangax.github.io/compat-table/es6/ ES6
  38. 38. core-js How? https://github.com/zloirock/core-js
  39. 39. How? es5.js (IE < 9) Custom build https://github.com/zloirock/core-js
  40. 40. How? es5.js (IE < 9) es6.js (all) Custom build https://github.com/zloirock/core-js
  41. 41. index.html How? … <!--[if lt IE 9]> <script src="/js/es5.js"></script> <![endif]--> <script src="/js/es6.js"></script> <script src="/js/build.js"></script> </body>
  42. 42. Issues
  43. 43. Issues Context
  44. 44. ~110 modules Issues
  45. 45. Issues
  46. 46. ES5 / ES6 Issues
  47. 47. Dependencies Issues
  48. 48. Issues ├─ src ├─ boot.js └─ bus.js ├─ package.json ├─ test └─ node_modules ├─ slideout └─ emitter Dashboard ES6 ES6
  49. 49. Issues bus.js // Deps import Emitter from 'emitter'; // bus const bus = new Emitter(); // Export export default bus;
  50. 50. Issues
  51. 51. … exports['default'] = bus; module.exports = exports['default']; },{'emitter':2}],2:[function(require,module,exports){ class Emitter { on(event, listener) { … Issues output.js
  52. 52. Issues Dashboard ├─ src ├─ boot.js └─ bus.js ├─ package.json ├─ test └─ node_modules ├─ slideout └─ emitter Babelify
  53. 53. Issues Dashboard ├─ src ├─ boot.js └─ bus.js ├─ package.json ├─ test └─ node_modules ├─ slideout └─ emitter Babelify
  54. 54. Issues Dashboard ├─ src ├─ boot.js └─ bus.js ├─ package.json ├─ test └─ node_modules ├─ slideout └─ emitter Babelify
  55. 55. global : true Issues
  56. 56. browserify({'entries': opts.entries, 'debug': true}) .plugin('factor-bundle', {'outputs': opts.bundles}) .transform('babelify') .on('error', function(err) { … }) .bundle() .pipe(fs.createWriteStream(opts.output)); Issues
  57. 57. browserify({'entries': opts.entries, 'debug': true}) .plugin('factor-bundle', {'outputs': opts.bundles}) .transform('babelify', {'global': true}) .on('error', function(err) { … }) .bundle() .pipe(fs.createWriteStream(opts.output)); Issues
  58. 58. … exports['default'] = bus; module.exports = exports['default']; },{'emitter':2}],2:[function(require,module,exports){ var Emitter = (function () { function Emitter() { … Issues output.js
  59. 59. package.json Issues
  60. 60. … "browserify": { "transform": ["babelify"] }, … Issues Emitter.js - package.json
  61. 61. … "browserify": { "transform": ["babelify"] }, "dependencies": { "babelify": "6.0.2" }, … Issues Emitter.js - package.json
  62. 62. Issues
  63. 63. Writing ES6 Issues
  64. 64. Publishing ES5 Issues
  65. 65. Issues Module ├─ src └─ index.js ├─ package.json └─ test
  66. 66. Issues Module ├─ src └─ index.js ├─ package.json └─ test ES6
  67. 67. Issues Module ES5 ├─ src └─ index.js ├─ package.json └─ test ├─ dist └─ index.js
  68. 68. … "main": "dist/index.js", … Issues package.json
  69. 69. Issues Compile Task (npm, grunt, gulp, broccoli)
  70. 70. … "main": "dist/index.js", "script": { "compile": "babel src --out-dir dist" }, … Issues Compile Task
  71. 71. Issues npm run compile
  72. 72. … "main": "dist/index.js", "script": { "compile": "babel src --out-dir dist", "prepublish": "npm run compile" }, … Issues Prepublish Task
  73. 73. mango/emitter Issues https://github.com/mango/emitter
  74. 74. Inheritance Issues
  75. 75. 'use strict'; var extend = require('extend'); // Inherits prototype properties module.exports = function inherit(child, parent) { extend(child.prototype, parent.prototype); return parent.prototype; }; Issues inherit.js - ES5
  76. 76. Issues Emitter.js - ES6 class Emitter { constructor(options={}) { … } on() { … } emit() { … } … } export default Emitter;
  77. 77. // Deps var inherit = require('inherit'); var Emitter = require('emitter'); // Slideout function Slideout(options) { … } // Inherit from Emitter inherit(Slideout, Emitter); // Extend prototype Slideout.prototype.open = function() { … }; // Export module.export = Slideout; Issues Slideout.js - ES5
  78. 78. // Deps var inherit = require('inherit'); var Emitter = require('emitter'); // Slideout function Slideout(options) { … } // Inherit from Emitter inherit(Slideout, Emitter); // Extend prototype Slideout.prototype.open = function() { … }; // Export module.export = Slideout; Issues Slideout.js - ES5
  79. 79. console.log(Slideout.prototype); // { open: function } Issues Slideout.js - ES5
  80. 80. console.log(Emitter.prototype); // { } Issues Emitter.js - ES6
  81. 81. Issues http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts
  82. 82. Issues
  83. 83. class Emitter { … on() { … } … } Issues Emitter.js - ES6
  84. 84. class Emitter { … on() { … } … } Issues Emitter.js - ES5 function Emitter() {} Object.defineProperties(Emitter.prototype, { 'on': { 'writable': true, 'configurable': true, 'enumerable': false, 'value': function on() {} } });
  85. 85. class Emitter { … on() { … } … } Issues Emitter.js - ES5 function Emitter() {} Object.defineProperties(Emitter.prototype, { 'on': { 'writable': true, 'configurable': true, 'enumerable': false, 'value': function on() {} } });
  86. 86. Loose Mode (babel) Issues
  87. 87. Issues es6.classes
  88. 88. browserify({'entries': opts.entries, 'debug': true}) .plugin('factor-bundle', {'outputs': opts.bundles}) .transform('babelify', {'global': true, 'loose': ['es6.classes']}) .on('error', function(err) { … }) .bundle() .pipe(fs.createWriteStream(opts.output)); Issues Build Process
  89. 89. class Emitter { … on() { … } … } Issues Emitter.js - ES5 var Emitter = (function () { function Emitter() { … } Emitter.prototype.on = function on() {}; … return Emitter; })();
  90. 90. console.log(Slideout.prototype); // { open: function, on: function } Issues Slideout.js - ES5
  91. 91. Object.create Issues
  92. 92. 'use strict'; var extend = require('extend'); // Inherits prototype properties. module.exports = function inherit(child, parent) { extend(child.prototype, parent.prototype); return parent.prototype; }; Issues inherit.js - ES5
  93. 93. 'use strict'; // Inherits prototype properties. module.exports = function inherit(child, parent) { child.prototype = Object.create(parent.prototype); return parent.prototype; }; Issues inherit.js - ES5
  94. 94. super() - this Issues
  95. 95. class Slideout extends Emitter { constructor(options={}) { this._padding = options.padding; … } } Issues Slideout.js - ES6
  96. 96. Line 12: 'this' is not allowed before super() Issues
  97. 97. class Slideout extends Emitter { constructor(options={}) { this._padding = options.padding; … } } Issues Slideout.js - ES6
  98. 98. class Slideout extends Emitter { constructor(options={}) { super(options); this._padding = options.padding; … } } Issues Slideout.js - ES6
  99. 99. Issues https://twitter.com/jashkenas/status/585458831993528320
  100. 100. Issues http://benmccormick.org/2015/04/07/es6-classes-and-backbone-js/
  101. 101. import & hoisting Issues
  102. 102. import _ from 'i18n'; import translations from 'translations.json'; _.add(translations); import login from './login'; … Issues Login View - ES6
  103. 103. import _ from 'i18n'; import translations from 'translations.json'; _.add(translations); import login from './login'; … Issues Login View - ES6
  104. 104. Issues
  105. 105. Issues Login View - ES5 var _import = require('i18n'); var _import2 = _interopRequireWildcard(_import); var _translations = require('translations.json'); var _translations2 = _interopRequireWildcard(_translations); var _login = require('./login'); var __login2 = _interopRequireWildcard(__login); _import2['default'].add(_translations2['default']);
  106. 106. var _import = require('i18n'); var _import2 = _interopRequireWildcard(_import); var _translations = require('translations.json'); var _translations2 = _interopRequireWildcard(_translations); var _login = require('./login'); var __login2 = _interopRequireWildcard(__login); _import2['default'].add(_translations2['default']); Issues Login View - ES5
  107. 107. Issues
  108. 108. Babel 4.1.7 Issues
  109. 109. Takeaway
  110. 110. ● Transpile to ES5 (Babel) Takeaway
  111. 111. ● Transpile to ES5 (Babel) ● Use ES5/ES6 polyfills (core-js) Takeaway
  112. 112. ● Transpile to ES5 (Babel) ● Use ES5/ES6 polyfills (core-js) ● Babelify: opts.global or package.json Takeaway
  113. 113. Takeaway ● Transpile to ES5 (Babel) ● Use ES5/ES6 polyfills (core-js) ● Babelify: opts.global or package.json ● Write ES6, publish ES5 (compile task)
  114. 114. ● Transpile to ES5 (Babel) ● Use ES5/ES6 polyfills (core-js) ● Babelify: opts.global or package.json ● Write ES6, publish ES5 (compile task) ● Babel - loose mode (es6.classes, es6.modules, … ) Takeaway
  115. 115. Thank you! <3

×