/** * @class Cmd.codebase.json.JS * @extend Cmd.codebase.json.Asset * These configs apply to JavaScript assets defined in the "js" array. The "js" array * contains entries for each script that needs to be loaded as part of the application. * * The starter app template (default template) includes two scripts on the "js" array: * * "js": [{ * "path": "${framework.dir}/build/ext-all-rtl-debug.js" * }, { * "path": "app.js", * "bundle": true * }] * * The first entry is added to increase the speed of the development version, since it * loads all Ext JS classes (even with right-to-left support) at once from a single js * file instead of loading each from its own source file. * * Any entries in the "js" array that point to files inside the framework directory will * not be included in the final build output. * * The second entry is the entry point of this application. The `bundle` config tells * Sencha Cmd that this script should become the container for the concatenated classes. * The app's "bundle" will be written to `app.js` in the build output folder. * * ## The application bundle * All Ext JS applications make use of classes inside the Framework (for example `Ext.Button` * or `Ext.data.Store`) as well as classes inside its namespace (for example `MyApp.view.Main` * or `MyApp.model.Item`) or even classes that are part of a given package (for example * `MyCompany.common.User` or `ThirdParty.plugin.Widget`). During the build process, all * these classes are identified, listed and sorted according to how they need to be loaded * (in order to transitively satisfy all dependencies). These files are concatenated into * what Sencha Cmd calls the "application bundle". * * You can think of the bundle as file that contains the following (the order is important): * * {all framework classes required by the application} * {all theme-specific overrides} * {all overrides specified by your application} * {all classes inside your app's classpath (typically the "app" directory)} * {all scripts with "includeInBundle": true} * {the contents of the file with "bundle": true (typically app.js)} * * ## Loading additional scripts * Loading additional scripts is as easy as adding them to the "js" array. Take the following example: * * "js": [{ * "path": "foo.js" * }, { * "path": "${framework.dir}/build/ext-all-rtl-debug.js" * },{ * "path": "app.js", * "bundle": true * }, { * "path": "bar.js" * }] * * In this example, `foo.js` will load before the application bundle, where `bar.js` will * be loaded after it. * * Sencha Cmd will copy these files to the build directory and will include them in the * build manifest. When opening the application in the browser, three scripts will be * requested in the following order: * * http://example.com/MyApp/foo.js * http://example.com/MyApp/app.js * http://example.com/MyApp/bar.js * * ## Including scripts in the application bundle * You can instruct Sencha Cmd to include any script in the application bundle by * specifying `"includeInBundle": true` on its entry: * * "js": [{ * "path": "${framework.dir}/build/ext-all-rtl-debug.js" * },{ * "path": "foo.js", * "includeInBundle": true * },{ * "path": "app.js", * "bundle": true * }] * * In this case `foo.js` will be included in the bundle, right before the content of `app.js`. * * You can specify any number of files to be included in the bundle and their order will * be preserved: * * "js": [{ * "path": "${framework.dir}/build/ext-all-rtl-debug.js" * },{ * "path": "foo.js", * "includeInBundle": true * },{ * "path": "bar.js", * "includeInBundle": true * },{ * "path": "app.js", * "bundle": true * }] * * The contents of `${build.dir}/app.js` will now look like this: * * {all framework classes required by the application} * {all theme-specific overrides} * {all overrides specified by your application} * {all classes inside your app's classpath (typically the "app" directory)} * {the contents of foo.js} * {the contents of bar.js} * {the contents of the file with "bundle": true (typically app.js)} * * ### Tweaking the inclusion order * While this may be a desired outcome for most cases, others may require the additional * files to be included _before_ the app bundle or even _between_ the framework classes * and the application classes. Let's see how we can achieve that. * * #### Including scripts *before* the application bundle * As noted before, the application bundle is a Sencha Cmd concept that contains all the * dependencies of the built application in the order they'll be needed. The top-most * requirement are the core framework classes, which have no dependencies. This is why * there's no out-of-the-box way to include scripts *before* other contents in the * application bundle. * * It is however possible to use the underlying ant task hooks to include a script before * the bundle: * * 1. Let's assume you want to include the contents of a file named foo.js, located in the * root directory of the application: * * console.log("I'm foo.js"); * * 2. Add the following task to the application's build.xml file: * * <target name="-after-js"> * <concat destfile="$temp.tmp"> * <fileset file="foo.js"/> * <fileset file="${build.dir}/app.js"/> * </concat> * * <move file="$temp.tmp" tofile="${build.dir}/app.js"/> * </target> * * 3. Build the application * * sencha app build * * 4. The contents of the built app.js will now look like this: * * {the contents of foo.js} * {all framework classes required by the application} * {all theme-specific overrides} * {all overrides specified by your application} * {all classes inside your app's classpath (typically the "app" directory)} * {the contents of the file with "bundle": true (typically app.js)} * * We took this approach instead of just concatenating to the file at the end to make sure * the additional script is also optimized and minified (as part of the normal optimization * and minification process). * * #### Including scripts *between* the framework classes and the application classes * In some cases, you may have some scripts that require the framework to run but need to * be loaded before any of the application classes. Let's check the bundle overview again * (without additional scripts and this time with numbers so we can reference some items * below): * * {(1) all framework classes required by the application} * {(2) all theme-specific overrides} * {(3) all overrides specified by your application} * {(4) all classes inside your app's classpath (typically the "app" directory)} * {(5) the contents of app.js} * * We want some script(s) to be included before (4), because the application classes may * depend on them. * * To achieve this, we can make use of * [Compiler Directives](http://docs.sencha.com/cmd/guides/advanced_cmd/cmd_compiler_reference.html#advanced_cmd-_-cmd_compiler_reference_-_compiler_directives). * Let's take a look at the following example: * * 1. Let's assume you want to include the contents of a file named foo.js, located in the * root directory of the application: * * console.log("I'm foo.js"); * * 2. Let's add the following comment to app/Application.js: * * // @require ../foo.js * * 3. Build the application * * sencha app build * * 4. The contents of the built app.js will now look like this: * * {all framework classes required by the application} * {all theme-specific overrides} * {all overrides specified by your application} * {the contents of foo.js} * {all classes inside your app's classpath (typically the "app" directory)} * {the contents of the file with "bundle": true (typically app.js)} * * While the typical approach of loading files individually when loading the application * may be suitable for most cases, Sencha Cmd provides some alternatives to include * scripts into the concatenated file, either before all other code or once the framework * classes are available (and before the application code is executed). */