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

Modernizing the Sencha class system

Modernizing the Sencha class system

Presentation by Lee Boonstra. Sencha Roadshows 2016

Lee Boonstra

December 09, 2016
Tweet

More Decks by Lee Boonstra

Other Decks in Technology

Transcript

  1. Agenda • Background - Goals for language and tools -

    Transpilers & Source maps • Class system content - Modules - Classes & Mixins - Life-cycle • The Road Ahead
  2. “ What you know as JavaScript in browsers and Node.js

    is actually a superset of ECMAScript. Browsers and Node.js add more functionality through additional objects and methods, but the core of the language remains as defined in ECMAScript. “
  3. Terminology • JavaScript - the language name • ECMAScript -

    the name of the standard • ES2015 / ES6 – Newest version of the ECMAScript standard • Transpiler - Transforms ES2015 code to the JavaScript that currently supported in our browsers.
  4. About Compatibility You can find an overview of compatibility, in

    one of these ECMAScript 2015 compatibility tables: http://kangax.github.io/compat-table/es6/ ES2015 Implementations: • V8 (Chrome, Node.js, Opera) • JavaScript Core (Webkit, Safari) • Chakra (MS Edge) • SpiderMonkey (Firefox) • Mobile (iOS 9+, Android 4.4+)
  5. Ext.define('MyApp.view.MyGrid ', { extend: 'Ext.grid.Panel', alias: 'widget.mygrid', //configs for a

    custom grid }); Why Ext JS? • Cross platform apps. - Support for legacy and modern browsers. - All types of devices • One framework, to develop complex applications fast. • Components, components, components…
  6. import { define } from '@extjs/kernel'; import { grid }

    from '@extjs/modern'; class MyApp.view.MyGrid extends grid { //configs for a custom grid } export default MyApp.view.MyGrid; ES2015 style of code The Benefits: • ES2015, helps you with developer productivity. • Can make use of new tools. • As a JS developer you can make use of the latest standards. • Reduces the Ext JS learning curve.
  7. Future-proofing Balance Between… Compatibility Ext.define works as before Existing code

    organization is supported Ext.require works as before callParent must be available Ext namespace is globally available New class syntax can derive from any class Module-based structure import and export syntax is supported super calls must work (strict mode) Ext is scoped to its module
  8. Sencha will provide an upgrade tool to transform an old

    Ext.define code base to the modern ES2015 class syntax!
  9. Transpilers • Transpilers (like Babel) are JavaScript-to-JavaScript compilers • Transpilers

    go beyond “polyfills” by providing missing language syntax! • Transpilers are currently the only platforms that accept imports, exports and decorators • Transpilers allow us to future-proof our code (unblocking the language adoption curve) - No more “I have to develop code for the worst supported browsers” • (though, not everything can be fixed by tools)
  10. Source Maps • Source Maps enable the debugger to display

    the original source code… - …not the ugly transpiler output! • Source Maps have been around since 2012 - This is great because they are widely supported • Source Maps are supported by: - Chrome, Firefox, Edge, Safari - IE11 (with Windows 8.1 Update) See: https://www.html5rocks.com/en/tutorials/developertools/sourcemaps/
  11. Trust, But Be Careful with it • Transpilers can produce

    some scary code - Only transpile away what your target browser(s) do not support - Check what is produced if performance or code size is a concern - Especially if you need to support browsers like IE 11… or Safari 9 (or older) • Even natively supported idioms can have surprising performance - The “for…of” loop construct – awesome syntax! Not-so-great performance https://kpdecker.github.io/six-speed/
  12. Trust, But Verify ES5: for loop vs. ES2015: for...of loop

    var data = [1, 2, 3]; var ret = ''; for (var value of data) { ret += value; } var data = [1, 2, 3]; var ret = ''; for (var i = 0; i < data.length; ++i) { ret += data[i]; }
  13. Ext = {}; Ext.global = window; Ext.global.Ext = Ext; Ext.define('App.some.Thing',

    { extend: 'App.foo.Bar', requires: [ 'Ext.grid.Panel' ], ExtJS: Namespaces • Namespaces are nested objects • Ext.define() defines class & adds to the namespace • The Loader maps names to URL’s • Files are loaded at global scope Ext = { global: { Ext: Ext, App: { foo: { Bar: constructor }, some: { Thing: constructor } } }, grid: { Panel: constructor } } Ext.Loader.setPath({ Ext: '../ext/src', App: './app' }); // Ext.grid.Panel // => '../ext/src/grid/Panel.js' // App.foo.Bar // => './app/foo/Bar.js'
  14. var foo = 'bar'; // private, not global export var

    abc = 'abc'; export default class Bar { // ... } New: ES2015 Modules • Modules are files • Modules execute in a private scope (not global) • Modules publish values using export • Modules can have one, unnamed “default” export value • Modules use import to acquire values exported by other modules • Modules are imported by path or name ./path/file.js import { abc } from '../path/file'; import Bar from '../path/file.js'; import Ext from '@extjs/kernel'; import { define } from '@extjs/kernel'; ./other/thing.js
  15. import { button } from '@extjs/modern'; import { hbox }

    from '@extjs/modern/layout'; import { Ext_Button } from '@extjs/modern'; New: Importing Components • Classes are exported in several ways: - By xtype - By alias family - By class name • These would be used where strings might be used today • These exports can be generated by the new build tool
  16. Ext.define('App.some.Thing', { extend: 'App.foo.Bar', requires: [ 'Ext.grid.Panel' ], alias: 'thing',

    text: 'Hello', constructor: function (config) { this.callParent([config]); }, method: function (x) { return this.callParent([x]) * 42; }, statics: { create: function (cfg) { cfg.type = 'thing'; return this.callParent([cfg]); } } }); ExtJS: Classes Ext.define() • Inheritance • Requires (directives) • Properties • Constructors • Methods • Static methods • callParent
  17. import { define } from '@extjs/kernel'; import { grid }

    from '@extjs/modern'; import Bar from 'app/foo'; @define('App.some.Thing', { alias: 'thing', text: 'Hello' }) class Thing extends Bar { method (x) { return super.method(x) * 42; } static create (cfg) { cfg.type = 'thing'; return super.create(cfg); } } export default Thing; New: ES2015 Classes import - export - class - @define • Inheritance • Directives • Properties • Methods • Static methods • Super calls (callParent) Decorator
  18. function define (className, body) { return T => { T.define(className,

    body); }; } @define('ShootAble', { alias: 'gun', shoot: function(){ return 'Pow!' } }) class HanSolo extends Human { } New: Decorators • Decorators are functions that manipulate classes (or methods) • Decorators can accept arguments… - But must return a function to call as if no arguments were provided • The @decorator syntax is just a different way to call these functions • Decorators are currently a Stage 2 proposal (not yet standardized) https://github.com/tc39/proposals //another way of achieving the same without a decorator: define('ShootAble', { alias: 'gun', shoot: function(){ return 'Pow!' } })(HanSolo);
  19. class Foo { constructor (x) { this.x = 42; }

    } new Foo(42); let obj = {}; Foo.call(obj, 42); ES2015: Restrictions on constructor • A constructor can only be called with the new operator. • Calling a constructor with call() or apply() throws a TypeError.
  20. Ext.define('Clickable', { click: function (e) { //click } }); Ext.define('MyApp.custom.Component',

    { extend: 'Ext.Component', mixins: [ 'Clickable' ], }); Ext.define('MyApp.view.OtherComponent', { extend: 'Ext.Component', mixins: [ 'Clickable' ], click: function (e) { this.mixins.clickable.click.call(this); } }); ExtJS: Mixins • Mixins is multiple inheritance • Mixins are classes • Methods from the mixin prototype are copied to the target class prototype • Unless there is already a method present component.click();
  21. import { Ext, define } from '@extjs/kernel'; import MyComponent from

    'app/view'; class Clickable extends Ext.Base { click (e) { //click } } @define({ mixins: [ Clickable ] }) class OtherComponent extends MyComponent { click (e) { this.mixins.clickable.click.call(this); } } @define({ extend: [ Clickable ] }) class OtherComponent extends MyComponent { click (e) { super.click(e); } } ES2015: Mixins • Mixins are classes (extend Ext.Base) • Use @define to mix in the mixin(s) • Mixins will be able to act more like a true base - The extend directive accepts mixins - Calls to overlapping methods are handled in the super call
  22. The Life-cycle of Ext.Base Creation • Instances are created with

    operator new - or Ext.create() or other factory • The native constructor is available to ES2015 classes - Not recommended in most cases • The construct method is available to all classes - The new name for the old constructor
  23. The Life-cycle of Ext.Base Configuration • Use the config directive

    to define configuration properties • Config system calls your apply and update methods • Ext.Base construct calls initConfig
  24. The Life-cycle of Ext.Base Destruction • Cleanup is handled by

    destroy • Sets flags like destroying and destroyed • Ignores multiple calls • Calls destruct (just once) • New: Clears instance properties to avoid memory leaks
  25. import Ext from '@extjs/kernel'; class Human extends Ext.Base { construct

    (config) { super.construct(); this.talk = function(){ return “Hello!” }; } class HanSolo extends Human { construct (config) { super.construct(config); this.shoot = function() { return “Pow!” }; } @define({ mixins: [ HanSolo ] }) class Wookie extends Ext.Base { construct (config) { super.construct(); this.mixins.hansolo.construct(config); this.talk = function() { “Roarrrrr!” }; } } new Wookie(); Life-cycles Human Ext.Base HanSolo Wookie
  26. The Road Ahead Sencha Cmd 6.5 • Available now (Early

    Access)! • Uses Google Closure Compiler • Supports much of the ES2015 syntax (http://kangax.github.io/compat-table/es6/) • Provides polyfills as well • Transpiling is optional • New compressor (replaces YUI) can process native ES2015 code
  27. The Road Ahead Ext JS.Next • Framework will have changes

    in Ext.Base • New Build Tool and new Sencha Cmd • Upgrade tool to convert from projects from Cmd to Build • Estimated at 2nd half of 2017