Using Sencha Cmd with dynamically loaded controllers
Asked Answered
B

1

9

I've created an application using Ext JS 4. controllers property in my app.js contains only the main controller:

Ext.application({
    name: 'MyApp',
    appFolder: 'app',

    controllers: [
        "main.App"
    ],

    loadController: function(controller) {
        var oController = this.getController(controller);
        oController.init(this);
        oController.onLaunch(this);
    }
});

MyApp.main.App controller loads additional controllers by name using getController() approach (see loadController() method). These controllers are loaded dynamically and are not listed in my index.html file.

In order to generate production version for deployment to server I am using Sencha Cmd by issuing the following command in my application folder:

sencha app build

Tool finishes normally and compresses all files into one big all-classes.js. The problem is that my dynamically loaded controllers are not included in that file.

Which is the correct way to make dynamically loaded controllers (over 100 in total) to be minified and processed by Sencha Cmd?

I know, that I can list them in my app.js, or include in some file using Ext.require, but I am seeking for correct approach for including over than 100 different controllers, views, models and stores automatically in my build. I believe that are other users of Ext JS, which are creating large-scale applications and are building somehow and I'll be grateful for any suggestions or just success stories, which will help me to find the correct way to build.

Backplate answered 22/1, 2013 at 11:27 Comment(0)
Z
7

I would put all controllers into the uses array. These should force the tool to keep track on them and include them into the build. On the other hand uses does not require the class to be available at definition time but guarantee them to be available the time the onReady(one is within the application) block(s) is(are) called.

Note that you will need to use the fully qualified names within the uses array!

I do not use the buildtool therefore I cannot test it but it should work.


Update from the comments example provided by @bhovhannes

bhovhannes: I've added a code in build.xml, which collects all names of my controllers into uses array when I do sencha app build. This way I fill nothing in uses array during development, just add controllers into controller folder, because all them are loaded dynamically from my app

app.js

Ext.application({
    name: 'MyApp',
    appFolder: 'app',

    controllers: [
        "main.App"
    ],

    uses: [
        /*ant-generated-content-start*/ /*ant-generated-content-end*/
    ],

    autoCreateViewport: true,
});

build.xml

<?xml version="1.0" encoding="utf-8"?>
<project name="MyApp" default=".help">
    <import file="${basedir}/.sencha/app/build-impl.xml"/>

    <target name="-before-build">

        <echo message="Collecting all controllers in application class property ... "/>
        <fileset id="app_controllers" dir="${app.dir}/app/controller" casesensitive="yes">
            <include name="**/*.js"/>
        </fileset>
        <pathconvert pathsep="," property="app_controller_names" refid="app_controllers" targetos="unix">
            <chainedmapper>
                <globmapper from="${app.dir}/app/*" to="${ant.project.name}/*" casesensitive="no" handledirsep="yes"/>
                <chainedmapper>
                    <regexpmapper from="^(.*)\.js$$" to='"\1"'/>
                    <filtermapper>
                        <replacestring from="/" to="."/>
                        <replacestring from="\" to="."/>
                    </filtermapper>
                </chainedmapper>
            </chainedmapper>
        </pathconvert>
        <echo message="Collected controllers: ${app_controller_names}"/>

        <echo message="Injecting into app.js ..."/>
        <replaceregexp file="${app.dir}/app/app.js"
                       match="/\*ant-generated-content-start\*/(.*)/\*ant-generated-content-end\*/"
                       replace="/*ant-generated-content-start*/ ${app_controller_names} /*ant-generated-content-end*/"
                       byline="true"
                />
    </target>

    <target name="-after-build">
        <echo message="Reverting to original app.js ..."/>
        <replaceregexp file="${app.dir}/app/app.js"
                       match="/\*ant-generated-content-start\*/(.*)/\*ant-generated-content-end\*/"
                       replace="/*ant-generated-content-start*/ /*ant-generated-content-end*/"
                       byline="true"
                />
    </target>

</project>
Zachary answered 22/1, 2013 at 11:45 Comment(7)
Thanks for link to uses. It can be useful. But that way all my controllers will be included via a huge uses array. And that not only makes development more complicated (each time, when adding a new controller, one should also add it into uses section), but also puts all controllers into all-classes.js, which make dynamic controller loading absolute (why to load dynamically, if controller is already downloaded and is available with all remaining stuff in all-classes.js?)Backplate
@Backplate I see the downside while developing but note that it is just ensured that the class exist. I personally using a serverside driven approach where the frontend is created by user-role. I know that my controllers are already there when I call them and that is all you should care. But I must admit that I am not that used to the Sencha CMD tool. Maybee there is a argument which allow you to include a whole folder into the build process, which may be a solution you are looking for.Zachary
I've added a code in build.xml, which collects all names of my controllers into uses array when I do sencha app build. This way I fill nothing in uses array during development, just add controllers into controller folder, because all them are loaded dynamically from my app.Backplate
@Backplate Can you give further details about what you did precisely in your last comment? Thanks!Susann
@JosvicZammit, have a look to pastebin.com/22AmTU0r and pastebin.com/GCeg1ber. First one is my app.js, second one is my build.xml. All my controllers sits in /app/controller folder and only main.App controller is loaded at startupBackplate
@Backplate Thanks for sharing this! If you don't mind I will add that code to SO so provide a better qualitiyZachary
@Backplate Thanks a million to yourself and @sra, I applied your solution to my problem but unfortunately didn't work out. Still I did learn something anyway, thanks :)Susann

© 2022 - 2024 — McMap. All rights reserved.