Sencha Ext JS 7.7 is Here – Discover What’s New and Exciting – LEARN MORE

Create a Smooth Loading Experience for Large Enterprise Apps with Sencha Cmd

August 23, 2017 180 Views
Show

Large enterprise applications often include millions of lines of code, and offer many specialized features for different constituencies. While these apps are crucial to the business, they can also get a reputation for loading slowly and offering poor performance to users.

All of the functionality is important, but very few individual users will utilize all of that functionality. In fact, on any given day or interaction with the app, a user will typically use just a small subset of it. They likely only care about how the app behaves on their particular client or device, for example, and the functionality related to whatever task they happen to be performing.

You could break the app into smaller, more focused apps but that forces users to remember which app does what they need. A better approach is to keep everything in the same app but improve it, so different functionality can be loaded only when it’s needed. Users have access to everything they need, without getting bogged down by the parts they won’t use.

Ext JS has long supported the concept of packages which provide modular functionality such as resources, styling, and code. Those packages have typically been incorporated by Sencha Cmd at build time, which doesn’t enable developers to control the user experience dynamically.

Dynamic Package Loading with Sencha Cmd 6.5

With Sencha Cmd 6.5, we’ve added support for dynamic package loading – enabling developers to better control the startup time and network footprint of their apps. Developers still define which packages are used by the app, but Sencha Cmd can now work with a dynamic package loader class that manages dependencies at build time, but it doesn’t force apps to load all the packages at startup. Instead, the developer can implement logic that loads packages – with any necessary dependencies loaded automatically – at an appropriate time in the application workflow. For example, a resource-heavy data visualization might be loaded only on a large screen and when the user activates the appropriate menu or tab. On devices with small screens, a different package might be loaded.

The rest of this post will use a simple sample app to show how you can leverage dynamic package loading in your own apps.

Example App Walkthrough

Our sample app is available on GitHub. If you clone the repo, it will contain everything you need except for the Ext JS bits. Please follow the instructions in the project’s README if you’d like to run it yourself.

If you’re adding dynamic package loading to your own app, you’ll need to start with a package to add. Probably the easiest place to start is creating a new package with Sencha Cmd:

sencha generate package -require NewDevCard

Where “NewDevCard” is the name of the package, and we’ve used the -require option to avoid automatically adding the package to the requires array in the project’s app.json. Packages included in the requires array will be automatically loaded at startup – exactly what we’re trying to avoid.

Instead, we’ll add our dynamic package loader to the requires array in our project’s app.json:

"requires": [
     "package-loader"
],

Now, we’ll add the package to the “uses” array:

"uses": [
     "NewDevCard"
],

The Ext.Package.load() method then makes it trivial to load packages when you’re ready for them. The package loader handles the package’s JavaScript and CSS assets as well as recursively loading any packages that it may require.

In our sample app, we load the package when the user opens a tab which uses the package. Most of the code goes into the controller, which we’ll detail below. In the view, we add a property pkg to the config object for the panel displayed in the tab (from view/main/Devcards.js):

}, {
    // the contact tab using data from the developer record
    xtype: 'panel',
    pkg: 'NewDevCard',
    layout: 'fit',
    title: 'ContactFromPkg'
}

The pkg property doesn’t have any special significance; we just coded the controller to use that property as an indication that the panel uses a dynamically-loaded package.

The controller (view/main/MainViewController.js) contains the bulk of the package-handling code. We use the requires array to ensure the package loader is available:

requires: [
     'Ext.Package'  // from "package-loader"
],

We set up a handler for tab activations which ensures that the package is appropriately loaded:

onItemActivate: function(sender, value, oldValue, eOpts) {

    let tabpanel = sender;
    let tab = value;
    let pkg = tab.pkg;

    if (pkg) {
        if (Ext.Package.isLoaded(pkg)) {
            this.handlePackage(pkg);
        } else {
            tabpanel.setMasked({
                message: 'Loading Package...'
            });

            setTimeout(()=>{
                Ext.Package
                .load(pkg)
                .then(this.handlePackage.bind(this, pkg));
            }, 250);
        }
    }
}

If the tab we’re activating has the pkg property set, we first check whether the specified package is loaded. If not, we mask the tab and use Ext.package.load() to load the package. When it’s available, we use this.handlePackage() to activate the loaded package.

handlePackage: function(pkg) {
    let tabpanel = this.lookupReference('main-tabpanel')
    let tab = tabpanel.child('[pkg=' + pkg + ']');

    tabpanel.setMasked(null);

    //only add item if the item isn't already added
    if (!tab.hasPkgItem) {
        tab.hasPkgItem = true;

        tab.add({
            xclass: 'MyApp.view.' + pkg.toLowerCase() + '.Main'
        });
    }
},

First, we identify the correct tab and unmask it. Unless we have already processed the package for the tab, we add the MyApp.view.newdevcard.Main xclass to the tab to activate the package code.

In terms of coding, that’s basically all that’s needed:

  • In app.json, require package-loader and use the package (NewDevCard).
  • In the controller, require Ext.package and add some logic, so Ext.package.load() loads the package at an appropriate time.
  • Use the newly-loaded package in the app.

Now we just need to build and package up the app. The normal way of making a development build is with sencha app build --dev. This includes packages specified in the requires array, ensuring that everything is included. When using dynamic package loading, we need to add the --uses option to ensure that the packages specified in the “uses” array are also included in the build.

The following command will perform a full development build of the application, including (but not automatically loading) all of its external packages:

sencha app build --dev --uses

The application and each of the use packages will be placed in separate bundles. When your application loads, it will include only its code and the code from its require packages. The JavaScript, CSS, and resources for the use packages will be in the application’s build folder just like images or other assets.

Running the dev server as usual, with

sencha web start

will automatically serve up the app and handle asset dependencies and use packages as required. In production scenarios, you can include the bundled packages along with your other assets to be served up by your production server.

See It In Action

To see the dynamic loading feature in action, try firing up our example app and open a developer profile. When you open the “CONTACTFROMPKG” tab for the first time, the app will dynamically load the NewDevCard package and display the profile’s contact info.

Sencha Cmd - Dynamic Package Loader

By encapsulating functionality into separate packages and leveraging dynamic package loading, you can significantly improve application responsiveness and footprint. Your users will enjoy a superior user experience, and will no longer be forced to wait for every byte of your application to load when they really only need about 20% of it. You will also save time during development and testing by reducing load times and enabling Sencha Cmd to more efficiently load and watch “dev” builds.

coming soon

Something Awesome Is

COMING SOON!