Sencha recently announced the general availability of ExtJS 6.2. People who regularly read my posts (hi, to all three of you. 😉 will be aware that I’ve been working with the ExtJS library for a number of years now, while building a suite of apps of some not inconsiderable size1. It’s probably not the largest ExtJS app in the world, but it’s up there. And when you work on an application for a number of years, you’ll need to upgrade its framework from time to time.
Every time I’ve done this, the process has been a bit different. This time, it’s different in a good way – it was easy.
Sencha CMD improvements – sencha framework
One of the reasons it was easier this time around is that Sencha snuck a new feature into Sencha CMD 6.1. For those who don’t know, Sencha CMD is the build tool that Sencha recommends using with ExtJS. It evaluates which files you use in your project (both your own files, and the framework ones), and produces a custom minimised version of the JavaScript and CSS files for your project. It’s not the only such tool around, and you don’t have to use it, but it’s easier to use it than not.
I didn’t notice the new feature at the time, as it was announced back in June and I only bother doing CMD updates when I do framework updates. Furthermore, ExtJS 6.2 comes with Sencha CMD 6.2 – making it even easier to not notice the new feature. That said, I’m glad I did notice it, because the new framework
command suite makes life a lot easier.
I use a workspace to manage the suite of apps I work on. Up until June, it was only possible to have one ExtJS framework in your workspace. That meant to do an upgrade, I had to delete the old framework, install the new one, and update all of my apps in one fell sweep. This was further complicated by the fact that I called my framework by version number – e.g. ${workspace.dir}/ext-6.0.0
instead of ${workspace.dir}/ext
; I guess I like making my life harder for myself.
Now, however, I’ve got full support for having multiple frameworks in my workspace. Sure, in the long run, I’ll only have one at a time, but during transition periods, this is fantastic.
Step 1 – Upgrade my workspace and app to Sencha CMD 6.2
Your workspace knows what version of the CMD tool you use to build it. So you have to upgrade that first. So – after installing the new CMD version, but before installing the new framework version – I ran sencha package upgrade
and sencha app upgrade
in each of my packages and applications. In hindsight, I could have just done sencha workspace upgrade
, but I didn’t think of it at the time.
I do this step separately, because I also need to update my build server to the new CMD version, and inform my team. Updating to the new CMD version is something I do a week or so before I update the frameworks, just to make sure there aren’t any complications from that step. Fortunately, you can use newer versions of CMD to build older versions of ExtJS (just not the other way around).
Step 2 – Make your workspace aware of the framework you already have.
If you’re upgrading, you’ve already got a framework that you are using. Maybe you’ve used the default of ${workspace.dir}/ext
, or maybe you’ve used the ext.dir
property in ${workspace.dir}/.sencha/workspace/sencha.cfg
to specify where your ExtJS libraries live. What you need to do here is make your workspace aware of the frameworks.
The easy way to do this is with the sencha framework add
command. Simply specify the path to your ExtJS library – twice. Once to say where you’re copying from, and once to say where you want it to live.
# Assuming you have your ExtJs library in your workspace, in a folder called ext-6.0.0 $ sencha framework add ext-6.0.0 ext-6.0.0 Sencha Cmd v6.2.0.103 [INF] Added framework ext6 to workspace.json
This adds the following block of text to your workspace.json
file:
"frameworks": { "ext6": { "path":"ext-6.0.0", "version":"6.0.0.640" } },
Then you can remove the ext.dir
property from your ${workspace.dir}/.sencha/workspace/sencha.cfg
file.
You can then test this using sencha workspace upgrade
.
What you’ll probably see is output like this:
$ sencha workspace upgrade Sencha Cmd v6.2.0.103 [INF] Upgrading metadata of 4 applications [INF] Upgrading metadata of application: IesExpert [INF] Downloading package "ext@6.0.0.640"; [INF] Downloading : .....^C
If you see that, kill the upgrade; you don’t want to download ExtJS again. What you need to do instead is tell your applications and packages that they are using ExtJS 6 – in particular, the ext6 framework you’ve defined in your workspace.json
. To do this, you need to edit each of your app.json
and package.json
files (for applications and packages respectively), replacing (or inserting, if needed) the framework
value from ext
to ext6
.
/** * The Sencha Framework for this application: "ext" or "touch". */ "framework": "ext6",
Once that is done, you can do sencha framework list
, and it will show you all of the frameworks in your workspace, along with which applications use it. (It doesn’t list the packages, which is a nuisance). If all of your apps are showing, you can then test the sencha workspace upgrade
command again.
$ sencha framework list Sencha Cmd v6.2.0.103 Workspace located at: <your workspace directory>; Available frameworks - ext6: (Commercial) - Framework: Ext JS - Version: 6.0.0.640 - Path: ext-6.0.0 - Used by 4 applications: <list of your applications>
Okay, that was a moderate bit of work, largely needed because I didn’t find a way to get Sencha CMD to do this for me. However, it takes less time to do that it took me to write it out. Note that if you’ve kept the default framework name of ‘ext’, you may not need all of this.
Step 3 – Add the new framework
Okay, let’s add the new framework. That’s the beauty of this part.
I assume you’ve downloaded Ext 6.2 locally to a tmp directory or similar – someplace not in your application. Given that, all you need to do is this:
$ sencha framework add <path to tmp dir>/ext-6.2.0 ext-6.2.0 Sencha Cmd v6.2.0.103 [INF] Copying framework to <workspace dir>/ext-6.2.0 [INF] Added framework ext62 to workspace.json
You now have two versions of ExtJS in your workspace – something you can verify with sencha framework list
. This will also reveal that the framework key is ext62
. Now it’s time to upgrade your apps and your packages. Let’s do packages first.
Actually upgrading
To upgrade your packages, update the ‘framework’ property in package.json
from ext6
to ext62
, then do sencha package upgrade
followed by sencha package build
. In my case, this revealed that I needed to re-apply an update to font-awesome, which was a nice find. (I’m using Font-Awesome 4.6, while Ext 6.2 comes with 4.4)
Finally, for each application, you simply run sencha app upgrade ext62
. The latter is the framework you want to upgrade too – why it’s only the app upgrade
subcommand that gets this love and not the package upgrade
or workspace upgrade
, I don’t know.
Warning: This will create an ext
framework (no version number) in your workspace. However, it doesn’t make your application use it.
I’d also recommend doing a sencha app refresh
, followed by sencha app upgrade
.
You can now shakedown and otherwise test your applications one at a time to ensure they work correctly with the new framework. When you’re finally ready, you simply remove the old framework (as well as the ext
one created as a side-effect, if necessary), using sencha framework remove ext6
.
What looks promising in ExtJS 6.2
There are a number of things worth looking at in the release notes and upgrade notes. Here’s a quick summary of some of the things that appeal to me:
- Object Destruction
- ExtJS objects will set all their properties to null during the destroy() method now; we don’t have to do that ourselves. Generally, this will probably mean that we won’t need destroy handlers at all.
- Actions
- They’ve made using Actions with ViewControllers better, with support for declaring actions inside the ViewController directly to be shared with views. This, in turn, will probably influence how we wire up UI components (e.g. button handlers) – but they don’t give examples in the release notes, so I need to investigate this more.
- Improvements to Data Binding
- They’ve made data binding more flexible, include the ability to insert a breakpoint.
- Declarative Key Binding
- Historically, key binding in ExtJS has been shitty. The new approach – especially combined with the new declarative Actions – makes it look a lot simpler, at least within a dialog.
- Better Drag Drop
- There appears to be a better drag-drop API. This is a new API, which will ultimately replace the old API, so we’ll need to consider moving over at some point.
- ViewModels for Grid Rows
- You can now have a view model for an individual grid row – this can be used in cell widgets (and the new row-level widgets).
- Sort at Grid level, not Store
- Oh, this is nice… you can now sort in Grids without impacting the store. You do this by providing a custom sorter configuration to the column. Need to investigate this some more – sometimes we want sorts to update the backing store, but most of the time we don’t. Importantly, though, you can use this to sort on a field that’s not what you see on screen. Which can be useful.
- Dynamic Theming via CSS Variables
- The Fashion framework introduced in Ext6.0 has been updated to include the new CSS 3.0 ‘Css Variables’ feature (available in all modern non-Microsoft browsers). This allows for changing CSS dynamically – we could, in theory, use it to have user-specific styling (such as corporate color theming). Previously, if we’d wanted that, we would have had to had multiple builds for the CSS style sheets, and downloaded the one we wanted. I’m not sure how ready our CSS themes are ready for this sort of change, but it’s certainly something to keep in mind.
Problems with the Upgrade
This was the smoothest ExtJS upgrade I’ve been through, and I’ve done four now (one a year). But it’s not completely smooth. So far, I’ve found three bugs:
- a problem with the zIndexManager. If you are sending components to the front manually, it’s possible that the load mask may not be set up properly. This causes a crash. A simple override fixes this:
Ext.define('MyApp.override.ZIndexManager', { override: 'Ext.ZIndexManager', privates: { syncModalMask: function(comp) { // ExtJS 6.2.0.981 has a bug where it doesn't look to see if the mask is rendered before trying to sync it. That's // not the best thing. Here's a tentative fix: do nothing if the mask doesn't have a target. if (!this.mask || !this.mask.maskTarget) { return; } this.callParent(arguments); } } }, function() { if (Ext.getVersion('core').getShortVersion() !== '620981') { console.warn("EXTJS Version has been updated from 620981. This bug should have been fixed in 6.2+. Check please!") } })
- we had some tables that for some reason had a
hbox
layout internally. Well, grids don’t work with that correctly anymore, and this causes a crashing bug. The simple fix was to remove the layout (it was stupid, anyway) -
the private
selected
property ofSelectionModel
classes is now a Bag instead of a Collection. We had some code that was naughty and accessed it directly. We fixed that up to go through thegetSelection()
method instead.
Summary
Once I put in the new framework support, this was the smoothest update I’ve done. Not perfect, but a lot better than previously.
- ~60KLOC over ~500 files, plus another ~105KLOC of test code over 285 files. ↩