ES6 in Production [JSConfUY2015]

Post on 17-Jul-2015

132 views 0 download

transcript

ES6 in ProductionJSConf Uruguay 2015

- Made in Buenos Aires, Argentina

- Front-end Developer

- Working at Mango

@pazguille (twitter / github)

Guille Paz

#ES6inProdYour feedback is welcome!

ES6

Why?

Why?

Future

Why?

Why?

Code

Why?

● Write expressive code

Why?

● Write expressive code

● Easier to understand

Why?

● Write expressive code

● Easier to understand

● Standardizes commons practices

Why?

ES6 Modules

define('Slideout',

// Deps

['inherit', 'Emitter'],

// Slideout

function(inherit, Emitter) {

function Slideout(options) { … }

// Export

return Slideout;

});

Why?

AMD

// Deps

var inherit = require('inherit');

var Emitter = require('emitter');

// Slideout

function Slideout(options) { … }

// Export

module.exports = Slideout;

Why?

CommonJS

Why?

ES6 Modules

// Deps

import inherit from 'inherit';

import Emitter from 'emitter';

// Slideout

function Slideout(options) { … }

// Export

export default Slideout;

Why?

Classes

// Slideout

function Slideout(options) { … }

// Inherit from Emitter

inherit(Slideout, Emitter);

// Extend prototype

Slideout.prototype.open = function() { … };

Why?

Classes

// Slideout

class Slideout extends Emitter {

constructor(options={}) { … }

open() { … }

}

Why?

Classes

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

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;

Why?

Classesarrow = > functions

Module Syntax

let/const

Rest Parameters

Templates Strings Default Parameters

getmango.com/blog

https://getmango.com/blog/writing-es6-modules-with-6to5/

How?

Transpilers

How?

How?

ES6 ES5

How?

How?

Build Process

How?

How?

browserify({'entries': opts.entries, 'debug': true})

.plugin('factor-bundle', {'outputs': opts.bundles})

.on('error', function(err) { … })

.bundle()

.pipe(fs.createWriteStream(opts.output));

How?

How?

Babelify

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?

Browser

How?

How?

http://kangax.github.io/compat-table/es5/

ES5

Polyfills

How?

How?

http://kangax.github.io/compat-table/es6/

ES6

core-js

How?

https://github.com/zloirock/core-js

How?

es5.js(IE < 9)

Custom build

https://github.com/zloirock/core-js

How?

es5.js(IE < 9)

es6.js(all)

Custom build

https://github.com/zloirock/core-js

index.htmlHow?

<!--[if lt IE 9]>

<script src="/js/es5.js"></script>

<![endif]-->

<script src="/js/es6.js"></script>

<script src="/js/build.js"></script>

</body>

Issues

Issues

Context

~110 modules

Issues

Issues

ES5 / ES6

Issues

Dependencies

Issues

Issues

├─ src

├─ boot.js

└─ bus.js

├─ package.json

├─ test

└─ node_modules

├─ slideout

└─ emitter

Dashboard

ES6

ES6

Issues

bus.js

// Deps

import Emitter from 'emitter';

// bus

const bus = new Emitter();

// Export

export default bus;

Issues

exports['default'] = bus;

module.exports = exports['default'];

},{'emitter':2}],2:[function(require,module,exports){

class Emitter {

on(event, listener) {

Issues

output.js

Issues

Dashboard

├─ src

├─ boot.js

└─ bus.js

├─ package.json

├─ test

└─ node_modules

├─ slideout

└─ emitter

Babelify

Issues

Dashboard

├─ src

├─ boot.js

└─ bus.js

├─ package.json

├─ test

└─ node_modules

├─ slideout

└─ emitter

Babelify

Issues

Dashboard

├─ src

├─ boot.js

└─ bus.js

├─ package.json

├─ test

└─ node_modules

├─ slideout

└─ emitter

Babelify

global : true

Issues

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

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

exports['default'] = bus;

module.exports = exports['default'];

},{'emitter':2}],2:[function(require,module,exports){

var Emitter = (function () {

function Emitter() {

Issues

output.js

package.json

Issues

"browserify": {

"transform": ["babelify"]

},

Issues

Emitter.js - package.json

"browserify": {

"transform": ["babelify"]

},

"dependencies": {

"babelify": "6.0.2"

},

Issues

Emitter.js - package.json

Issues

Writing ES6

Issues

Publishing ES5

Issues

Issues

Module

├─ src

└─ index.js

├─ package.json

└─ test

Issues

Module

├─ src

└─ index.js

├─ package.json

└─ test

ES6

Issues

Module

ES5

├─ src

└─ index.js

├─ package.json

└─ test

├─ dist

└─ index.js

"main": "dist/index.js",

Issues

package.json

Issues

Compile Task(npm, grunt, gulp, broccoli)

"main": "dist/index.js",

"script": {

"compile": "babel src --out-dir dist"

},

Issues

Compile Task

Issues

npm run compile

"main": "dist/index.js",

"script": {

"compile": "babel src --out-dir dist",

"prepublish": "npm run compile"

},

Issues

Prepublish Task

mango/emitter

Issues

https://github.com/mango/emitter

Inheritance

Issues

'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

Issues

Emitter.js - ES6

class Emitter {

constructor(options={}) { … }

on() { … }

emit() { … }

}

export default Emitter;

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

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

console.log(Slideout.prototype);

// { open: function }

Issues

Slideout.js - ES5

console.log(Emitter.prototype);

// { }

Issues

Emitter.js - ES6

Issues

http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts

Issues

class Emitter {

on() { … }

}

Issues

Emitter.js - ES6

class Emitter {

on() { … }

}

Issues

Emitter.js - ES5

function Emitter() {}

Object.defineProperties(Emitter.prototype, {

'on': {

'writable': true,

'configurable': true,

'enumerable': false,

'value': function on() {}

}

});

class Emitter {

on() { … }

}

Issues

Emitter.js - ES5

function Emitter() {}

Object.defineProperties(Emitter.prototype, {

'on': {

'writable': true,

'configurable': true,

'enumerable': false,

'value': function on() {}

}

});

Loose Mode(babel)

Issues

Issues

es6.classes

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

class Emitter {

on() { … }

}

Issues

Emitter.js - ES5

var Emitter = (function () {

function Emitter() { … }

Emitter.prototype.on = function on() {};

return Emitter;

})();

console.log(Slideout.prototype);

// { open: function, on: function }

Issues

Slideout.js - ES5

Object.create

Issues

'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

'use strict';

// Inherits prototype properties.

module.exports = function inherit(child, parent) {

child.prototype = Object.create(parent.prototype);

return parent.prototype;

};

Issues

inherit.js - ES5

super() - this

Issues

class Slideout extends Emitter {

constructor(options={}) {

this._padding = options.padding;

}

}

Issues

Slideout.js - ES6

Line 12: 'this' is not allowed before super()

Issues

class Slideout extends Emitter {

constructor(options={}) {

this._padding = options.padding;

}

}

Issues

Slideout.js - ES6

class Slideout extends Emitter {

constructor(options={}) {

super(options);

this._padding = options.padding;

}

}

Issues

Slideout.js - ES6

Issues

https://twitter.com/jashkenas/status/585458831993528320

import & hoisting

Issues

import _ from 'i18n';

import translations from 'translations.json';

_.add(translations);

import login from './login';

Issues

Login View - ES6

import _ from 'i18n';

import translations from 'translations.json';

_.add(translations);

import login from './login';

Issues

Login View - ES6

Issues

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']);

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

Issues

Babel 4.1.7

Issues

Takeaway

● Transpile to ES5 (Babel)

Takeaway

● Transpile to ES5 (Babel)

● Use ES5/ES6 polyfills (core-js)

Takeaway

● Transpile to ES5 (Babel)

● Use ES5/ES6 polyfills (core-js)

● Babelify: opts.global or package.json

Takeaway

Takeaway

● Transpile to ES5 (Babel)

● Use ES5/ES6 polyfills (core-js)

● Babelify: opts.global or package.json

● Write ES6, publish ES5 (compile task)

● 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

Thank you!

<3