0

Assume you have built (coded) your MVC Sencha Touch App with a bunch of Views, Controllers, Models, Stores, Utils etc...

Whats the best way to "build" the application for production use?

Tasks would be:

  • Concat and minify all JS Source Files
  • Concat and minify Stylesheets (basically running Compass with production environment)
  • Remove not needed folders

Has anyone done this yet with either JSBuilder or Apache Ant? I find the JSBuilder solution integrated with the Sencha Touch lib quite buggy and undocumented. Apache Ant would perfectly fit in with "bigger" build- or CI-systems like Jenkins but I miss a good example how to achive this with a Sencha Touch app.

So the question is, how should a build script for Sencha Touch look like?

fbrandel
  • 1,605
  • 3
  • 17
  • 18

1 Answers1

2

EDIT: Warning: this is an old answer, today there might be better ways to do this. Modern build tools for javascript have come a long way since 2011.

I actually did just this today.

First I considered using sprockster, since I liked the c/c++ include style of defining script dependencies.

I ended up using Apache ant because some of my team members are somewhat afraid of ruby. Apache ant also seemed like a more universal and well documented tool.

I haven't figured out how to build the sass files automatically just yet, but that shouldn't be too difficult.

The process i use is kind of simple:

  1. concatenate all js files and place them in the build folder
  2. minify all js files in the build folder and rename them *-min.js
  3. copy all required files to the dist folder (including images, sencha-touch.js, index file etc)

This is what i ended up with:

<project name="ProjectApp" default="dist" basedir=".">
    <description>
        Project Manager build file
        dist-debug is the target that's best for debugging
        Run ant dist-debug to build the project
    </description>
    <!-- set global properties for this build -->
    <property name="src" location="src"/>
    <property name="lib" location="lib"/>
    <property name="build" location="build"/>
    <property name="dist"  location="dist"/>
    <property name="utils"  location="utils"/>
    <property name="img"  location="img"/>

    <target name="init">
        <!-- Create the build directory structure used by compile -->
        <mkdir dir="${build}"/>
    </target>

    <target name="concatenate" depends="init" description="Concatenate all js files">
        <concat destfile="${build}/application.js" fixlastline="yes">
            <fileset file="${src}/js/app.js" />
            <fileset file="${src}/js/observablize.js" />
            <fileset file="${src}/js/config.js" />

            <!-- Models -->
            <fileset file="${src}/js/models/Project.js" />
            <fileset file="${src}/js/models/ProjectInformation.js" />
            <fileset file="${src}/js/models/Picture.js" />
            <fileset file="${src}/js/models/Milestone.js" />
            <fileset file="${src}/js/models/Risk.js" />
            <fileset file="${src}/js/models/data.js" />
            <fileset file="${src}/js/models/Invoice.js" />
            <fileset file="${src}/js/models/Customer.js" />
            <fileset file="${src}/js/models/OpenItem.js" />
            <fileset file="${src}/js/models/favorites.js" />
            <fileset file="${src}/js/models/mockObjects.js" />

            <!-- Database -->
            <fileset file="${src}/js/database/createTables.js" />
            <fileset file="${src}/js/database/database.js" />
            <fileset file="${src}/js/database/projectObserver.js" />

            <!-- Network -->
            <fileset file="${src}/js/network/network.js" />
            <fileset file="${src}/js/network/queries.js" />
            <fileset file="${src}/js/network/parseProjectServiceProject.js" />
            <fileset file="${src}/js/network/parseQueryEngineProjects.js" />
            <fileset file="${src}/js/network/parseDocArchiveSearchResponse.js" />
            <fileset file="${src}/js/network/parseDocArchiveDataResponse.js" />
            <fileset file="${src}/js/network/parseQueryEngineInvoices.js" />
            <fileset file="${src}/js/network/parseQueryEngineCustomer.js" />

            <!-- Views -->
            <fileset file="${src}/js/views/Viewport.js" />
            <fileset file="${src}/js/views/XTemplates.js" />
            <fileset file="${src}/js/views/Login.js" />
            <fileset file="${src}/js/views/ProjectList/ActionSheet.js" />
            <fileset file="${src}/js/views/ProjectList/ProjectView.js" />
            <fileset file="${src}/js/views/ProjectList/ProjectList.js" />
            <fileset file="${src}/js/views/ProjectList/ProjectsLists.js" />
            <fileset file="${src}/js/views/ProjectInfo.js" />
            <fileset file="${src}/js/views/ProjectRisks.js" />
            <fileset file="${src}/js/views/ProjectMilestones.js" />
            <fileset file="${src}/js/views/ProjectDetail.js" />
            <fileset file="${src}/js/views/Overlays.js" />

            <!-- Controllers -->
            <fileset file="${src}/js/controllers/login.js" />
            <fileset file="${src}/js/controllers/projects.js" />
        </concat>
    </target>

    <target name="compress" depends="concatenate" description="Compress application.js to application-min.js">
        <apply executable="java" parallel="false">
            <filelist dir="${build}" files="application.js" />
            <arg line="-jar" />
            <arg path="${utils}/yuicompressor-2.4.6.jar" />
            <srcfile />
            <arg line="-o" />
            <mapper type="glob" from="*.js" to="${build}/*-min.js" />
            <targetfile />
        </apply>
    </target>

    <target name="dist-debug" depends="concatenate" description="generate the distribution">
        <!-- Create the distribution directory -->
        <mkdir dir="${dist}"/>

        <!-- copy over the required files -->

        <!-- required libraries -->
        <!-- sencha touch -->
        <copy file="${lib}/sencha-touch/sencha-touch.js" todir="${dist}"/>

        <!-- stylesheet -->
        <copy file="${build}/application.css" todir="${dist}"/> 

        <!-- index file -->
        <copy file="${src}/index.html" todir="${dist}"/>

        <!-- manifest file -->
        <copy file="${src}/cache.manifest" todir="${dist}"/>

        <!-- app javascript -->
        <copy file="${build}/application.js" tofile="${dist}/application.js"/>

        <!-- images -->
        <copy file="${img}/icon.png" todir="${dist}"/>
        <copy file="${img}/startup.png" todir="${dist}"/>
        <copy file="${img}/disclosure.png" todir="${dist}"/>

    </target>

    <target name="dist" depends="dist-debug,compress" description="generate minified distribution"> 
        <!-- app javascript -->
        <copy file="${build}/application-min.js" tofile="${dist}/application.js"/>  
    </target>   

    <target name="clean" description="clean up" >
        <!-- Delete the ${build} and ${dist} directory trees -->
        <delete dir="${build}"/>
        <delete dir="${dist}"/>
    </target>

</project>

As you can see, I specify every single file in my project. This is just to get the order right. If your code is better written than mine, and don't have any dependencies, you could just include an entire source folder.

bobbaluba
  • 3,584
  • 2
  • 31
  • 45
  • Looks like clean solution, thanks! Now I wonder if it would be possible to parse the index.html to get all needed files in the expected order. This would avoid writing the file paths again to the build.xml. Or I just go with selecting all JS files in the folders.. – fbrandel Aug 06 '11 at 10:22
  • I spent hours googeling for something like that, and I considered writing such a script myself. I found some online tool that does it, but can't remember where. I think the best solution is to always build the project when testing, I wonder if there is an 'compass watch .' equivalent for ant, making it build every time it detects changes in a js file. Initially, you could just do simple search and replace in a text editor to create your fileset for the build.xml – bobbaluba Aug 06 '11 at 10:44