Recently i read the VUE-documentation about client side rendering, which is considered to be slower than server side renedering:
...because the browser will receive a largely empty HTML page, and has to wait until the JavaScript is loaded before rendering anything.
This is commonly agreed, but is it really true?
When you read this page, what do you see? Is this HTML? No! What you see is the graphical representation of what we call the "DOM tree", the internal database that resides in your browser. HTML is just one way to tell the browser, how to create the DOM tree.
But wait, is it really HTML that defines the composition?
No, not really. When Tim Berners-Lee invented HTML, the computers at the CERN this days could not display colors at all. They had this handy "green on black" screens, you all know from the film "the matrix", so they did not use colors. That is the reason you can set a text to "BOLD" or ITALIC, but not to "RED" with HTML. It is a child of the late 80th and hasn't changed much since then. The capabilities of HTML to represent more than just plain text are fairly limited.
Setting up the DOM
What sets up a page content is HTML and CSS, and the process those two work together is fairly complex. As CSS changes the behavoir of the machine that "renders" HTML elements, a browser first has to load the CSS definitions before he can start to do anything. And as the processs to determine, which CSS definition is applicable to a single element is fairly a complex and painfull work, it is just a wonder that this still is recognized as "fast". Modern browsers are absolute great pieces of software to keet track of the process and deliver a smooth user experience anyway.
The common belive of the "fast HTML pages" completely turns out to be a fairy tale, if you create multi page applications with "Hyperlinks". This was initially the core concept of the WWW, but also a reason to use Javascript: if the page needs a complete page reload to jump from one content to another, it is nothing users would accept today.
HTML is still the standard
But anyway, static HTML+CSS is a common way to deliver web content, and from a security perspective, server side rendering has big advantages. But that is not our focus here, we are talking about speed and user experience. And most pages will have some Javascript anyway, at least to perform some page updates.
Sure, the user experience will be bad if a page stops rendering to wait for a some content or Javascript to be loaded, but this is the disadvantage of using two different rendering engines, not a general constrain. If a page was purely built with Javascript, the user does not see any delay at all.
Talking about Rendering engines: Would it be possible to create your own "Rendering engine"? It is not only possible, is is fairly simple, as the HTML-DOM-Api exposes all the possiblilities of HTML+CSS to Javascript. And after the "Browser war", the Api of all modern browsers is mostly identical. From that perspective, using HTML files is just a detour. Most markdown parsers do exactly this, they get some "content" and call the appropriate api functions to "render" the content.
Using stateless programming on a stateful DOM
One reason for slow page loads is the size of the downloaded files, mainly caused by external libraries to be loaded. Some file types like images can be loaded delayed, but the main scripts used to render the page have to be loaded before. So it is very important to have this modules as small as possible.
So, let´s see, what is "state of the art" today? There are many approaches out today to help you to build better web pages. The most common frameworks like React and Vue rely on an external state logic. It is common sense, that it is necessary to have some logic to control "state changes" on a web page to reduce the number of unnecessary transactions of the page.
This was true, if the DOM was completely statles, but in fact it is not: the DOM is a state machine. Each element on screen is represented by a DOM element, that know precisely what state the element has. And browsers are extremely good at maintaining state changes. Even complex interactions on the DOM are hidden from the user to provide a smooth experience.
So, if the browser does all this, why do we need a second machine that does the same? Truth is, that functional programming used to control a state machine is not the best Idea you can have. Im not talking about possible advantages of functional vs object oriented vs procedural programming, which is another topic. Functional programming has - at least for complex applications - big advantages. But to control the DOM smoothly, you may need things like a "virtual DOM" to use it. And many tasks of websites like reacting on a button press are not very complex. This is easily done with event functions like "onClick". So, you get a big overhead to do things, that otherwise would be easy. Or, to say with other words: some frameworks solve problems that you would not have without them.
New approaches to web programming
There are many libraries and frameworks that try to change the roles like Svelte, that creates precompiled JS code from a source, which is made of a melange of HTML and JS. Finally you have the choice to run your code on server- oder client side.
About two years ago I tried to find out, if you can create web pages without HTML at all, and the results where pretty amazing. There is a free library on github called the Document Makeup Library DML that is mainly a wrapper to the HTML-DOM-API. This little piece of code allows to create full featured web applications relatively fast, the introduction page is a good example of what is possible. There are some more examples on dev.to.
If you don´t want to dig deep and like just a quick intro, you can check out a demo, that implements the core routines in only some lines of code. I total you get a complete responsive calculator application in just 61 lines of javascript without any html and no external library. Direct Dom Programming can be extremely compact.
Using the DOM as a state buffer
Creating HTML elements directly with the DOM-api gives you full access to the DOM tree without id´s or lengthy "getElementBy..." calls. An element created from withing Javascript gives you a direct reference to the DOM tree:
let el = document.createElement(typ)
So, if you store the reference in a variable, you can directly access the complete state of an element, including screen position, content etc.
el.style.color = "red"
You can even store own properties in the element for later access.
el.myProperty1 = "remember me";
el.myProperty2 = 200;
The only thing that might be a bit tricky is to find out, which CSS rules are actually used for the element.
Creating elements from within Javascript gives you another big advantage: If you create an object inside a function or a class object, the element reference is only know to the creating parent and is not exposed globally. You gain the power or "encapsulation". If you create elements within a javascript Class, the DOM-elements are bound to the Class Objects, which have their own local namespace. So you will avoid any namespace conflicts.
Long story short
There are many cases where delivering HTML will be the solution of choice, and the security advatages of severside rendering are undisputed. But not using HTML may give you some unexpected new options to create web applications.
There are simple and fast solutions to handle state changes in all modern programming languanges. They have been used and tested for a long time and that are perfectly applicable to web programming. Using getters and setters is the most simple solution to let a state change show up in a DOM element, that was created by and is bound to a Javascipt objcet.
The DML-Library has already proven, that you also can use complex arrangements of elements in a way very similar to the use of web components, but without the overhead. I found that web development generally speeds up very much. So, it´s really worth a try to build a web without HTML.
Top comments (12)
What a great discussion here in the comments. It's always good to know how things work behind the scenes and have the insights to try different approaches using JS, especially now that search engines are able to index it.
This is baffling to me. Unless you do something really weird, a page should load in < 300 ms, which I've never heard of anyone complaining about.
There are some issues with your notes on performance. For example, a page rendering with DML will not be able to take advantage of the same browser caching as regular HTML pages. The same goes for caching of external resources like CSS files with styling reused across pages. Packaging it all up as Javascript has significant performance costs.
Your general approach (and your work on DML) also seems to ignore a lot of the benefits of CSS and HTML: a lot of work has been done to make complex code relatively maintainable and easy to reason about.
Styling elements individually, which DML seems to encourage, requires a lot of discipline in extracting and reusing small functions -- without necessarily encouraging that practice. CSS encourages exactly this by providing reusable classes as the most basic abstraction.
On the other hand, you're not alone in this. CSS frameworks like Tailwind are very similar in being close to styling for every element.
Hy Niels,
thank you for checking out DML so thoroughly. Let say: this is just an experiment, but in some cases it works pretty well.
Maybe I have to clarify some points:
If you check out the DML-homepage, you will find a lot of "living" examples with interactive code. I developed this page without any external tools within some days only. I´m pretty sure this was not possible with any other framework i kow.
You can use CSS and DML without any limitations, even with Tailwind or any other tools you like. I used shoelace on my demonstation page, which integrates pretty well. There is absolutely no difference if an element was created fromHTML or with DML, it just behaves the same.
Using inline styles is not encouraged as a general approach. But if you need some styling for a single element only, you can do so without creating a separate CSS definition, you do not even need an ID for that. But if you want some general styling, you better go with an external CSS file.
I found, that the CSS files I use with DML are much smaller than things I usually see. This is, because I only need the general styles, nothing that applies to a single element only.
You have all the benefits of caching for external files, there is absolutely no difference if you use DML. You can also use lazy loading if you like. Just, you do not need to cache any HTML, as there is none.
The browser is very efficient to optimize DOM interactions. Even if you rely on heavy DOM manipulations, you will hardly see any flicker at all. As long as your code is not too stupid, the result will be very smooth.
So, currently all projects I started with DML came out pretty well, just using Javascript. If it comes to reusable code, this is truely an advantage to go just with JS-classes instead of webcomponents. But this is only possible, if you do not use any HTML at all.
I see that using external CSS files is possible. I think my confusion stems from your continued uses of phrases like "just using Javascript"---even in the response above you phrase it like that. If you are using CSS, then all your code isn't in Javascript.
Am I correct in understanding that the goal of DML is limited to replace HTML with Javascript? If so, how is it different in its aim from e.g. React or Vue that replace HTML with their own templating?
Finally, on your note about the site you built:
I think your site looks like a great case for a static-site generator like Eleventy, with some vanilla Javascript to run the code examples. I think a few days sounds reasonable. The output would be more cacheable HTML.
I think there's a fundamental thing I'm not understanding with DML. You are largely reproducing the logic of HTML while replacing the syntax with something that is valid Javascript. I understand that you get easier references to elements in this way, but other than the syntax it doesn't really differ from many other templating languages... I feel like I'm missing what it does differently and better on a fundamental level?
There are some fundamental differences between a "markup language" and a programming language: You cannot use any "logic" in HTML beside some very simple, predefined tasks.
Assume, you want to have a "responsive design", which generates a different page depending on the screen width. This is just simple with the DML approach, you implement the decision with one line of code.
In the "classic" approach, there is a special tooling in CSS for just that case. But what, if you want to create the site differently based on sceen orientation, or based on the daytime? Everything easy done with Javascript, but you will possibly find no tool that does exactly this. This is the reason, tools like Angular or JQuery have such a overwhelming number of options: They need to provide a tool for every possible situation.
If you need to create a list of numbers from 1 to 100, this is just one line in DML:
What options you have with just HTML? Learn Angular and use ng-for? So, you alway have to jump out and get more complexity in your setup. And you probably will be limited to what this external tools provide.
As you may see, with a programming language you are prepared for every possible situation with some lines of code and with the tool you already know. With the "declarative" approach, you need a new tool for every possible situation. Maybe you have seen the "interactive editors" on the DML homepage. That have been created also with JS only and without any new tools to learn. It is just plain Javascript.
There is another important difference: Names in HTML are always globally scoped. So, for every element you need to access, you need to create a separate name or "ID". With DML, you get the DOM refecence directly, so you can encapsulate the process. See this example, that is also on dev.to compared to a "classic build":
There is some code to create a small working clock with DML, all elements included. Here is the complete code you need to create a nice group of colored clocks. No React, no Angular, now Webcomponents:
This is the result:
See the full code here
I understand the advantage of having a programming language, and how that gives you more flexibility. But at the end of the day, e.g. React is also just Javascript - with a little bit of HTML-like syntax in JSX files. Both React and DML requires adopting a framework and learning its conventions.
For the example of the clock, there is no need for DML - the same could be achieved with plain HTML and Javascript. It's a neat example of how a very simple and general programming language can be really powerful, compared to a large, opinionated framework. And I agree! Plain Javascript should be used more often, and is more powerful than what people give it credit for!
Given some function
myClock
that returns an element, you could do this in plain Javascript:It's only slightly more verbose, and leads me to my previous question: is DML mostly about the new syntax? In which case that's cool, but for most of what I do I'd want more granular control than always appending new elements to the document per default.
I think it's absolutely fine and good that you are experimenting and finding different ways of doing things! And your approach definitely works.
I think what I'm reacting to, and trying to suss out now, is based on your claims of better performance than e.g. using classic static pages... it's an interesting experiment, but there's a lot of things DML doesn't consider in its approach.
If you prefer and enjoy it, that's absolutely fine by me!
But it also seems less unique in the space of frontend web technologies to me than how you present it.
Thank you anyway for the in-depth discussion!
Likewise! I always think it's really cool when people try completely unexpected things. And DML has definitely made me think through a lot of things in order to evaluate it :-)
Hy Niels,
looking to you example above, did you recognize that you did exactly the same what my code does?
Every DML-component uses _base.append(... internally. So you could write:
This is precisely the same what you did, you just do not need to do it manually.
But the main value of the concept is different:
I like the message that you are trying to communicate about web development being fragmented, with three (or more) languages to learn instead of one, but I am not confident that a convergence on JavaScript is the solution.
DML library is intriguing, but it doesn't seem very beginner friendly. The simplicity of HTML is one of the reasons the web is so approachable. I think web frameworks that focus on building on top of HTML like Marko and Svelte have the potential to achieve your goal of unification without taking away the approachability of the web.
React is also not very beginner friendly. After about 2000 pages of documentation I gave up.
DML is not as complicated as it may seem, but it requires some programming skills. If you now how to write code, the learning curve is pretty flat. All DML functions that create HTML elements use just the same names, so h1("text") creates a headline, ul(["This","is","a","list"]) creates a list.
You will need to learn CSS usage, but the style sheets I used have been pretty short compared to what I find on other projects. And the overall number of files included in your project is pretty low. If you check out the DML-homepage, this uses just a small number of tools:
This is pretty much all you need to compose the page. No framework, no database, no CMS, no extensive tooling. And not much more to learn than some Javascript and CSS.
I agree with you about the beginner friendliness of React (so much that I wrote a post about it), but even the DML homepage states that it is "easy to learn if you speak 'javascript' and know HTML and CSS already [emphasis added]." That said, for the target audience of people who already know programming it is an excellent tool.