The JavaScript language today is hardly recognizable when compared to the JavaScript of a few short years ago. The changes range from small pieces of syntax (such as loops, variables, and functions), up to the level of classes for creating coherent functional units and extend all the way to connecting these pieces into applications via modules.
Today, through the widespread use of tools such as Babel, Traceur, webpack, and others, many developers have embraced these new language features and their code can still run on “those” browsers.
In my session at SenchaCon 2016 (Ext JS and ES2015/6/7 – Modernizing the Ext JS Class System), we’ll talk about how this evolution in language and tools affects the applications we write using Ext JS. We’ll look at how the class
keyword compares with Ext.define
, and how class names line up with modules. And we’ll compare the two end-states of an upgraded application: one with minimal changes to existing code and one that fully embraces all of the new language features.
Don’t have your ticket yet for SenchaCon 2016? Register today.
You can try the new and updated features of Javascript Web Framework which help to modernize your team and apply modern techniques when building applications.
Table of Contents
Sneak Peak
Class Declarations
Let’s take a simple utility class that might be found in an Ext JS application today and see what an upgrade might look like.
Ext.define('App.util.Foo', { extend: 'App.some.Base', mixins: 'Ext.mixin.Observable', config: { value: null } constructor: function (config) { this.mixins.observable.constructor.call(this, config); }, updateValue: function (value, oldValue) { this.fireEvent('valuechange', value, oldValue); } });
The following diagram shows the important pieces produced by the code above:
If you look at the constructor property on the prototype, you’ll see that it points to the method we passed to Ext.define
. This approach, while flexible, is not compatible with the new class
keyword. Using the class
keyword produces the following, immutable relationship:
App.util.Foo === App.util.Foo.prototype.constructor
Minimal Upgrade
The minimal upgrade requires us to rename the “constructor” method to avoid this conflict. The new name is simply “construct
“:
Ext.define('App.util.Foo', { extend: 'App.some.Base', mixins: 'Ext.mixin.Observable', config: { value: null } construct (config) { this.mixins.observable.construct.call(this, config); }, updateValue (value, oldValue) { this.fireEvent('valuechange', value, oldValue); } });
Though not necessary, we’ve also taken advantage of the new function property syntax for object literals and removed the “: function
” from our methods.
Because the new Ext.define
internally produces a standard class
, we gain some benefits as well. Consider the following diagram showing what is generated by the upgraded Ext.define
call above:
Because class constructors are now prototype-chained to their superclass constructors, effectively all static members are inheritableStatics for free!
Maximum Upgrade
At the opposite end of the upgrade continuum is a complete upgrade to all the new language features and options. Let’s look at what the fully upgraded version of the above class might look like:
import { define } from 'extjs-kernel'; // module names not final import { Observable } from 'extjs-core'; import { Base } from 'app-some'; @define({ mixins: Observable, config: { value: null } }) export default class Foo extends Base { updateValue (value, oldValue) { this.fireEvent('valuechange', value, oldValue); } }
In this version, we’re taking advantage of several new class system features as well as some upcoming JavaScript features.
If you haven’t seen the @define
syntax before it’s called a decorator, and it’s an exciting language feature currently being worked through the standardization process. It’s available today via the magic of transpilers. Transpilers are tools that compile JavaScript-to-JavaScript or more precisely, Advanced-JavaScript-to-Browser-Friendly-JavaScript. Through the @define
decorator, you can apply all the additional powers of the Ext JS class system to this standard class
.
We also removed the construct/constructor
methods in this example. This is because the construct
method of Ext.Base
now provides a Common Object Lifecycle. When called with a single object parameter or if the class uses the Config System, the necessary steps to initialize the instance are handled automatically.
Last, we’re using the new, standard import
and export
keywords. Support for these is also by virtue of transpilers (because no browser yet supports them). To learn more of the details, you can also attend Ross Gerbasi’s talk: The Modern Toolchain.
Choices, Choices
Because there is no one-size-fits-all approach, the overarching goal of this upgrade is to minimize what must be done to existing code while at the same time enabling developers to usefully modernize JavaScript techniques and practices.
To hear first-hand what else is coming, be sure to attend my session at SenchaCon 2016!
Doesn’t this “maximum upgrade” syntax trade away the ability to load class source files in any order and asynchronously fetch their dependencies? This seems to also lose the ability to analyze the dependencies of a class source file via a javascript parser.
Will this new syntax require running some watch tool with an AST parser to continuously line up dependencies for synchronous loading?
Hi Chris,
When using ES6 import, the build tooling handles the loading and evaluation of these scripts.
In the case of webpack this loading is via a “bundle” file and the contained modules are executed in proper dependency order. from there This is largely invisible in the debugger due to source maps. SystemJS (an alternative to webpack) uses normal, async loading of source code but it then schedules the execution of the modules to respect their import order.
So, bottom line then is that while the syntax looks like synchronous loading, it is only really sequential evaluation that is going on.
Yes, a watch process will be an option to keep things up to date on disk.
I am really excited about the move to support the newer es standards. I am hoping that you post early access releases as soon as possible because this will effect our maven/sencha cmd build process and much of new code.
Nice to see Sencha working seriously to Make ExtJS Great Again :-) Just kidding, ExtJS never stopped being great.
Looking forward for learning more in Vegas.
MEGA = Make ExtJS Great Again !!
MEGA = More ExtJS Greatness Ahead :)
@David, @Edouard,
Thanks for the kind words.
We’ll have lots more info at and then after SenchaCon. We will get bits out as soon as things are baked enough. Stay tuned and thanks for the feedback.
Hope to see you there!
Does it means that a transpiler will be integrated in the “standard” SenchaCmd build process?
If this is the case, it’s a good news!
Yes, the output language is configurable for production/testing builds (not in dev mode where we load files individually). The language level support and polyfills are coming from Google’s Closure Compiler (see https://github.com/google/closure-compiler/wiki/ECMAScript6 for more details).
Cmd 6.5 has its own minifier to replace YUI. This is currently the only minifiier that does not require you to transpile down to ES5 first. So that means you can opt-out of transpiling for production and leave your ES6 code “as is”… when that makes sense for your target browser(s).
Is the new minifier a brand-new effort or is it based on some previous work? Just curious.
It’s a new compressor similar in spirit to YUI – just renames locals and does some other minor minifications. Slightly better compression on ext-all.js than YUI and can operate on pure ES6 w/o transpilation :)
Hey @Don Griffin,
great to hear that Ext is embracing the vivid JavaScript ecosystem!
There is a ES6 aware minifier based on Babel (supported by Babel team), so IMO no need to reinvent the wheel: https://github.com/babel/babili
Sebastian
Follow up: I just noticed that Closure Compiler also supports ES6.
So what’s the advantage of your own minifier over using Closure (or Babili)
Sebastian
Hi Sebastian,
As it currently sits, Closure’s compressor has two issues. First, its renamer breaks a couple things due to eval() usage. Second, you have to transpile to ES5 in order to compress the code. The Cmd minifier works against the full ES6 tree.
I haven’t looked at the Babel compressor yet because we don’t provide Node.js with Cmd and also do not require it as a system dependency. One could just use Cmd to produce a testing build and then run any compressor against the output, but in testing using uglify, it was significantly slower the YUI (which is on par with the new Cmd compressor).
We will be looking at Node.js-based solutions more closely for our next major release of build tools that we announced at SenchaCon, so stay tuned for details there.
And thanks for the feedback :)
Hi, I’m just wondering if it would be possible to enable transpilation (with sourcemaps) in dev mode for those of us who are still in an IE11 environment?
Also, when Sencha Build comes out, will it be possible to plug into it to add for example ESlint as part of the pre-compilation process? Thanks.
Hi Niall,
Source maps are a key part of why we are working on Sencha Build. Since that tool set will integrate with the Node.js and webpack build environment, all those things will be possible.
Unfortunately, Sencha Cmd does not support source maps, and even in 6.5 (where it does support transpilation) that is still the case.
Thanks for the great questions!
Best,
Don
Hi Don!
Hope you’re doing well!
Any updates or plans on this topic?
Thanks
Can I use ES6 modules right now to create a Grid with the recent release of ExtJS 6.5? Where can I find the documentation on using ES6 in ExtJS 6.5? What’s the final module naming structure? Is there documentation available for this?
In Ext JS 6.5 and Sencha Cmd 6.5 (https://www.sencha.com/blog/announcing-ext-js-6-5-and-sencha-cmd-6-5-ga) you can use pretty much all the ES6 syntax, but support for ES6 modules is a version 7 thing.
Thanks for the great question!
Will it be possible to use Chrome to debug using the original ES6 file even though the browser is really using a transpiled ES5 version? In other words, I would not want to be debugging through code that I didn’t directly write.
Hi Guoneng,
Yes, with the v7 tools we will support source maps (most likely using Babel) so you will be able to debug in the source instead of the transpiled output.
Reading this post it would appear that as of ExtJS 7 we can use standard JavaScript class syntax ? Am I correct on this?
We are very supportive of all efforts you make towards standardization with respect to language features. Keep up the good work!
best
Mark
Any chance we will be able to build ExtJS app without sencha cmd, but with WebPack/Rollup?
This is the best way that we are knowing here.