Allen Conway's Blog

Exploring all things software engineering and beyond...

State of the Union: Future and Historic Thoughts on WebAssembly, JavaScript, and .NET

With all the goodness happening in the world of WebAssembly it's important to keep an eye on what's happening and how this will positively impact development going forward. In the world of JavaScript there are questions about how the worlds will converge. This maybe in contrast with a portion of the .NET community, which seems at times they don't want it to converge; they want JS dev to be thrown out with the garbage as evidence by the sly remarks toward our community over the years (which as a JS dev I've digested kindly). This sentiment is also supported via the primary description of Blazor:

Blazor lets you build interactive web UIs using C# instead of JavaScript

Although that picture gets clearer as I realize their baby (web in .NET) was called ugly for the last decade so they are salivating for Blazor to feel at home again on the web. (zing!) OK back on track and in all seriousness, Blazor is a rich platform to build modern apps using C#, and I do fully appreciate the excitement of being able to run the same code on the client and server. This is a significant strength in addition to several other bullet points about the stack. 

BTW, I qualify to make these remarks as I've been both a .NET developer and a JavaScript developer, so I've been on both sides of the fence for extended periods of time. Just look at the header image on this blog; it's a legacy Visual Studio logo representing the numerous years I've spent as a .NET developer.

History will show though without JS, the development community as a whole I don't think would be near where they are today and still creating per-platform apps like 15 years ago. The ability to write-once and deploy platform agnostic for the last 10 years is unparalleled until recent advancements. It's historic significance can't be ignored. 

Also there is no hidden agenda here to resist change or remain some kind of isolated JS developer wearing blinders. I'm not that dogmatic in my career path as I've typically moved along with change remaining modern to where mainstream development has gone, and not tried to hang on to a stack out of stubbornness. I'll adopt change as the community does, and always excited about the advancements of the future.

The reality is there is too much momentum in JavaScript development for companies/customers/clients to pump the brakes and change everything. This process is always an evolution. There is also the fact that not all development is greenfield, so the question arises about how to have the best of both worlds (JS and WASM)? 

Being pragmatic and assessing the current landscape, I think the real step forward for folks not purely on a single stack like C#/.NET, or any narrow/single stack for that matter will be a hybrid one (by definition hybrid); at least in the beginning. This is even suggested straight from the horse's mouth:

I feel like bullet points 2 and 3 above will emerge in the 1st 3-5 years as a prevalent way of developing modern web apps. A hybrid approach that uses both JavaScript and compiled WASM modules referenced within to produce performant and modern web applications. The language used to create and target a WASM module will be dependent on the team's experience. 

Here are some interesting examples that do just this:



It's important to continually modernize our stack and remain fluid with the direction the community guides us. WebAssembly plays an important role in the future of all types of development. What are your thoughts on how this will evolve?

Using Quokka.js for Real-Time Feedback in TypeScript

I'm always looking for cool VS Code extensions and Quokka.js certainly hits the spot. It provides real-time feedback on JavaScript and TypeScript directly in VS Code in a variety of forms. For example if you're testing some code via console.log, you can get the output directly inline to the right of the code which is awesome.

Once installed, all I needed to do was open the command pallet in VS Code (Ctrl+Shift+P) and select, 'Quokka.js: Start on Current File' as shown below:

After initiating the extension, as seen below I was getting live logging directly in the code.

If there's a value not provided in the scope of the file, Quokka.js obviously can't produce an output and this was expected behavior:

There is quite a bit more functionality offered like code coverage assessment (as it pertains to code execution paths, not unit testing), and a provided value explorer. There is also a Pro edition with additional tools available.

Check out the links below to get started:

VS Code Extension for Quokka.js

I'm excited about WebAssembly, but not as much about my beloved .NET, Blazor's implementation

As a web client developer these days, I'm sold on WebAssembly and looking forward to it's adoption by the multiple languages that can compile to it. However interestingly one of the things I'm beginning to feel is my personal dislike for the Blazor syntax and implementation. I suppose my multiple years being entrenched in JS/TS with really enjoying TypeScript + the SPA frameworks that have a relatively clean separation of markup (declarative) and logic (imperative) has made me have a bit of dislike for lacing the view directly with imperative view logic like this in Blazor:

@page "/myorders"
@inject HttpClient HttpClient

<div class="main">

@if (ordersWithStatus == null)
else if (ordersWithStatus.Count == 0)
  <h2>No orders placed</h2>
  <a class="btn btn-success" 
        href="">Order some pizza</a>
  <text>TODO: show orders</text>

As a side of humor, to format code blocks on this blog I have to select a 'brush' for the language formatting. Case in point, in the above snippet I wasn't sure if I should have picked HTML, C#, or Blazor.

This is probably because I was never a fan of the classic ASP, MVC Razor, or even Blazor implementations where view logic is interlaced with the markup (for web client code I'd even throw in JSX - as explained here). This doesn't matter a pile of beans really because this is all subjective and has absolutely no bearing on how successful Blazor or any other language targeting WebAssembly will be. I actually love the .NET stack and was carved from that block since the beginnings of my professional career, but I just don't like that particular style of implementation for the web. Shoot for all of ASP.NET's webforms shortcomings, the view overall was relatively clean (keeping logic in code separate from the markup) and pure aside the fact the tags may have been ASP.NET server-side controls but still took the shape of HTML tags (analogous in form to today's custom HTML elements).

I also do not like the JSInterop style in Blazor. You can invoke JavaScript functions from within C#, and that alone is handy I suppose, but messy. The functions you want to invoke must be available on the global scope of windowYuck. JavaScript scope and encapsulation was difficult enough to manage through the years, I'd rather not go back to the days of hanging code off the window object making everything globally available. In 100 level examples this seems fine, but get to 10's or 100's of thousands of lines of code in an enterprise app and this could get ugly.

  window.MyFunction = (someValue) => {
    //JS code here...

using Microsoft.JSInterop;
public class JsInteropExample
  public static Task MethodName(strings someValue)
    return JSRuntime.Current.InvokeAsync("MyFunction", someValue);

I'm probably not alone in my opinions, and that's why I'll be keeping an eye on the ability to use TypeScript as a target for WA. I like JS/TS and am comfortable with it for developing web applications. I feel many client side developers may have a similar sentiment and not want to either learn a server-side language, or just prefer the front-end languages they've been using for years. TS on it's own won't be enough (it's just a language), so it would have to be TS + some web framework (??) and we'll have to wait for the pieces to come together.

To that end I'll keep an eye on things like assemblyscript which is a TypeScript to WebAssembly compiler. It doesn't appear to have the traction some of the other compilers do at the moment, but I'm sure it or something similar will gain momentum as WA picks up and the masses of web developers may not feel like using C#, C++, or Rust.

AssemblyScript: a TypeScript to WebAssembly compiler

AssemblyScript: Status and Roadmap

I'm not counting Blazor out for sure, and it's still going to evolve as it's only an experimental project at the moment. I really enjoy developing in C# so it seems like a great match, but in it's early stages it's rough around the edges and maybe that's just my opinion that's shaped as a front-end developer. I'm pragmatic and will not count out the usefulness of developing on a single-stack and this is where Blazor shines for .NET developers. 

I'd be interested in feedback or thoughts about using TypeScript to transpile to WebAssembly or anything else along these lines, so please feel free to leave a comment and let me know.

Named vs Fat Arrow Functions in TypeScript

When working with TypeScript, it's important to understand some of the key differences between named and fat arrow functions. Let's have a look at a basic class with one of each type of function defined, and also the resulting ES5 that TypeScript transpiles to for a better understanding.

Here is a sample TypeScript class with the two different types of functions.

class MyTsClass {

    private myValue: number = 0;

    myNamedFunction(): void {
        setTimeout(function () {
            console.log(`Inside myNamedFunction, this.myValue = ${this.myValue}`);
        }, 1000);

    myFatArrowFunction = (someValue: number) => {
        this.myValue = someValue;
        console.log(`Inside myFatArrowFunction, this.myValue = ${this.myValue}`);

const myClass = new MyTsClass();          

Here is the resulting transpiled ES5 JavaScript.

"use strict";
var MyTsClass = /** @class */ (function () {
    function MyTsClass() {
        var _this = this;
        this.myValue = 0;
        this.myFatArrowFunction = function (someValue) {
            _this.myValue = someValue;
            console.log("Inside myFatArrowFunction, this.myValue = " + _this.myValue);
    MyTsClass.prototype.myNamedFunction = function () {
        var _this = this;
        setTimeout(function () {
            console.log("Inside myNamedFunction, this.myValue = " + _this.myValue);
        }, 1000);
    return MyTsClass;
var myClass = new MyTsClass();

For the purpose of this post, we'll concentrate on (2) main aspects of the code
  1. Where the method is created on the object, and the resulting performance impact
  2. How the this keyword behaves
It's important to understand the differences because there is a performance impact. Notice how the named function on the class is created and attached on the object's prototype. In this manner, the method is stored in memory only one time, as objects created from the same constructor point to a single prototype object. This is the more memory efficient implementation.

Now inspect the fat arrow's function in the ES5 code. Because the method is declared and created in the object's constructor (instance member), it will be declared again per each new instance of this type of object created. This has a memory and performance overhead. As a note, this is the identical resulting behavior to explicitly creating methods within the class constructor in TypeScript.

At this point we might be thinking, "Well that's enough let's just use named functions which will be declared on the object's prototype and be done with it!" There is more than meets the eye and the fat arrow function is quite useful. One of the main advantages is that fat arrow functions lexically capture the context of this in TypeScript. This is critically important in functions that contain callbacks or where re-assignment of instance variables might occur. The former use case is one that we run into often with observable callbacks in say Angular components. You may have run into issues with the this keyword and noticed it wasn't the correct context. The issue is if not using the fat arrow syntax, the context of the this keyword will be undefined. If strict mode isn't enabled, the context of this will be of the window object. If you look in the ES5 tanspiled code, you'll notice this is captured from outside the function body allowing our context to be captured correctly.

var _this = this;

Let's look at the console output from the original code above. Notice in the setTimeout call the use of this. However in this instance it's not the proper context resulting in undefined when accessed. 

The fix is to update the callback to use the fat arrow syntax which will capture the correct context of this

myNamedFunction(): void {
  setTimeout(() => {
    console.log(`Inside myNamedFunction, this.myValue = ${this.myValue}`);
  }, 1000);

If we run the code again, we get the console output we expect.

In a TypeScript project with the default configuration of "noImplicitThis": true set in the tsconfig.json file, you'll actually be warned in the IDE of this scenario, " 'this' implicitly has type 'any' because it does not have a type annotation." This would be an indication you need to use the fat arrow function instead.

There are other use cases beyond the ones I'm mentioning here today in regards to the behavior of this with inheritance and calling the parent class as well as other differences. However these are two key areas that should be understood, as I see the usage flip-flop without intent, and developers should be aware of the performance and behavior differences and create the correct type where appropriate. They have separate purposes, so I'm not a fan of just one or the other. Using only fat arrow functions have their performance impact, but shouldn't be avoided all together as they are instrumental on capturing the correct context of this when needed. 

Visual Studio Code Snippet - Triple Slash Directive

Sticking with the theme of my last blog post, Running ES6 Modules Native in the Browser using TypeScript, this post looks at pure JavaScript/TypeScript projects (i.e. NodeJS), that might not be using a framework or module loader, yet still need the ability to reference dependencies from other files. We've been doing this for years using the Triple-Slash Directive like the following:

/// <reference path="./src/ts/myClass.ts" />

In Visual Studio Code I was looking for an extension, snippet, or shortcut to type out the above. Interestingly I came up with nothing. Maybe it's inside another extension I hadn't seen, but rather than look for a needle in a haystack, I decided to quickly hand-roll my own snippet. This is trivial to do in Visual Studio Code. Here is the snippet for a triple-slash directive, and it can be used with the following prefix name: "tripSlash"

  "Triple_Slash_Directive": {
      "prefix": "tripSlash",
      "scope": "javascript,typescript",
      "body": [
        "/// <reference path=\"${1:path}\" />",
      "description": "Triple Slash Directive used for declaring dependencies between files when no module loader is used"

Running ES6 Modules Native in the Browser using TypeScript

ES6 Modules have a clean and intuitive syntax, and it's nice to know that there is now widespread support natively to use them in the browser. The main drawback to date is that not every browser version dating back supports ES6 modules and thus a module/loader bundler is still required for production applications (only one of many reasons). However it can be a lot of work to spin up Webpack or SystemJS just to throw together a small test application. Another use case might be if building an intranet app in a controlled/known environment using a supported browser. Regardless of the reason here is how you can use ES6 modules natively in the browser using TypeScript or JavaScript. (This post will focus on TypeScript, but you can use plain JS too)

1. Create an ES6 module

A module is nothing more than a self-contained set of functionality, executed within their own scope and not on the global scope. We'll use the export keyword to expose that functionality outside the module, and the import keyword to use that exposed functionality in another module.

export class Person {
        return '123 Pine St.';

2. Create another ES6 module importing the module created previously

import { Person } from "./Person.js";
export class ContactInfo{
    getContactInfo() {
        const person = new Person();
        const address = person.getAddress();
        console.log(`The address is: ${address}`)

Make sure to note that "bare" modules are not supported. This restriction allows for browsers to scale in the future when using module loaders, and allow "bare" modules to contain special meaning or functionality. This syntax below is not supported and you'll get the following error in the browser, even though the application might build correctly:

import { Person } from "Person";
"Uncaught TypeError: Failed to resolve module specifier "Person". Relative references must start with either "/", "./", or "../"."

The correct syntax is to reference the exact file directly. 

3. Configure tsconfig.json

Configure the module type to be "ES6." Using anything else will ultimately yield in errors in the browser at runtime as the other module types are not supported. 

"compilerOptions": {
    "module": "es6"

4. Leverage the "module" type in index.html

As this isn't a classic script, we must identify the file as being a module using the type="module" attribute. Note you can use the async attribute with modules if desired which will execute the script as soon as possible, without a guarantee of order, and also not waiting for the HTML parsing to finish. There is also no need to add the defer attribute as it behaves like this by default; a module script can't block the parser.

<script src="scripts/typescript/Person.js" type="module"></script>
<script src="scripts/typescript/ContactInfo.js" type="module"></script>

5. Run and check for errors

If you see any errors such as "exports is not defined" or "define is not defined" then you probably have the tsconfig.json configured incorrectly and it's instead transpiling to another module type that is unsupported in the browser (i.e. commonjs, amd, etc..) natively without a module loader. If testing the basic functionality above, upon calling getContactInfo() you should see the output in the debugger.

For a full list of browser compatibility on ES6 module support, see the following link:
JavaScript modules via script tag

If you're wondering about the .mjs module file extension support in TypeScript, see the following discussion on GitHub: Support '.mjs' output

Buyer Beware: the client has burned us before, put stock in code on the server

Have you ever played poker? Do you like a full house? A royal flush? Those are amazing but the hand you're dealt is two 3's, a 5, a jack, and a 9. Software development and its future, often has speculation laced in but sometimes we need to deal with the hand we're dealt. As primarily a web developer these days and on and off over the last 15+ years, there has always been that "next thing in the pipeline that will save the horrors of web development." Sounds kind of like a gambler that says, "if I can just play one more hand, I'll win it all back and more!"

This all builds up to be a bit cynical, but the reality is web development is and always has been an ever changing, volatile platform for which to develop. There probably is no better group of people accustomed to change than your savvy modern day web developer. I don't think anyone should label web developers as 'in love' with how modern web development is implemented in general. It's a kludge of open source libraries and techniques that defines the very word 'web.' That being a tangled web of various libraries and techniques all pointing back to that love-hate relationship with JavaScript. 

JavaScript in some respects is that mediocre poker hand we were dealt. However in the web world it's perceived weaknesses are at the same time it's strengths. Albeit a dynamic language that frustrates many, it's also flexible and powerful providing us with that "write once run anywhere" ability due to the fact of browsers all being able to interpret and run JavaScript.The language has IMO matured exponentially in the last 5-10 years, and with the addition of high level superset languages like TypeScript, working with JavaScript isn't the nightmare it once was.

However, you won't see any "I love JavaScript" bumper stickers on the back of my car. I spent years working in various languages like WinBatch, VB, VBA, VB.NET, and C# on the server or client. The reality is today those do us no good in web development on the client. Ah but you say, WebAssembly is here to save the day! Yeah I've heard this tune played before (cough, cough, Silverlight). C# running on the client, same business rules on the client and server, our woes are over, etc. etc.. Listen, I know Silverlight and WebAssembly are not the same at all. The only analogy I'm making is it's not the 1st time in history something has been deemed the "savior" to web development. Call WebAssembly 'x' for this purpose, and "project x will save the day!" In reality I'm actually quite optimistic about where WebAssembly is going to take us on the client. Imagine using C# for everything? That would be beautiful. For an optimistic view of WebAssembly and it's future with smart client development, check out Rocky Lhotka's post: A Bright Future for the Smart Client

Let's pump the brakes for a minute though. It's early 2018 and I'm expected to deliver today using the hand I'm dealt. In that case we are looking at a host of JS libraries and frameworks to help us build a responsive SPA when it comes to web development. I also have the option of using server-side heavy tech, but for the purpose of this post, I'll focus on the more mainstream approach these days using JS and building responsive JS apps. The bright side of all this is there isn't that "one way" to do development. I suppose that's a double edged sword, but the reality is it gives us options. Like ES6? Use it. Don't like JS? Use TypeScript? Like Angular? Nope. Use React or Vue. Like LESS? Nope. Use SASS. The options go on and on and on. I do agree in some ways this stinks. I often talk about the days early in my career where being really awesome at VB6 meant you could conquer the world, finish your job, and not have to worry about 1,000 surrounding technologies, languages, and libraries. I feel like times were a bit more straight forward. However back in 2002, it was accepted that everybody and their brother was using Windows + IE and that was it. Times have changed and so has the web. The expectation today is run anywhere. Thankfully, JavaScript has provided that flexible nature to allow use to be fluid and make our way to being platform and browser agnostic. Thus we can reach a lot of people with a single line of code.

So what does this all mean? Well I can say for one thing today: the web is a volatile space and likely to continue beings so in the near future. Even if WebAssembly or any other technology comes along and truly revolutionizes web development as promised, it will take a long time to wash out the gabillion lines of JS out there running the web today. That and the fact we'll probably be in a scenario where, "1/5th of the APIs are available with new tech 'x', and a roadmap is available for the remainder." Point being, set yourself up well to play this hand you're dealt today no matter how it plays out. Be smart and architect your application properly to be successful today and in the future no matter what technologies throw their hat in the ring to save web development. This includes the next best JS framework ever to be head and shoulders above them all!

Put stock in your code on the server

How do we play our hand to isolate ripple effects as much as possible as technology proves to be volatile? The answer might be in looking at statistics from the past, rather than looking into a crystal ball. 

Let's take a walk through history for a moment in web development starting 18 years ago in 2000. If you were to build say a banking or financial web application beginning at that time and continuing to keep current on a mix of .NET and client technologies, here is the journey you would might have taken:

Classic ASP -> ASP.NET Webforms -> ASP.NET Webforms + AJAX Control Toolkit -> ASP.NET Webforms + Silverlight -> ASP.NET MVC (aspx engine) -> ASP.NET MVC (razor engine) -> AngularJS -> Angular 2,3,4,5....

What does this all mean? The web layer is and always has been volatile. Maybe the buck stops with WebAssembly in the future, but that is still yet to be proven; that's another crystal ball moment. I want to use the history of the journey we've taken to help make sound decisions today. This leads me to the point that I'd take little stock in the front-end of our application, and put stock in the server-side code.

Here's an example. Back in 2002, you wrote that financial or banking application using C#. If you at the time had used sound OO techniques dating back to the 70's, unit tested the code, and wrapped it in abstractions to deliver the data, that code could be mostly intact today. I couldn't say that for probably a single line of code on the front-end. 

I'm not oblivious to the changes in both C# and .NET technologies, so odds are code was probably refactored. However the most volatile part on the server is that being the manner in accessing the data and the manner in delivering the data. Sure there is volatility there as well. Maybe those core classes and business logic were once deliver via .NET Remoting, then an ASMX Web Service, followed by WCF, than WebAPI. However those should be ultra-thin layers acting as a means to an end to deliver the data. Same applies to accessing the data. You started with ADO.NET, then to LINQ to SQL, then to Entity Framework and through all of its versions. Again, this didn't necessarily need to change all of your core code; this is another layer that should be understood as being volatile.

So back to the web, today. I want to view the front-end layer as a thin and volatile layer that as history has shown has about an average of a 1-3 year lifespan it seems. I want the meat and potatoes of my code that matters on the server. I won't even get into the intellectual property or security considerations of why code should be on the server as I think that should be obvious with today's tech stack. I want to leverage the front-end code for only front-end matters. I want a pristine viewmodel of sorts returned via a service, where the only logic happening in the presentation layer is that of view manipulation and presentation logic. I've been on enough projects where IP and rules heavy work was done on the client (why, because you can!), only to have year long projects to refactor that code back to the server behind services.

Using an oversimplified view of the layers, let's look at the following using physical size to demonstrate placement and emphasis of code. Instead of a heavy client-side implementation like shown below:

I believe the implementation should be more along the lines of this based on everything discussed:

Put stock in your code on the server. History shows that in the battle of volatility the server-side wins out and the web is just too dynamic. Add to this security, IP considerations, and the unbelievably volatile and ever-changing world that is the 'web' it really is the smart move to make. The cynics will bring up leveraging CPUs on the client vs the server, but the world has changed. Data is small and efficient. The server has oodles of horsepower and is a known entity; we control it. The client is a wildcard; we don't know what they have. Long gone are the days where we know the client is a Windows machine controlled by an organization with a spec machine.

When analyzing data, as opposed to fat SOAP payloads of the past, payloads now are concise and to the point leveraging HTTP standards to deliver data as lean as possible. One must also yield to the fact that the days of 4GLTE and blazing fast WiFi and networking speeds are becoming the norm and will only continue to get better. It's pointless to argue that all apps must work flawlessly offline because that isn't reality across the board. We're in a world where if we aren't connected, things just don't work. Don't plan on making any airline reservations or bank account transfers when your device has no connectivity. I'll also avoid edge cases at this point as I understand there could be web apps made for 3rd world countries or the like where bandwidth is a premium, so data across the wire must be under the microscope. I'm sticking with mainstream, modern day, web development here. I'll leave the door open for you to evaluate edge cases that don't fit the 80/20 rule and call for an exception.

I can always go to the server and scrape off the services layer and re-introduce a new tech to replace that abstraction if needed. There are architectural recommendations within the server as well to make sure to thin-out the services facade and keep lightweight as that too as mentioned is know to be volatile over time. On the front-end, I want this same flexibility. Odds are I'll be asked to rewrite my web app in a few years to 'project x' tech which is the best thing ever for the web! I need to be lean up top and be able to scrape that thin veneer or icing off the cake, and put a new layer on easily. This isn't so easy to do if I've put the majority of my code on the client. When the boss or architect comes to me and says, "we are redoing our financial app using new front-end tech" I'll be positioned to say, "no problem, we can mitigate the ripple affect because the key logic and inner-workings of our app are stable and on the server, so we'll just need to redo the thin veneer that is the web-client code."