Going Remote with Sencha Command

With the introduction of Sencha Touch 2.0.0 GA we got the use of Sencha Command which allows developers to create an app and build an app. Well, not as simple as that as there is more to it than simply creating and building but that's for another blog post maybe. One thing that I try to emphasize is that you not edit index.html. The only exception to my rule is to edit the CSS and HTML for the loading screen but nothing else! No adding <link> elements, <script> elements, nothing! Of course your application may require it but try not to do it.

app.json

app.json is the configuration file that the builder and microloader uses to know really how to work and what to load. What to load, like CSS and JavaScript files? Exactly! There are both js and css properties that tell the builder to copy over to the build folder and setup the microloader to load and possibly save to localStorage. However, there is a flaw with this and is noted in the comment above the js and css properties that the path must be relative to the app.json file. Many apps require the loading of remote sources and one of the more popular ones is the Google Maps API. To load a Google Map you must have a <script> element to load the API but you shouldn't edit index.html and app.json's js property only loads relative files which both mean that there is no way to handle remote files.

Hack

The URL that you need to load for the Google Maps API is likely http://maps.google.com/maps/api/js?sensor=true and if you look at this file you can plainly see that it bootstraps their API and creates a <script> element to load the actual API. You could, in theory (I haven't tested it) create a local file that has this source and it would work but it's a hack and I wouldn't recommend it. Yeah, I have see someone do this and the reason was because they really didn't have any other way to load the Google Maps API before their app was launched which I couldn't blame them for trying it.

Savior

I haven't dug into the source for Sencha Command and the microloader (Ext.blink) so I took it upon myself to jump head first to implement a way to load remote files using a simple config in app.json. I wanted to add a simple and descriptive config to the config objects you can put into the js array and the "remote" config was born. This config would mark that resource as being a remote file and accepts true or false (defaults to false, well, undefined really but it's falsey so the same in this instance).

Sencha Touch 2.0.2

First thing I notice while digging into Sencha Command was that it copies the files to the build folder in a couple places. A few if statements and solved that issue. Tested and things were working great! I didn't do enough testing admittedly and this was released for Sencha Touch 2.0.2. @themightychris (Chris Alfano from Jarv.us Innovations) tweeted about how to load remote files in Sencha Touch 2 and as a proud father of what I thought worked I told him about the "remote" config. He replied with errors... oh boy. I should have known it was too easy to throw a couple if statements at a problem and expect it to work fully. The next day I didn't do any work on the Forums until I fixed it, my fault, my problem, my fix.

What it does now is when Sencha Command builds the index.html it will create <script> elements for your remote JavaScript files and <link> elements for your remote CSS files. The microloader, the system responsible for actually loading the resources, submits Ajax calls to load the assets and once all the assets have been loaded it then kicks off your application's launch method. So why create <script> files in the builder and not let the microloader do the loading? The issue I came across is I couldn't accurately determine when the Google Maps API was loaded due to it creating it's own <script> tag as mentioned before (see why I explained that now?). I could determine when the <script> element that I created would load but not the <script> element the Google Map bootstrap element I created would create so the launch method would fire before the Google Maps API was actually loaded causing issues with my Ext.Map test. So not knowing what people will use I felt creating <script> elements in the index.html the safest solution. So once you do a production build, you can see the <script> elements in index.html that Sencha Command created. Not the prettiest solution but sometimes you just don't have the control you want. This fix will be part of the next release (2.0.3 I believe it will be) but for you premium users it should be in SVN and part of the nightly builds you can get from http://support.sencha.com/

Example

Enough backstory, I know you are craving some code! Diving into the Sencha Touch 2.0.3 directory I created a simple app:

cd ~/Sites/sencha-touch-2.0.3
sencha app create MyApp ../MyApp

Simple to create an app isn't it? Hell yeah it is (I was a doubter but now I'm a promoter)! I then edited the MyApp.view.Main class to add an Ext.Map item as the 2nd item so I opened the ~/Sites/MyApp/view/Main.js in my editor (IntelliJ IDEA if you were wondering) and added this code as index 1:

{
    xtype   : 'map',
    title   : 'Map',
    iconCls : 'maps'
},

and of course added Ext.Map to the requires array at the top of the file. So now we have our view using Ext.Map which will use the Google Maps API so we need to add the JavaScript file in app.json so I opened app.json and made 2 edits. First I added this code after the sencha-touch.js asset in the js property array:

{
    "path": "http://maps.google.com/maps/api/js?sensor=true",
    "remote": true
},

and then at the bottom to get around a current error I changed the logger config to false:

"buildOptions": {
    "product": "touch",
    "minVersion": 3,
    "debug": false,
    "logger": false
},

So now app.json is going to tell Sencha Command to include the Google Maps' remote JavaScript file and the display the map in my MyApp.view.Main tab panel. First I need to test to make sure everything is working so I do a testing build:

cd ~/Sites/MyApp
sencha app build testing

Launched http://localhost/MyApp/build/testing/ in Chrome (my browser of choice) and everything displayed just fine, my map shows correctly (centered South-East of San Jose California because I didn't tell it to center anywhere and that's default). More importantly I checked out the console and there were not errors! Great, so from everything I know thus far my app is working perfectly so now I can deploy with a production build:

sencha app build production

Launched http://localhost/MyApp/build/production/ in Chrome (yup, still my favorite browser) and everything works perfectly!

Summary

So we learned some backstory on the issue at hand and the little bumpy road to the fix that is the "remote" config for your JavaScript and CSS assets in app.json. We then looked at building a simple example all using Sencha Command.

Happy coding!

comments powered by Disqus