Ext JS 4.2 to Ext JS 6.6 upgrade

15.04.2019.

Upgrades of legacy applications to latest frameworks and versions is often one of the most challenging tasks put in front of software developers. This is especially pronounced when original developers are no longer available and the application has gone through many iterations and upgrades which left the original documentation inaccurate and incomplete.

In the fast changing world of front-end development, we faced with an upgrade of front-end application based from Ext JS 4.2 to the latest Ext JS  6.6 framework. The original application was developed during the time when Internet Explorer was ruling the world, using Ext JS 3.0 and was a decade old. Change requests and enhancements made during that period of time amounted to several times more effort than the original application. With changes of major browsers, HTML5, javascript versions and plugins, the old codebase could not be integrated to any modern javascript library or plugin. The JS world moved on.

To make things more complex, frontend application was not separated as standalone project built through standard node based development environment. Instead it was integrated/bundled as part of backend system developed in Java/Spring framework. That made most of the Sencha documentation and Sencha Cmd examples not directly applicable to the codebase.

Starting with Sencha upgrade guides, the task did not seem that complex. We found a few sources on the Internet who advised to rewrite complete application in some newer framework. Due to incomplete specifications of requirements, that was considered unacceptable risk. There are quite a few listed items (upgrading from versions 4.3 to 5.0 to 5.1 to 6.0), and we tried to follow them to the letter. However, we found that instructions incomplete for the complex application that we had.

At the moment of writing, latest version of Ext JS is 6.6, which means stepping over two major releases, where each of releases have significant changes in component configuration and component default behavior.

Since this is business application, mainly consisting of panes, tab panels and grids, upgrade caused majority of issues with component configuration and data binding. In the following lines are mentioned main challenges and issues which occurred during upgrade ordered subjectively from most to least important.

Grid is now plugin

One of biggest issues was with grid filters, as they have changed from a feature to plugin component. This meant rewriting configuration of grid filter features with different syntax, and we had quite complex filters on almost all columns shown in the application. Below is example of syntax modification in configuration of Year Panel and how yearStatus filter was changed from plugin to cell feature.

Charts moved to separate package

The legacy Ext JS 4 charts have been converted into a separate package. This means that if charts are used within app when upgrading to Ext JS 6 it is mandatory to refactor and include “charts” package as dependency for App.

In order to recrate Ext.chart.Chart component, we had to define Ext component with constructor attribute  xtype: ‘polar’.

Raw is replaced with data

Because of the changes to the data property, there is no longer a separate raw data property tracked on each record. The data object passed to the constructor simply becomes the data property and defaulting and conversions are applied in place.

JSON preserve raw data

Response from Ext.Reader component is now read as rawData, instead as for JSON reader’s jsonData. To achieve legacy behavior, it is necessary to add properties to proxy reader.

preserveRawData: true,
keepRawData: true,

Pass button configuration instead of button object

Ext.Button is not needed when defined in grid item array element. Ext button constructor needs to be removed and plain JSON object configuration should be moved one level up in hierarchy to Item list directly with no constructor.

New store records ID passed as String type

New record id generated as string type instead of integer as previously. For newly created models on user interface, ID is generated as “Com.Class.ModlelName@-1” instead of -1. This was in our case resolved on server side.

Scrollable property changed

Panel’s configuration attribute for enabling scroll on component is renamed. Instead of autoScroll configuration parameter in Ext 4, parameter scrollable was introduced in Ext JS 6 configuration. Also this parameter needs to be applied only while creating component, in root level of Ext.Create method. If it is defined in initComponent function, element will not be scrollable, unlike in Ext JS 4 where it was working.

 Default behavior of modified data and fields changed

In Ext JS 4 by default if data for some object in grid plugin was modified and saved, whole object was sent to backend and updated. In Ext JS 6 only data ID and changed properties are being sent, which is not enough for our background logic.

To fix this behavior, property should be added to writer in stores’ proxy object:

writeAllFields: true

Apply vs applyIf

Majority of our components used additional post configuration code using call to Ext.applyIf function inside of initComponent handler. This code sometimes would fail in very strange way, by not applying post-configuration changes. We solved most of these cases by replacing this function with unconditional apply function.

Ext.require and Ext.syncRequire

Legacy application was developed without proper npm/node development environment, so we missed all the goodies of autoconfiguration and module loading mechanism that is setup by Sencha Cmd and well defined in the developer guide.

Thus we had to refactor whole Ext initialization process and perform whole module loading procedure ourselves. Major change was a default asynchronous method of resolving modules that need to be downloaded from the server, which represented a major issue for our code base. It was solved by changing and modifying order of Ext.require calls. In some cases, code dependencies mandated changes to immediate module loading (syncRequire), which slowed down whole application loading process. We wanted to avoid separation of front-end and backend source code into separate projects. This was a mistake. Although we wanted to minimize the time spent on migration, it required a lot of fiddling until we found a proper sequence.

Conclusion

These are main changes which affected whole application and each of issue could result with changes on dozens of files, based on application size. Still there are numerous smaller issues, manifested either on user interface or data binding, which were resolved with backend in css, or JS/HTML directly. Also, all plugins/custom plugins need to be updated to Ext JS 6 compatible version, since in our case, none of them worked by default.

Good luck with upgrade! 😊