About kraigb

A reader of my recent MSDN Magazine article asked what I thought about performance in Cordova apps, and here's what I wrote in response.

Performance really depends on the underlying hardware, the individual platform, and the version of the platform, because it’s highly dependent upon the quality of the app host and hardware that’s running the code.

On Windows 8.1 and Windows Phone 8.1, you’re running a native app (no webviews), and because Microsoft has put tons of perf work into the IE engine on which the app host is built, JavaScript/Cordova apps run quite well. In the perf tests I did on Windows 8.1 with JavaScript apps (see chapter 18 of my free ebook), I found that the delta from JS to C# was 6-21%, JS to C++ was 25-46%, and C# to C++ was 13-22%. This was for CPU-intensive code (and a Release build outside the debugger, of course) and thus represents the most demanding situations. If you’re primarily working with UI code in the app where the system APIs are doing the bulk of the work, I’d expect the deltas to be smaller because the time spent in UI code is mostly time spent in optimized C++.

On Android, iOS, and Windows Phone 8, Cordova apps run JS inside a Webview, and thus are very much subject to Webview performance. From what I've heard–and I haven't done tests to this effect myself–performance can vary widely between platforms and platform versions. More recent versions of the platforms, e.g. iOS 7/8 and Android 4.2 or so, have apparently improved Webview performance quite a bit over previous versions. 

In short, if you’re targeting the latest platforms, performance is decent and getting better. If you're targeting these systems, then, Cordova performance should be suitable for many types of apps, though probably not for intensive apps.

It's important to note that "performance" is not really a matter of throughput: it's a matter of user experience. I like to say that performance is, ultimately, a UI issue, because even if you don't have the fastest execution engine in the world by some benchmark measure, you can still deliver a great experience. I think of all the video games I played as a kid on hardware that was far inferior to what's probably inside my washing machine today. And yet the developers delivered fabulous experiences.

That said, running JavaScript in a Webview on platforms like iOS isn't going to match a native iOS implementation, especially with signature animations that are really hard to match with CSS transitions and such. But if you're not needing that kind of experience, Cordova can deliver a great experience for users without you having to go native.

I made a diagram that’s on http://www.visualstudio.com/explore/modern-mobile-apps-vs that tries to illustrate where Cordova falls relative to Xamarin, native, and mobile web. The vertical axis is “mobile app user experience” which includes perf as well as the ability to provide a full-on native experience like I just mentioned. 

The diagram is one way to look at the relative strengths of different cross-platform approaches. In the end, you of course have to decide what perf measures are important for your customers, do some tests, and see if Cordova will work for your project. And of course, pester the platform providers to improve Webview perf too! 🙂

Many of you have probably seen this already–an article that I wrote (with contributions from my teammate, Mike Jones), for MSDN Magazine.


I expect to be writing for MSDN more because my larger team at Microsoft owns the content calendar now!












  11. In UnitTest1.cs, add


    1. using MathTestB.
    2. Change TestMethod1 to TestAddOne.
    3. Add code to test 124+1 = 125



















Here's the short review I wrote on Amazon:



Continued from #2: First build and run

It's been a couple weeks since my last post, but I haven't been idle during that time–my Cordova efforts have been channeled into an MSDN Magazine article on Cordova, and now that I have that draft done I can share more of the insights here, meaning that I can ramble on with more details than I can fit into an article! 🙂

First of all, I modified my markup to be a little more generic and flexible for the app. One change is to drop the map display from the app altogether in favor of a simple field for the location. I did this because the map element took up a lot of space that I didn't have on small phones, and also created more complexity for layout. In the end, the map really isn't important to the app, and by making it a text field the user can also edit the location information if they want.

Another change is to add an explicit Share button because platforms other than Windows don't have the swipe-in-from-right-edge gesture to get to it, and don't have a system-level sharing feature either. (That's something we'll deal with later on.) I could have made use a WinJS app bar for this, but I decided to keep it simple and just create a div with a button.

I also just made all the content areas <div> elements instead of using <header> and <section> and so forth. Here's the new markup:

    <div class="mainContainer">
        <div class="title mainChild">
            <h1 class="titlearea ">Here My Am!</h1>
        <div id="locationSection" class="mainChild subsection">
            <h2 class="section-title">Here:</h2>
            <div id="locationControls">
                <input id="txtLocation" type="text" placeholder="tap to edit" />
                <button id="btnLocate" class="iconGlobe"></button>
        <div id="photoSection" class="mainChild subsection">
            <h2 id="photoHeading" class="section-title">My:</h2>
            <div id="photo">
                <img id="photoImg" src="#" draggable="false"
                    alt="Tap to capture image from camera" />
        <div id="shareSection" class="mainChild">
            <button id="btnShare" class="shareButton" disabled>Share</button> 

I should note that one of the complications that came up in migrating the Windows Here My Am! app is that the map I originally used was either displayed in an iframe with an ms-appx-web:// src or an x-ms-webview element, both of which are specific to Windows. I had to do this because the map area used remote code for Bing Maps. Now Cordova apps on all platform other than windows automatically run inside a webview, which means I could have just references the Bing Maps script directly, but that would (a) not work if the device is offline, and (b) wouldn't work on Windows because you can't load script into the default local context in which index.html runs. Upon further investigation, there really isn't a workaround for this at present: your root page in a Cordova app on Windows runs in the local context, but on other platforms runs in a web context. It's a difference that you just have to live with for now, and in my case I just dropped the map feature.

My next step is to style the markup it so it looks like the following:


The big trick here is to understand the impact of Cordova's nature on your HTML/CSS work. On Windows 8/8.1 and Windows Phone 8.1, a Cordova apps runs as a native JavaScript app; on all other platforms it creates a native (non-JS) wrapper around a webview. Whatever the case, the engine that renders your HTML, CSS, and JavaScript is related to the browser of the underlying platform. On Windows it's IE (10 or 11, depending on the OS); on Android it's the Android browser, (Chrome-based, of the version that matches the OS), and on iOS it's iOS Safari (7 or 8).

Which means: a Cordova's app CSS must work in each target platform's webview, just like web applications must work in different browsers by employing the appropriate prefixed and non-prefixed styles. In short, everything you know about responsive web design applies with Cordova.

As noted in the last post, I discovered this right away because the CSS grid upon which I rely heavily on Windows isn't implemented on these other platforms. And that's not all–there are many variances and differences. But thankfully there's the site caniuse.com that will tell you what parts of HTML5 and CSS are and aren't available on which platfoms, and whether or not they need prefixing. Super helpful! I suggest you visit that site and get familiar with it.

What I found was very helpful at this stage (aside from going to a CSS framework which would relieve me from the details), was to first create a Windows app project with my HTML, and then open it in Blend for Visual Studio and do my Windows-based styling. In this case I needed to use flexbox for the layout, knowing that I couldn't use the grid. Blend gave me an easy way to work out things like margins and media queries in a very friendly environment, setting the baseline styles for the app.

Along the way I also decided that given the small size of many phone screens and the fact that I eliminated the map section, it didn't make sense to support a landscape orientation. We'll return later on how to enforce that in a Cordova app; at this point it just meant that I didn't need to worry about landscape orientations at all.

With my baseline CSS from Blend, I then dropped the HTML and CSS onto my web server; you can see it all at http://www.kraigbrockschmidt.com/src/heremyam/index.html (and it has some JS in there too now). What this allowed me to do is check the styling in a variety of browsers, and then use the browser's developer tools to find the necessary styling for that browser.

On my Windows machine I opened the site in both IE and Chrome; in the latter I worked out the webkit styles for flexbox. Once I did that and updates index.css on the web host, I then opened the same page on my Android tablet to verify the layout. Then I switched to my MacBook (which I acquired to build for iOS) and checked things out in Safari, and then also opened the site on my iPad. I opened the site on my Windows Phone too. (And, I might add, that creating a short URI saves a lot of trouble entering it into a mobile browser.)

I liked using the browsers here for three reasons. First, the developer tools let you change the live CSS and see the result, just like Blend does for Windows. Second, the mobile browsers especially are very clearly linked to the webview that a Cordova app will use. Third, a browser is easily resizable, allowing you to test and style for smaller screen sizes. For example, here are the IE, Chrome, and Safari browsers sized down to a minimum, with styles for <= 499px widths and <= 480px heights, which reduce font sizes and tighten up margins:


Here's the resulting CSS. Note that use of flex: 1 1 0px; and -webkit-flex: 1 1 0px; to expand certain elements to full available space (the location input control horizontally, the image area vertically). The #btnLocation::before rule is what sets the globe icon in the locate button, and other styles on the button make it circular.


    Windows and Windows Phone (through 8.1) use -ms prefixed styles.
    Android and iOS use -webkit prefixed styles.

    There are a few general design breakpoints for layout:
    Heights: 480 and 768 (actually 767, see below)
    Widths: 480, which accomodates the 500-pixel width of Windows split-screen views.
    If you use device-[height | width] then there are more variations. Using
    [min | max]-[width | height] you get automatic scaling for CSS, which reduces
    the breakpoints. This has the effect that some device sizes don't translate
    exactly: the iPad's 768 dimension comes through as 767.78 so the breakpoint
    has to be 767 as CSS media queries operate on integer comparisons.    	

    This app will focus on being portrait-only to simplify the layout
	requirements. The only adjustments we'll make, then, are for 
	various screen sizes and not for orientation.

.mainContainer {
    /* Windows */
	display: -ms-flexbox;
	-ms-flex-flow: column;	

    /* Android, iOS */
    display: -webkit-flex;
    -webkit-flex-flow: column;
	height: 100%;	

/* Override of WinJS */
h3 {
    font-weight: 300;

.mainChild {
    margin-left: 20px;
    margin-right: 20px;	

.title {
	margin-top: 10px;	

.subsection {
    -ms-flex-flow: column;	

    display: -webkit-flex;
    -webkit-flex-flow: column;		
	margin-top: 15px;	

.section-title {
	/* height: 40px; */

#locationControls {
    /* Use a row flexbox here to allow the input control to fill the space */
    -ms-flex-flow: row;	

    display: -webkit-flex;
    -webkit-flex-flow: row;		

#txtLocation {
	flex: 1 1 0px;  /* Expand to fill available space */    
    -webkit-box-flex: 1 1 0px;   
    -webkit-flex: 1 1 0px;

#btnLocate {
    margin-left: 15px;

    /* Make it circular */
	min-width: 40px;
    width: 40px;
    border-radius: 20px;

#btnLocate::before {
    /* WinJS references ../fonts/Symbols.ttf from its stylesheets */
    font-family: "Symbols";
    font-weight: normal;
    font-size: 10pt;    
    content: "E12B"; /* globe */  

#photoSection {	
	flex: 1 1 0px;        
    -webkit-flex: 1 1 0px;    
    min-height: 100px;

#photo {	
	border: solid 1px gray;	
	width: 100%;    
	height: calc(100% - 40px); /* 40px is height of heading */
    margin-top: 6px;
    margin-bottom: 10px;

    /* Make sure the image is centered inside this area */
    display: -webkit-box;
    display: -ms-flexbox;    
    display: flex;
    justify-content: center;
    align-items: center;

    /* iOS */
    display: -webkit-flex;
    -webkit-flex: 1 1 0px;
    -webkit-align-items: center;
    -webkit-justify-content: center;

#shareSection {
    display: -webkit-box;
    display: -ms-flexbox;
    display: -webkit-flex;
    display: flex;
	-ms-flex-pack: center;	
    -ms-flex-item-align: center;
    justify-content: center;
    align-items: center;
    -webkit-justify-content: center;
    -webkit-align-items: center;

	margin-bottom: 15px;

.shareButton {
    margin-left: 8px;
    margin-right: 8px;

/* Adjustments for narrower/shorter screens */
@media screen and (orientation: portrait) and (max-width: 499px),
       screen and (orientation: portrait) and (max-height: 480px)
    h2 {
        font-size: 14pt;

    button, input {
        font-size: 10pt;        

/* Tighten up margins for short screens */
@media screen and (orientation: portrait) and (max-height: 480px) {
    .title {
        margin-top: 5px;

    .mainChild {
        margin-left: 10px;
        margin-right: 10px;

    .subsection {
        margin-top: 10px;

    button, input {
        min-height: 15px;

    #photoSection {
        margin-top: 5px;

    #photo {
        margin-bottom: 5px;

    #shareSection {
        margin-bottom: 5px;


It's important to note–and you'll see this if you run in the Ripple emulator–that the sizes reported to CSS are scaled sizes, especially where max-height, max-width, and so forth are concerned. I would suggest sticking with these instead of trying to get device pixels, because doing that would only increase the complexity of your CSS for no benefit.



Switching platform targets in Visual Studio

One of the most important things to know when working in Cordova is how to switch between target platforms. There aren't obvious controls in Visual Studio for this, but it's there. Either use the Build > Configuration Manager menu item, click the Debug/Release drop-down in the toolbar and select Configuration Manager:


Once you're there, the Active Solution Platforms drop-down is where you set your target.


Doing this will change the main VS toolbar to reflect options available for that target. This is how you switch between targets and run the app on devices and emulators.

Tip: to shortcut this you can add the platform drop-down directly to the toolbar. Right click the toolbar and select Customize at the bottom of the long list. In the dialog that appears, click the Commands tab, then select Toolbar and Standard:


Now click Add Command, then pick Build > Solution Platforms:


This adds the platform drop down to the toolbar. You might need to use the Move Down button in the Customize dialog to place it where you want. I also used the Modify Selection button to narrow the size to 130, and placing it where I wanted I see this on my toolbar:


Running the app, and first issues encountered: varying CSS support

With everything migrated now, I was able to run the app on the Local Machine (Windows) as expected. The one caveat I found is that Cordova at present targets Windows 8.0 and not 8.1 (I think Cordova version 3.6 is supposed to do 8.1), which means that it doesn't understand variable-sized views, and only snapped/filled states. This means that in a narrower view that's later than 320px you get the 320px snapped view inside the wider view like you do with any Windows 8.0 app on 8.1.

On Windows Phone the app ran great in portrait mode, but the layout wasn't working in landscape. Hard to tell why, because the present Cordova targets Windows Phone 8.0 which means the app is running inside a webview inside a Silverlight app. This means there's no debugger support whatsoever, so I can't poke into the DOM to see what's going on.

On Android the layout is all wrong…because an Android webview in which a Cordova app runs doesn't support the CSS3 grid specification as we enjoy on Windows. Urk. I've relied heavily on grid layout but clearly I'll have to convert to flexbox, which is why I said CSS comes up early.

On iOS (in the Ripple emulator), looks like we have the same issue.

The upshot here is that when working in Cordova, your HTML/CSS work is going to be very much like writing responsive web pages for different browsers, because that's really what's happening with Cordova: your code is running inside a webview which has varying capabilities depending on the target platform. 


Finding your DOM in the Ripple Emulator

When running on my Android device, Visual Studio's DOM Explorer works just like it does for a Windows app–you can do in and tweak styles and so forth.


When running in the Ripple emulator, you still get the DOM Explorer except that you see everything that's showing in the emulator, including all the surrounding controls:


Egads! Where is my app? Well, the easy way to find it is through that click-to-select button in the upper left above: click that, then click in the emulator, and you'll see the DOM tree expand to where your app is. You'll see that it's located under the sections ui > middle > device-container > viewport container > and then the iframe "document":



What's very cool in the DOM Explorer is that the CSS editor does inherently known what styles are and aren't supported for that target device. I can see right away, for instance, that display: -ms-grid; isn't among those supported for Android and iOS webviews, which isn't at all surprising. So the next job is to convert my grid-based CSS to cross-platform flexbox, which will be the next post.

I said that CSS would come in early, but the first thing to discuss in migrating the Here My Am! files from my existing Windows Store app project to a Cordova project. For this I'm just starting with the HereMyAm2a code from Chapter 2 of my free ebook. And in fact I'll keep it simple for starters and just migrate the HTML and CSS, leaving off the JS code for now.

Preliminary notes/build environment

Although I'd started working on a universal Windows app migration for this project, it's not a necessary step for working with Cordova, because it also produces cross-platform apps that will work on Windows and Windows Phone alike, as well as iOS and Android. With Cordova, you let plugins worry about platform-specific things–you don't want that kind of code in your project. 

In addition, it's helpful to know that you don't need a Mac as a build server to work with Cordova until you really want to produce an app for the store. With the Visual Studio extension installed, you can run a Cordova app directly in the Ripple emulator , which is very cool in that you can switch between devices, resolutions, and orientations (including between target platforms) much like Blend for Visual Studio does for Windows, so you can see just how (badly) your CSS is performing.

For myself, I'm working on a Surface Pro 3 as my main machine, have a Windows Phone hanging off it, have an Asus MemoPad7 as an Android dev device, which I wrote about recently. My team has a Mac laptop set up in one of my co-worker's offices as a build server (also for Xamarin) which I can get to over VPN to the Microsoft corpnet from my home office…pretty cool!

Project structure

I started with a new Cordova project (File > New > Project > JavaScript > Multi-Device Hybrid App > Blank App (Apache Cordova)); this is what you want to do rather than trying to convert an existing Windows project. I then migrated the appropriate files over:

Windows Project File Cordova Project File
default.html index.html (This is the default; you can use default.html if you change the start page in config.xml)
js/default.js scripts/index.js (didn't migrate the code yet; the project template uses scripts instead of js as a folder…I might change this later)
package.appxmanifest config.xml (the Cordova generic manifest)
css/default.css css/index.css
html/map.html html/map.html (there is no default html folder, so I created one just to hold this file for the time being)
images/taphere.scale-100.png images/taphere.png; I'll be switching to draw this with a canvas later on, so it's just a placeholder.
images/<logos> Not migrated yet as these need to be specific for each platform, whcih I haven't done yet.
WinJS references WinJS is not a cross-platform, open-source library, an instead of having it in the project references I downloaded WinJS 3.0 and brought it directly into the project:

  • /css/frameworks/ui-dark.css (you'll get a whole ton of warnings on styles in here because of the differences in CSS support between platforms)
  • /css/fonts/Symbols.ttf (ui-dark.css and ui-light.css assume this file is in ../fonts, so it needs to be in a sibling folder unless you modify the reference)
  • /scripts/frameworks/base.js
  • /scripts/frameworks/ui.js
  • /scripts/frameworks/WinJS.js

I don't know how much of WinJS I'll be using, but given that I have lots of experience in this area, it seemed like a good opportunity to keep up! Plus the ui-dark.css has styling that I'm used to with this app. We'll see how it goes.

  The project template also includes a merges folder for platform-specific code, and a res folder for resources that I'll get to later on.


Updating index.html

With this migrated project, I fixed up the references in index.html to bring in the appropriate files:

    <link href="css/frameworks/ui-dark.css" rel="stylesheet" />    

    <!-- Cordova standard -->
    <script src="cordova.js"></script>

    <!-- WinJS -->
    <script src="scripts/frameworks/base.js"></script>
    <script src="scripts/frameworks/ui.js"></script>
    <script src="scripts/frameworks/winjs.js"></script>

    <!-- Project references -->

Note: in a Windows project, especially with WinJS page controls, it's usually helpful to prefix all references with a leading /. You do not want to do this with Cordova because it doesn't work. I'll have to see what happens later on when I try using page controls.

Note also that you need the reference to cordova.js even though it doesn't exist in your project.

With my script/css references fixed up, I just use the same markup as before in index.html:

    <div id="mainContent">
        <header id="header" aria-label="Header content" role="banner">
            <h1 class="titlearea "> 
                <span class="pagetitle">Here My Am!</span>
        <section id="section" aria-label="Main content" role="main">
            <div id="photoSection" class="subsection" aria-label="Photo section">
                <h2 class="group-title" role="heading">Photo</h2>
                <img id="photo" class="graphic" src="images/taphere.png" alt="Tap to capture image from camera" role="img" />
            <div id="locationSection" class="subsection" aria-label="Location section">
                <h2 class="group-title" role="heading">Location</h2>
                <div id="map" class="graphic" aria-label="Map"></div>


Up next, running the app.