Skip to content

Instantly share code, notes, and snippets.

@jehugaleahsa
Last active August 30, 2023 18:37
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jehugaleahsa/f49fa5d3a60145e8cbcdc72750e09c76 to your computer and use it in GitHub Desktop.
Save jehugaleahsa/f49fa5d3a60145e8cbcdc72750e09c76 to your computer and use it in GitHub Desktop.
Razor and TypeScript

Once more around the bend

We're just going in circles...

If you have been a web developer for a while, you probably feel like you're going in circles. Going all the way back to CGI scripts, you were generating HTML using string literals, formatting and concatenation:

const message = "Hello, World!!!"
console.log("<html><body>" + message + "</body></html>");

Then someone decided it would be easier to inline code into HTML documents directly, using a more declarative approach:

<%
    $message = "Hello, World!!!"
%>
<html>
<body>
<%= $message %>
</body>
</html>

Then someone else decided this led to too much code showing up in the UI, so they split things out:

<% $model = import("backend").getModel() %>
<html>
<body>
<%= $model.message %>
</body>
</html>

Then Microsoft came up with ASP.NET and made separating UI and backend explicit via code-behind. Of course, in doing so, they also doomed a generation of developers to having to work around the framework to do basic HTTP.

Then with things shifting toward client-side and AJAX, people started trying to work around ASP.NET and we eventually ended up with MVC. Just in time for jQuery to take over the world.

Curiously, when jQuery was still young, people started manipulating the DOM by building HTML using string literals, formatting and concatenation:

var message = "Hello, World!!!";
$('#parent').append('<div>' + message + '</div>');

Now we're back to the good, old CGI days again, except on the client side. Dear lord! So, someone decided to go the PHP route again and we ended up with templating, thus we had mustache and handlebars.js. With handlebars we had access to branches, loops and more!

Suddenly, templates started having a lot of logic in them and we needed a better mechanism to separate out logic from UI... again. So AngularJS comes out and it makes it really easy to tie a view to backend logic via controllers and $scope.

We are we now?

Now with Angular2, I feel like we're dealing with ASP.NET again, but on the client side. Most of the code has moved into TypeScript, which means we can opt for more type safety. There's almost no access to raw HTML anymore and HTTP is pretty well-hidden behind Http. You build out these elaborate components and you compose them to build out your applications, similar to ASP.NET's user controls.

Unfortunately, Angular2 has one MAJOR flaw -- it was designed to be built on the server side, using server-side development tools, like Node.js, gulp, tsc, webpack, AngularCLI, etc. Much of what the framework does can be done before it is ever sent to the client's machine... but it doesn't! Instead, it ships off an enormous compiler to the client, only to JIT compile all of your templates on first load. Even if your files are cached, you browser is going be doing some serious crunching before anything can be displayed - before it can even begin to start making other HTTP requests!

So AOT (ahead-of-time compiling) is supposed to make up for that obvious deficiency but it is hard to configure (some might say nearly impossible) and it imposes annoying limitations on the code.

The reality is Angular2 should probably have been designed with server-side template compilation as the default from the start. I wouldn't be surprised if a near future version of the library made that radical change and AOT just becomes a part of the normal build process. What's curious is that doing too much ahead-of-time compilation can have the opposite affect of making your payload bloated. Gah!

So what's next?

I would be very surprised if Microsoft isn't already working on "Razor for TypeScript". The biggest drawback with client-side templates right now is a lack of type safety. There's no tooling support or Intellisense to map what's in a TypeScript file to what's in a template. You're basically running blind. Generally, this level of type safety isn't really necessary when you keep your templates small and really break things out into reusable components. Where it does bite you is refactoring - you simply can't rename variables that are referred to by your templates.

Razor was a bit revolutionary because it allowed you to type C# code in HTML, without the need for special tags, like <% %>, <? ?>, etc. Most of the time, a simple @ was a good enough indication. Tie that in with Angular2-like components and you've really got something. Most importantly of all, you make sure that template is built on the server side, packed up and ready to go to the client. Imagine:

<html>
    <body>
    @message
    </body>
</html>

That file would need to be tied to the backing TypeScript file somehow and the tooling would need to understand that relationship, just like Visual Studio knew .aspx files mapped to .cs files. An alternative would be to take the MVC approach and pass the "model" to the view and use something similar to the @model syntax. That avoids the need for some of the special tooling support, at least.

Summary

Admittedly, it is all a bit confusing. Wasn't that all ASP.NET was doing? Aren't we just doing the same thing we did before but now in TypeScript instead of C#? The difference is that TypeScript compiles to JavaScript and that allows it to be run in the browser. The process of compiling templates stays on the server, but the logic for manipulating those rendered templates (aka, the DOM and shadow DOM) all takes place on the client.

Strangely, doing server-side template rendering limits you. When you show/hide child HTML, they have to be part of a pre-compiled template. You can't just slap arbitrary HTML into your innerHTML. Believe it or not, this is probably a good thing, as it is much more secure. It also forces developers to define their components up-front.

I don't think we're really going in circles; we're just spiraling closer to the ideal web development platform.

@genifycom
Copy link

No! We really are going in circles.

As more and more code moves to the browser, the browsers will begin to run out of memory (they are already using huge amounts of memory) and performance will slow. At that point, we will switch back to more code on the server side.

The "management" of code on the browser side is completely unproductive. It is hard to manage "projects". Refactoring is a nightmare! Every day or so a "new" framework comes out which is not compatible with other frameworks. Horrible.

This is NOT Computer Science. This is butchery.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment