45
Modernizing the Ext JS Class System Don Griffin @dongryphon

SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

  • Upload
    sencha

  • View
    207

  • Download
    1

Embed Size (px)

Citation preview

Page 1: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

Modernizing the Ext JS Class System

Don Griffin@dongryphon

Page 2: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

Agenda

• Background- Goals for language and tools

- Tool landscape

• Class system content- Modules

- Classes & Mixins

- Life-cycle

• Timeline- WARNING: Code names ahoy!

Page 3: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

Goals

Page 4: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

Future-proofing

Balance Between…

Compatibility

Page 5: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

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

• class syntax can derive from any class

• Module-based structure is first-class

• import and export syntax is supported

• super calls must work (strict mode)

• Ext is scoped to its module

Sencha will provide an upgrade tool to transform a code base to ES6 form!

Page 6: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

Language Standards

Page 7: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

ES6 Score Cards

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

?

Page 8: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

Tools Enable Language Adoption

Page 9: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

Build Tool Trends

https://www.google.com/trends/explore?cat=5&q=grunt,gulp,webpack

Page 10: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

Node.js

Sencha Build (*)Open tooling platform

Scanner

Optimizer

Indexer

Compressor

webpackplugins

rollup

gulp

SystemJS

??

Page 11: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

Transpilers and Source Maps

Page 12: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

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 “least common denominator” development!

- Mostly…

- Not all API’s can be polyfilled (Proxy)

Page 13: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

Source Maps

• Source Maps enable the debugger to display the original source code…- …not inscrutable 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)

Page 14: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

Trust But Verify

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

Page 15: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

Trust But Verifyfor...of

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];}

Page 16: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

Class System Contents

Page 17: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

Namespaces vs Modules

Page 18: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

Ext = {};Ext.global = window;Ext.global.Ext = Ext;

Ext.define('App.some.Thing', { extend: 'App.foo.Bar', requires: [ 'Ext.grid.Panel' ],

Namespaces

• Namespaces are nested objects

• Ext.define() 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'

Page 19: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

var foo = 'bar'; // private, not global

export var abc = 'abc';

export default class Bar { // ...}

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

• Named modules are resolved by the module loader

import { abc } from '../path/file';

import Bar from '../path/file.js';

import Ext from '@extjs/kernel';

import { define } from '@extjs/kernel';

./path/file.js

./other/thing.js

Page 20: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

import { button } from '@extjs/modern';

import { hbox } from '@extjs/modern/layout';

import { Ext_Button } from '@extjs/modern';

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 Sencha Build

Page 21: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

Sencha Cmd Understands Namespaces

Sencha Build Understands Modules

Page 22: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

Classes

Page 23: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

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

Classes Today

Ext.define()

• Inheritance

• Directives

• Properties

• Constructors

• Methods

• Static methods

• Super calls / callParent

Page 24: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

Classes Today

__proto__

prototype

create

App.some.Thing

__proto__constructormethodself

App.some.Thing.prototype

{fn} {fn}{fn}

Function.prototype App.foo.Bar.prototype

Object.prototype

__proto__

foo 42

new App.some.Thing()

Page 25: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

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;

Classes in ES6+

import - export - class - @define

• Inheritance

• Directives

• Properties

• Methods

• Static methods

• Super calls

Decorator

Page 26: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

function define (className, body) { return T => { T.define(className, body); };}

@define('App.some.Thing', { alias: 'thing', text: 'Hello'})class Thing extends Bar {}

define('App.some.Thing', { alias: 'thing', text: 'Hello'})(Thing);

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)

// @define('App.some.Thing', {// alias: 'thing',// text: 'Hello'// })

https://github.com/tc39/proposals

Page 27: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

Classes in ES6+

__proto__

prototype

create

App.some.Thing

__proto__constructmethodconstructor

App.some.Thing.prototype

{fn} {fn}{fn}

Function.prototype

App.foo.Bar.prototype

Object.prototype

App.foo.Bar Same meaningas constructor

was previously

Page 28: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

Classes Before

__proto__

prototype

create

App.some.Thing

__proto__constructormethodself

App.some.Thing.prototype

{fn} {fn}{fn}

Function.prototypeApp.foo.Bar.prototype

Object.prototype

Page 29: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

Classes After

__proto__

prototype

create

App.some.Thing

__proto__constructmethodconstructor

App.some.Thing.prototype

{fn} {fn}{fn}

Function.prototype

App.foo.Bar.prototype

Object.prototype

App.foo.Bar

Page 30: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

class Foo { constructor (x) { this.x = 42; }}

new Foo(42);

let obj = {};Foo.call(obj, 42);

Restrictions on constructor

• A constructor can only be called with the new operator.

• Calling a constructor with call() or apply() throws a TypeError.

Page 31: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

Mixins

Page 32: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

Ext.define('App.mixin.Foo', { method: function (x) { return x * 42; }});

Ext.define('App.some.Thing', { extend: 'App.foo.Bar', mixins: [ 'App.mixin.Foo' ],});

Ext.define('App.some.OtherThing', { extend: 'App.foo.Bar', mixins: [ 'App.mixin.Foo' ],

method: function (x) { return 10 * this.mixins.foo.method.call(this, x); }});

Mixins Today

• Mixins ≈ multiple inheritance

• Mixins are classes

• Methods from the mixin prototype are copied to the target class prototype

• Unless there is already a method present

• The mixins object references the various mixin prototypes

thing.method(2);

this.mixins.observable.constructor.call(this);this.mixins.observable.construct.call(this);

Page 33: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

import { Ext, define } from '@extjs/kernel';import Bar from 'app/foo';

class Mixable extends Ext.Base { method (x) { return x * 42; }}

@define({ mixins: [ Mixable ] })class Thing extends Bar { method (x) { return 10 * this.mixins.mixable.method.call(this, x); }}

@define({ extend: [ Mixable ] })class OtherThing extends Bar { method (x) { return 10 * super.method(x); }}

Mixins in ES6+

• Mixins are classes (that 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

Page 34: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

Common Object Life-cycle

Page 35: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

The Life-cycle of Ext.BaseCreation• Instances are created with operator new- or Ext.create() or other factory

• The native constructor is available to ES6 classes- Not recommended in most cases

• The construct method is available to all classes- The new name for the old constructor

Page 36: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

The Life-cycle of Ext.BaseConfiguration• Use the config directive to define configuration properties

• Config system calls your apply and update methods

• Use the built-in, single-object-parameter form of the construct method

• Ext.Base#construct calls initConfig (if needed)

Page 37: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

The Life-cycle of Ext.BaseDestruction• Cleanup is handled by destroy• Sets flags like destroying and destroyed• Ignores multiple calls

• Calls destruct (just once)

• Clears instance properties to avoid memory leaks

Page 38: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

The Life-cycle of Ext.BaseTemplate methods (*)• ctor- Called to initialize an instance

- Called after the ctor of all base classes and mixins

• dtor - Called to cleanup an instance

- Called before the dtor of bases or mixins

• No super calls required- All implementations of ctor and dtor are called automatically

Page 39: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

import Ext from '@extjs/kernel';

class A extends Ext.Base { construct (x) { super.construct(); this.x = 42; this.x2 = this.x * 10; }}

class B extends A { construct (x, y) { super.construct(x); this.y = y; this.y2 = y * 427; }}

@define({ mixins: [ B ] })class C extends Ext.Base { construct (x, y) { super.construct(); this.mixins.b.construct(x, y); this.c = this.x + this.y + this.x2 + this.y2; }}

new C(4, 42);

Life-cycles & Diamonds

A

Ext.Base

B

C

Page 40: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

import { Ext, define } from '@extjs/kernel';

@define({ config: { x: 0 }})class A extends Ext.Base { updateX (x) { this.x2 = x * 10; }}

class B extends A { ctor () { this.y2 = this.y * 427; }}

@define({ mixins: [ B ] })class C extends Ext.Base { ctor () { this.c = this.getX() + this.y + this.x2 + this.y2; }}

new C({ x: 2, y: 42 });

Life-cycles & Diamonds

A

Ext.Base

B

C

Page 41: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

Life-cycles & Diamonds

A

Ext.Base

B

C

• ctor methods are called once per class- In base-to-derived order (including mixins!)

• dtor methods are called once per class- In derived-to-base order

• Ext.Base#construct calls ctor

• Ext.Base#destruct calls dtor

• ctor/dtor methods are gathered lazily- Never unless construct/destruct are used

ctor

ctor

ctor

ctor

dtor

dtor

dtor

dtor

Page 42: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

The Road Ahead

Page 43: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

The Road AheadSencha Cmd 6.5

• Available now (Early Access)!

• Uses Google Closure Compiler

• Supports much of the ES6 syntax (http://kangax.github.io/compat-table/es6/)

• Provides polyfills as well

• Transpiling is optional

• New compressor (replaces YUI) can process native ES6 code- Only compressor currently to do so!

Page 44: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin

The Road AheadExt JS.Next

• Sencha Build and Sencha Cmd

• Upgrade tool to convert from projects from Cmd to Build- See Ross’s talk!

• Estimated at 2nd half of 2017

Page 45: SenchaCon 2016: Modernizing the Ext JS Class System - Don Griffin