Every time I go to talk to folks about Windows 8, the same questions pop up. I blame this largely on Microsoft’s silence about Windows 8 following the release of a tidal wave of information followed by the Windows 8 Developer Preview at Build in September. C’est la vie. This too shall pass.
One of the topics of conversation that comes up repeatedly is how to choose between using HTML5 + JavaScript or XAML + C#/VB (aka .NET) to build Metro style applications. What are the factors that you should consider before making your choice? Is HTML5 better? Is there a future for XAML? How do you choose?
Inevitably someone in the conversation cites the portability of HTML5 and JavaScript as the answer. It goes something like this…
“You should use HTML5 and JavaScript for Metro style applications because its portable and XAML isn’t. If you build with HTML5 then you can use the same code for your website or other platforms because its standards-based….HTML and JavaScript.”
This couldn’t be further from the truth. The use of HTML5 + JavaScript in Windows 8 is about as proprietary as using XAML + .NET. Consider the “Hello World” of the modern era – an RSS feed reader.
If you are going to build a feed reader into your Metro style application using HTML5 and JavaScript, it would look something like this:
DEFAULT.HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>RssReader</title>
<!-- WinJS references -->
<link rel="stylesheet" href="/winjs/css/ui-light.css" />
<script src="/winjs/js/base.js"></script>
<script src="/winjs/js/ui.js"></script>
<script src="/winjs/js/binding.js"></script>
<script src="/winjs/js/controls.js"></script>
<script src="/winjs/js/animations.js"></script>
<script src="/winjs/js/uicollections.js"></script>
<script src="/winjs/js/wwaapp.js"></script>
<!-- RssReader references -->
<link rel="stylesheet" href="/css/default.css" />
<script src="/js/default.js"></script>
</head>
<body>
<h1>RSS Reader</h1>
<div id="downloadStatus"></div>
<div id="template" data-win-control="WinJS.Binding.Template">
<div class="postTitle" data-win-bind="innerText: title"></div>
<div class="postDate" data-win-bind="innerText: date"></div>
</div>
<div id="posts" data-win-control="WinJS.UI.ListView"
data-win-options="{itemRenderer: template,
layout: {type: WinJS.UI.ListLayout},
selectionMode: 'single',
onselectionchanged: selectionChanged}">
</div>
<div id="contentTemplate" data-win-control="WinJS.Binding.Template">
<div class="postTitle" data-win-bind="innerText: title"></div>
<div class="postDate" data-win-bind="innerText: date"></div>
<div class="postContent" data-win-bind="innerHTML: content"></div>
</div>
<div id="content"></div>
</body>
</html>
DEFAULT.JS
(function () {
'use strict';
WinJS.Application.onmainwindowactivated = function (e) {
if (e.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.launch){
downloadStatus.innerText = "Downloading posts...";
var syn = new Windows.Web.Syndication.SyndicationClient();
var url = new Windows.Foundation.Uri("https://dougseven.com/feed/");
syn.retrieveFeedAsync(url).then(processPosts, downloadError);
// Define an event listener for the onselectionchanged event.
posts.addEventListener("selectionchanged", selectionChanged);
// Process the declarative controls
WinJS.UI.processAll();
}
}
function selectionChanged(e) {
content.innerHTML = "";
var selection = posts.winControl.selection;
if (selection.length) {
var post = postItems[selection[0].begin];
var contentTemplate = WinJS.UI.getControl(
document.getElementById("contentTemplate")
);
contentTemplate.render(post).then(function (element) {
content.appendChild(element);
});
}
}
var postItems = [];
function processPosts(feed) {
// Clear the process indicator
downloadStatus.innerText = "";
// Iterate over the items
for (var i = 0, len = feed.items.length; i < len; i++) {
var item = feed.items[i];
var post = {
title: item.title.text,
date: item.publishedDate,
content: item.summary.text,
};
postItems.push(post);
}
// Populate the ListView control's data source
posts.winControl.dataSource = postItems;
}
function downloadError() {
downloadStatus.innerText = "Error loading posts.";
}
WinJS.Application.start();
})();
The Results
The resulting application creates a simple two column RSS feed reader, with post titles on the left, and post content on the right (in HTML):
Now imagine you wanted to use the same code to make your RSS feed reader website. Immediately you have to cut out all references to the WinJS JavaScript files, since WinJS is a JavaScript wrapper around key WinRT functions.
<!-- WinJS references –>
<script src="/winjs/js/base.js"></script>
<script src="/winjs/js/ui.js"></script>
<script src="/winjs/js/binding.js"></script>
<script src="/winjs/js/controls.js"></script>
<script src="/winjs/js/animations.js"></script>
<script src="/winjs/js/uicollections.js"></script>
<script src="/winjs/js/wwaapp.js"></script>
For example, the Metro style RSS feed reader application uses WinJS to manage a lot of the UI look and feel, data binding and how you interact with the application, including controls, animations, etc. All of that functionality will have to be rewritten in non WinJS format.
You are forced to rewrite key functionality, such as the feed syndication capabilities written in JavaScript which leverage Windows.Web.Syndication.SyndicationClient – a WinRT class that manages the network interaction between the client and the feed provider, including the asynchronous calls to get the RSS data and parse and format it correctly.
var syn = new Windows.Web.Syndication.SyndicationClient();
var url = new Windows.Foundation.Uri("https://dougseven.com/feed/");
syn.retrieveFeedAsync(url).then(processPosts, downloadError);
You have to rewrite the data binding of the feed items to the HTML layout.
// Populate the ListView control's data source
posts.winControl.dataSource = postItems;
// Process the declarative controls
WinJS.UI.processAll();
<div id="template" data-win-control="WinJS.Binding.Template">
<div class="postTitle" data-win-bind="innerText: title"></div>
<div class="postDate" data-win-bind="innerText: date"></div>
</div>
<div id="posts"
data-win-control="WinJS.UI.ListView"
data-win-options="{itemRenderer: template,
layout: {type: WinJS.UI.ListLayout},
selectionMode: 'single',
onselectionchanged: selectionChanged}">
</div>
<div id="contentTemplate" data-win-control="WinJS.Binding.Template">
<div class="postTitle" data-win-bind="innerText: title"></div>
<div class="postDate" data-win-bind="innerText: date"></div>
<div class="postContent" data-win-bind="innerHTML: content"></div>
</div>
That doesn’t feel very portable.
The conclusion is that your language choice when building a Windows 8 Metro style application has next-to-nothing to do with portability.
Before you get on your soap box, yes you can reuse some of the assets from the application. For example, the CSS is reusable between Windows 8 and the web. Some of the JavaScript is likely reusable, if it isn’t tightly coupled to WinJS or WinRT. But that’s it. Most of what makes the app work is dependent on WinRT, so its not portable – WinRT only runs on Windows 8.
Get Comfortable
So what should your language selection be based on? Comfort.
Microsoft architected an application development stack that does what Microsoft does best – provides flexibility and gives YOU choice. If you want to build an application for Microsoft’s upcoming platform, you can choose the language that you are most comfortable with. Microsoft isn’t making you learn an entirely new stack – just learn the new bits – and use the skills you already have.
Choose XAML
If you are a .NET developer currently working in WPF or Silverlight, then XAML+.NET will be right up your alley. Sure you will have to learn WinRT and some new syntax, but most of what you need to know you already do.
Choose HTML
If you are a web-standards developer, familiar with HTML and JavaScript, then use those skills. Use HTML5, JavaScript and learn WinJS and WinRT.
Either way Microsoft has made developing for Windows 8 very approachable. Make your language selection based on your skillset and what is comfortable for you. Don’t feel like you have to lean a new language. Use what you know.
D7
Just curious, why no discussion of C++ on WinRT?
One of my left-over unresolved issues from BUILD is the question of whether or not we are regressing back to dominantly an unmanaged environment for Win8 and beyond. Is there any indication that this might be the case?
I think it’s more about skill portability than code portability. Developers familiar with HTML5 elements and the syntax of JavaScript can start developing apps after just learning a new library and some new CSS properties. Compared to having to learn XAML and C#, this is a much smaller hurdle, and the ability to reuse static content on both websites and WWAs is a huge advantage.
HTML5 and Javascript *is* portable.
Nothing about WinRT makes that untrue.
HTML5+JS apps will run on a myriad of platforms.
You’ve just chosen to construct your app and tightly couple it to WinJS (the WinRT javascript library)
As an analogy, C++ is a portable language, but it’s very easy to write unportable C++.
Much that is made of the portability of HTML5 and Javascript is the utilization of toolkits that provide an abstraction layer ontop of platform specific features, which nothing like that exists for WIndows8…yet.
But certainly my Javascript SDK for Twitter is far more portable than the same library written in C#.
Once you develop real world apps in Metro using HTML5/JavaScript you will realize what you’re saying makes no sense.