Let’s get this out of the way first — I understand the fatigue that comes with hearing about the newest framework of the week, but Marko isn’t a new framework. Rather it’s an older, and somewhat lesser known library originally created at eBay that focused on the whole server rendering concept probably long before that was a twinkle in the eyes of some of your current faves. (As a JS dev I'm obligated to say that it's "Blazingly Fast" as well, sorry).
Recently Marko has announced some exciting new changes that can be seen as similar to the shift from React’s class components to hook-based function components. It’s called the Tags api and to me it feels like a nostalgic return to form for web development.
Although this article mainly compares Marko to React, if you’re an average Vue or Svelte enjoyer then you’ll also feel at home with some of these comparisons because Marko:
- Enhances HTML with JS instead of enhancing JS with HTML
- Has reactive primitives that “just work”
- Enjoys all the benefits of being a compiled language
Let’s unpack some of this.
Enhanced HTML vs JSX
Try to think back to when you were first learning web development. If it was anything like my first time then it involved writing some plain old HTML and JS in notepad.exe and watching elements on the page go brrrr. Or maybe you first got a taste for it making themes for your tumblr or myspace blog. Or maybe you were a PHP dev, in which case, my condolences and also are you okay?
And in between jQuery and Angular maybe you found out about React + JSX, which looked like the familiar html syntax, but not quite because there were enough rules and variation that gave it quite the learning curve initially. And although you don’t need to use JSX to use React, let’s face it, if you’re not using JSX you’re going to get bullied. So combine that with learning how hooks work, add in a little redux/mobx, multiply by the amount of bundler and transpilation shenanigans, and then carry the dozen or so css frameworks and...well it really feels like web development took a complicated turn.
Here's where I want to say "enter Marko, stage left", but Marko was already just kinda standing on the stage dressed as a tree.
The first thing to like here is that with Marko any valid HTML is also already valid Marko, so if you already know how to write HTML then you’re more than halfway there. As a smaller benefit, attributes are also all interpreted as JS values so there's no need to suffocate them with curly braces either. This is already a much easier transition for the aspiring web developer than hopping right into JSX.
It's easy to take for granted how natural writing JSX becomes after staring at it for 5+ years, but for beginners the pitfalls in the differences between JSX and HTML are deep and often covered with leaves and branches.
Let’s look at an example of the same basic, non-interactive “Hello, World” in React:
import React from "react";
function HelloWorld() {
return <div>Hello, World</div>;
}
And also in your standard .marko
file.
Playground link
A lot less boilerplate, that’s for sure, but definitely nothing dramatic. Let's dig deeper.
Reactive Primitives vs useState
Let’s modify these examples to have an input field that will update who we’re saying "Hello" to in real time.
In React you’d use the useState
hook, which returns the current value along with an updater function as an array that you normally destructure. Then you'd call that updater function with your new value whenever you want to update it. Simple right?
import React, {useState} from "react";
export default function HelloWorld() {
const [value, setValue] = useState("world");
return (
<>
<p>Hello, {value}</p>
<input value={value} onInput={(e) => setValue(e.target.value)} />
</>
)
}
In Marko, you use the <let>
tag, which behaves similarly to the let
variable declaration in plain js, and to update it you kinda just…update it?
** Please direct all comments about the syntax to the Marko Discord channel.
Because we used the <let>
tag here, Marko knows that whenever value
is changed then anything that uses it needs to be re-rendered. No proxies, update functions, or reducers required.
Using the bind syntax, this example can be made even more concise.
And all we really did was enhance some plain old html with a few bits of extra syntax and suddenly we have have state in our component. And that's just the tip of the iceberg because you can create your own tags to grab state from anywhere, such as a global store, indexeddb, or localStorage.
Loops without the L
As we know, everyone’s favorite part of React is rendering multiple children in a loop. I think it’s the ugliness and reliance on beginner-unfriendly looking JS that really draws the crowd you know? I mean just look at this beauty?
import React from "react";
function Countries() {
const countries = ["Sudan", "Chile", "Japan"];
return (
<div>
{countries.map((country) =>
<p key={country}>{country}</p>)}
</div>
)
}
Let’s compare that to Marko though…
I mean, this comparison isn’t too bad right? But let's say I want to make it so that when you click on a country, that country’s color changes to some random color? Well in React, I would probably want to create a new component and manage the state separately:
import React, {useState} from ‘react’;
import getRandomColor from ‘./colors’;
function Country({name}) {
const [color, setColor] = useState(null);
return (
<p style={{color}} onClick={() => setColor(getRandomColor())}>
{name}
</p>
)
}
function Countries() {
const countries = ["Sudan", "Chile", "Japan"];
return (
<div>
{countries.map((country) =>
<Country name={country} />)}
</div>
)
}
Here's where Marko starts to gain the advantage over Svelte and Vue. In Marko you can create a reactive value at any point in the tree, including inside loops, and it’ll still work just how you’d expect.
I didn’t extract it out to a new component or do anything particularly complicated in order to add a bit of state. This is what Marko calls Fine Grained Reactivity. Of course you can create components in Marko as well, but Marko doesn’t force you to do so at the first sign of slightly complex behavior, or readability issues, or even for technical limitations.
Crying about components
Components are really a developer tool for organizing the developer's mind, and not something that your framework should force upon you when you don't really need it. And yet components in traditional frameworks are themselves seen as entirely stateful or stateless and you have to now learn terms like "Dumb", "Smart", and "Pure" and think hard about how to best optimize the type of component you use for the task at hand. Sometimes you even have to manually memoize entire components to get them to not render multiple times.
Marko's Tags api is a paradigm shift that takes away the burden of having to worry about most of the complexities of the framework itself and most other frameworks frankly seem too far along to copy it. It does so by allowing you to put state not on the component level, but wherever you want or need it to be.
And I know a lot of people will probably see the ability to add state anywhere in your tag as an easy way to write messy code, but I personally see it as a great method of prototyping complex functionality without having to worry about splitting tiny little parts of your project into separate components first. These tiny parts can always be slapped into a new component almost as easily as copy-pasting it into a new file, and at the end of the day whether you use components or inline it all into one big mega component, the html output should look more-or-less the same because the components are "compiled away" into only the truly reactive sections of the page. And you as a developer, in theory, don't have to worry about any of that. And with Marko's built-in server side rendering focus you won't even have to do any special setup to provide an optimized experience to the end-user.
Conclusion
This of course isn’t a full tutorial on Marko or the Tags api and I’ve really only lightly grazed the surface of what’s possible here. There are a few other tags that are comparable to React's hooks such as the <effect>
tag for running effects when variables change as well as the <set>
and <get>
tags for context passing.
The Tags api is still in the development phase and won't be fully released until Marko 6, but my team and I have been using the Tags api preview in production for a few months and have been reaping quite a few benefits already. But the possibilities here are like this pandemic: endless. For example imagine a tumblr/myspace/wordpress like website where writing extensions or widgets is as easy and simple as writing plain html and then "enhancing" it with a bit of functionality. It could get a whole new generation of youth into web development.
Between the Tags api's easy html-like syntax, fine grained reactivity, and built-in SSR, Marko may shape up to be a key player in the framework wars in the near future, so my suggestion? Invest in the stonk.
Top comments (0)