Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Load app.js before rest of application

I'm trying to figure out how I can load app.js before allowing the user to get the actual application. What I'm attempting to do is load a user's configuration file before all of my class Ext.defines fire... the reason I want to do this is because the Ext.defines actually depend on values in the user's configuration. So for example, in an Ext.define, I could have the title property set to pull from this global user configuration var. And no, I don't want to have to go through and change all of these properties to use initComponent... that could take quite some time.

Instead, what I'd like to do is load the configuration, and then let the Ext.defines run, but I will need Ext JS and one of my defined classes to be loaded before the rest of the classes. Is this possible? I've been looking into Sencha Cmd settings, but I've been extremely unsuccessful with getting this to work. I was playing with the bootstrap.manifest.exclude: "loadOrder" property, which loads classic.json, and doesn't define my classes, but unfortunately, that also doesn't fully load Ext JS, so Ext.onReady can't be used... nor can I use my model to load the configuration.

I have a very high level example below (here's the Fiddle).

Ext.define('MyConfigurationModel', {
    extend: 'Ext.data.Model',
    singleton: true,

    fields: [{
        name: 'testValue',
        type: 'string'
    }],

    proxy: {
        type: 'ajax',
        url: '/configuration',
        reader: {
            type: 'json'
        }
    }
});
// Pretend this would be the class we're requiring in our Main file
Ext.define('MyApp.view.child.ClassThatUsesConfiguration', {
    extend: 'Ext.panel.Panel',
    alias: 'widget.classThatUsesConfiguration',
    /* We get an undefined value here because MyConfigurationModel hasn't
     * actually loaded yet, so what I need is to wait until MyConfigurationModel
     * has loaded, and then I can include this class, so the define runs and
     * adds this to the prototype... and no, I don't want to put this in
     * initComponent, as that would mean I would have to update a ton of classes
     * just to accomplish this */
    title: MyConfigurationModel.get('testValue')
});
Ext.define('MyApp.view.main.MainView', {
    extend: 'Ext.Viewport',
    alias: 'widget.appMain',
    requires: [
        'MyApp.view.child.ClassThatUsesConfiguration'
    ],
    items: [{
        xtype: 'classThatUsesConfiguration'
    }]
});
Ext.define('MyApp.Application', {
    extend: 'Ext.app.Application',
    mainView: 'MyApp.view.main.MainView',
    launch: function() {
        console.log('launched');
    }
});

/* In app.js... right now, this gets called after classic.json is downloaded and
 * after our Ext.defines set up, but I basically want this to run first before
 * all of my classes run their Ext.define */
Ext.onReady(function() {
    MyConfigurationModel.load({
        callback: onLoadConfigurationModel
    })
});
function onLoadConfigurationModel(record, operation, successful) {
    if (successful) {
        Ext.application({
            name: 'MyApp',
            extend: 'MyApp.Application'
        });
    }
    else {
        // redirect to login page
    }
}
like image 701
incutonez Avatar asked Mar 09 '23 15:03

incutonez


1 Answers

I call this "splitting the build", because it removes the Ext.container.Viewport class's dependency tree from the Ext.app.Application class. All Ext JS applications have a viewport that is set as the main view. By moving all requires declarations of the core of the application to the viewport class, an application can load the viewport explicitly from the application class, and the production build can be configured to output two separate files, app.js and viewport.js. Then any number of operations can occur before the core of the application is loaded.

// The app.js file defines the application class and loads the viewport
// file.
Ext.define('MyApp.Application', {
   extend: 'Ext.app.Application',
   requires: [
      // Ext JS
      'Ext.Loader'
   ],
   appProperty: 'application',
   name: 'MyApp',

   launch: function() {
      // Perform additional operations before loading the viewport
      // and its dependencies.
      Ext.Ajax.request({
         url: 'myapp/config',
         method: 'GET',
         success: this.myAppRequestSuccessCallback
      });
   },

   myAppRequestSuccessCallback: function(options, success, response) {
      // Save response of the request and load the viewport without
      // declaring a dependency on it.
      Ext.Loader.loadScript('classic/viewport.js');
   }
});

-

// The clasic/viewport.js file requires the viewport class which in turn
// requires the rest of the application.    
Ext.require('MyApp.container.Viewport', function() {
   // The viewport requires all additional classes of the application.
   MyApp.application.setMainView('MyApp.container.Viewport');
});

When building in production, the viewport and its dependencies will not be included in app.js, because it is not declared in the requires statement. Add the following to the application's build.xml file to compile the viewport and all of its dependencies into viewport.js. Conveniently, the development and production file structures remain the same.

<target name="-after-js">
   <!-- The following is derived from the compile-js target in
        .sencha/app/js-impl.xml. Compile the viewport and all of its
        dependencies into viewport.js. Include in the framework
        dependencies in the framework file. -->
    <x-compile refid="${compiler.ref.id}">
        <![CDATA[
            union
              -r
              -class=${app.name}.container.Viewport
            and
            save
              viewport
            and
            intersect
              -set=viewport,allframework
            and
            include
              -set=frameworkdeps
            and
            save
              frameworkdeps
            and
            include
              -tag=Ext.cmd.derive
            and
            concat
              -remove-text-references=${build.remove.references}
              -optimize-string-references=${build.optimize.string.references}
              -remove-requirement-nodes=${build.remove.requirement.nodes}
              ${build.compression}
              -out=${build.framework.file}
              ${build.concat.options}
            and
            restore
              viewport
            and
            exclude
              -set=frameworkdeps
            and
            exclude
              -set=page
            and
            exclude
              -tag=Ext.cmd.derive,derive
            and
            concat
              -remove-text-references=${build.remove.references}
              -optimize-string-references=${build.optimize.string.references}
              -remove-requirement-nodes=${build.remove.requirement.nodes}
              ${build.compression}
              -out=${build.out.base.path}/${build.id}/viewport.js
              ${build.concat.options}
            ]]>
    </x-compile>

    <!-- Concatenate the file that sets the main view. -->
    <concat destfile="${build.out.base.path}/${build.id}/viewport.js" append="true">
       <fileset file="classic/viewport.js" />
    </concat>
</target>

<target name="-before-sass">
    <!-- The viewport is not explicitly required by the application,
         however, its SCSS dependencies need to be included. Unfortunately,
         the property required to filter the output, sass.name.filter, is
         declared as local and cannot be overridden. Use the development
         configuration instead. -->
    <property name="build.include.all.scss" value="true"/>
</target>

This particular implementation saves the framework dependencies in their own file, framework.js. This is configured as part of the output declaration in the app.json file.

"output": {
   ...
   "framework": {
      // Split the framework from the application.
      "enable": true
   }
}

https://docs.sencha.com/extjs/6.2.0/classic/Ext.app.Application.html#cfg-mainView https://docs.sencha.com/extjs/6.2.0/classic/Ext.container.Viewport.html https://docs.sencha.com/cmd/guides/advanced_cmd/cmd_build.html#advanced_cmd-_-cmd_build_-_introduction

like image 184
Trevor Karjanis Avatar answered Mar 20 '23 21:03

Trevor Karjanis