DEV Community

Paul Gordon
Paul Gordon

Posted on • Updated on

After creating RawJS, I'm never touching React again.

EDIT: I'm the author of RawJS. Everyone, please cool your jets. Omitting this on the main article was an oversight, and my authorship of this library was stated in my bio from the get-go.

EDIT 2: I'm considering locking the comments in this article, rewriting it, and linking forward. Some people are taking serious issue with the way I've framed parts of it. It's steering the discussion in a way that I don't think is productive for the community. I'll leave this here but if the turbulence in the comments continues, I'll lock & rewrite.

Way back in October of 2012, TypeScript 0.8 was released. I was working on a midsize JavaScript project at the time. The day it was released, I read over the initial spec, and after about 10 minutes of playing with it, I become so convinced that it would be the future that I began rewriting my entire app in TypeScript. The benefits over standard untyped JavaScript were that dramatic.

I get the same feeling with RawJS.

RawJS is a tiny library that makes vanilla JavaScript app development vastly more ergonomic. It's not just the latest web framework of the day to compete with React, Vue, Svelte, or whatever else. RawJS is different.

RawJS is a visceral demonstration of why the whole premise of frameworks themselves is perhaps a bit misguided. It suggests that most apps would likely be better off using vanilla JS and adopting certain programming patterns.

That's a pretty bold statement, I know. But I implore you to look into the mindset and the thinking behind what brought RawJS to life.

React Tends To Poison Projects With Crippling Levels Of Complexity

I don't believe I'm going out on too much of a limb by stating that React is overcomplicated. After all–Svelte was created specifically because of this.

React leads to bloated apps. Case in point––I recently was given the task to oversee the development of a React app whose complexity had spun out of control. I ended up throwing out the entire app, and reconstructing the whole thing with RawJS, using a team who had never touched RawJS, or had even done much direct DOM manipulation at all. Within a couple weeks, the team was up to speed and now the app is about 90% smaller than the previous React app. No, that's not a typo.

We've come to the point now where React is the "no one gets fired for buying IBM" choice. Problem is––people should be fired for buying IBM. This is the metaphor for the individual who can't be bothered do adequate needs analysis, defaults to herd mentality, and blindly goes with whatever most other people are using out of some combination of fear and laziness.

The degree of React's overcomplexity becomes a lot more clear once you've had the pleasure to develop an app using RawJS-accelerated vanilla JavaScript. RawJS calls into question the necessity of props, state, hooks, JSX, forced inheritance from specific bases (React.Component), Virtual DOM, automatic data binding, and essentially everything that React does.

The bloat of React and the restrictions it imposes (such as forbidding you from editing the DOM directly) are all centered around trying to maintain the integrity of it's Virtual DOM system, which I see as a solution to a domain-specific problem that was specific to facebook.com, that well-built apps simply don't have.

The alleged performance disadvantages of direct DOM manipulation are vastly overblown. As a matter of fact, when done properly, direct DOM manipulation usually results in improved performance. This is because you're able to get precise control over how the DOM gets updated. It allows you to go in with a scalpel update tiny regions of the DOM as necessary. Virtual DOM is the opposite of this. It's a blunt tool that runs a complex diffing algorithm over huge swaths of DOM subtrees in order to automatically compute what needs to get updated.

The usefulness of automatic data-binding and reactivity are also over-blown. Assuming your code is well organized, building your app so that the DOM updates as a consequence of data changes doesn't appear to result in any less code than just building the app to update the DOM explicitly when and where necessary. But the difference with the former is that it forces upon you a massive hard-to-debug black-box, and forces conformance into their layer of bureaucracy. It's hard to appreciate the benefits of getting away from this until you've put together a well-built vanilla JS app (such as with RawJS!).

Why is no one talking about Anonymous Controller Classes?

Anonymous Controller Classes (ACC) are a pattern that needs to get more attention. They're one of the key ideas that transform a vanilla JavaScript app from a sloppy mess into something coherent and beautiful.

The basic premise of an ACC is to create an object that is loosely connected to a single element in the DOM, and whose garbage collection lifecycle is equal to the lifecycle of the connected element. It's an advancement over and above inheriting from HTMLElement, which is another option (but one which I don't like, for reasons I'll leave to another article).

Consider the following code:

class SomeComponent {
    readonly head;

    constructor() {
        this.head = document.createElement("div");
        this.head.addEventListener("click', () => this.click());
        // Probably do some other stuff to this.head
    }

    private handleClick() {
        alert("Clicked!")
    }
}
Enter fullscreen mode Exit fullscreen mode

ACCs are classes that create a single .head element, possibly other nested elements, connect event listeners, assign styling, etc. They have methods which are typically event handlers or other helper methods. You then instantiate the component, and add the component's .head element to the DOM:

const component = new SomeComponent();
document.body.append(component.head);
Enter fullscreen mode Exit fullscreen mode

The class is considered "anonymous" because you can discard your instance of the component as soon as its attached to the DOM. The instance of the class will be garbage collected as soon as the element is removed from the DOM and garbage collected, because the DOM is the only thing that owns a reference to it. For example:

class SomeComponent {
    readonly head;

    constructor() {
        this.head = document.createElement("div");
        this.head.addEventListener("click', () => this.remove());
        // Probably do some other stuff to this.head
    }

    private remove() {
        // Remove the component's .head element from the DOM,
        // which will by extension garbage collect this instance of
        // SomeComponent.
        this.head.remove();
    }
}
Enter fullscreen mode Exit fullscreen mode

The great thing about ACCs is that they impose essentially no restrictions. They can inherit from anything (or nothing). They're just an idea––you can mold them to behave however you like.

Of course, there are many scenarios when you might want to get the ACC associated with a particular element. For example, imagine iterating through the ancestor elements of the this.head element, and getting the ACCs associated with it in order to invoke some public method. There is a lightweight library called HatJS which is designed to improve the ergonomics around working with ACCs.

EDIT: I'm the author of HatJS. And "Anonymous Controller Classes" is a term I originated. It's a pattern that emerged during experimentation, though I doubt I'm the first person to discover it, because the concept is quite obvious. Like JSON before it had a name. You don't need to use HatJS with RawJS. A lot of people are building vanilla JavaScript apps (or "vanilla TypeScript apps" for the pedantic) and having good success just by creating custom elements that inherit from HTMLElement, effectively merging the element and the controller into the same entity. I've built a few apps with that method and have decided that ACCs are better for reasons I can cover in a future article.

Improving document.createElement() has surprisingly powerful implications

Although this article attempts to make the strongest case possible for using the DOM APIs directly, one area where these APIs absolutely fall flat is in the area of constructing complex DOM hierarchies with attributes, styling, and event attachments. This part of the DOM API is so verbose that without some outside help, your code is going to be about 10x longer than it needs to be. This is where RawJS comes in.

RawJS was designed for exactly one purpose. It gives a 10x improvement in the ergonomics around document.createElement(). Call functions and get hierarchies of HTMLElement instances. It does nothing else. There's no weird background magic. You may not think this sounds terribly impactful. But you would be wrong in that assessment.

It turns out that for the last 15 years of ideation around framework patterns, we didn't need Virtual DOMs, reactivity, data-binding pre-compilers, or any other wild science projects. We needed the anonymous controller class pattern and a better way to create HTMLElement instances.

Using these two techniques, I can say for certain that I will never willfully use React, or any other competing framework again. This class of framework simply doesn't have enough to offer over and above what can already be done with JavaScript, to warrant the enormous weight and bureaucracy they impose.

So what does RawJS code look like? Calls to the RawJS creator functions follow the form:

const htmlElement = raw.div(...parameters);
Enter fullscreen mode Exit fullscreen mode

The powerful ergonomics come from the breadth of what is acceptable as a parameter (typed as a Raw.Param in RawJS).

Parameters can be strings, numbers, booleans, arrays, functions, DOM Node instances, calls to raw.on("event", ...) (which create portable event attachments), and pretty much anything else. RawJS always does what you'd expect.

I'm not going to reiterate the awesome things you can do with RawJS to construct hierarchies. This is covered in detail in the quickstart.

The main idea is that because nearly anything can be a Raw.Param, you're able to create mini libraries of functions that generate lists of Raw.Params and return them. The level of code reuse you can achieve with this is unprecedented. Again, its hard to appreciate until you've actually worked with it. I hate to make the comparison to LISP / closure, but there are similarities.

The best CSS-in-JS solution I've seen

What good is an HTML element hierarchy constructor without being about to also construct the corresponding CSS? RawJS also has the best-in-class CSS-in-JS solution that does things I've not seen in any other solutions. For example RawJS has full support for CSS that is scoped to a particular element.

const anchor = raw.a(
    // This constructs CSS within a global style sheet,
    // and the rules below will be scoped to the containing
    // anchor element.
    raw.css(
        ":focus", {
            outline: 0
        },
        ":visited": {
            color: "red"
        }
    ),
    raw.text("Hyperlink!")
);
Enter fullscreen mode Exit fullscreen mode

There is quite a bit of other things that can be done with RawJS's CSS-in-JS solution. This article isn't meant to be a RawJS tutorial, but if you're looking for that kind of thing there is a quick-start and a demo app.

Using the DOM as your state manager is actually good.

A common objection we get is, where do you store your application state? The answer is to use the DOM as your state manager.

Before you shudder at this, remember how tailwind pioneered the idea of dropping millions of class names on HTML elements, effectively recreating the equivalent of inline CSS, which for years was thought of as an anti-pattern, but the devs were insistent that it's actually good, and now everyone is doing it? The same idea applies to using the DOM as your state manager.

The way how everyone has decided to build apps these days is to start with some kind of data structure which is deemed to be your "source of truth", and then you need to awkwardly project this into a UI somehow. Doing it another way is considered "naive" or even an anti-pattern. However, I would like to suggest that having two separate representations that need to be kept in sync, itself is an anti-pattern.

Trying to use some framework to declaratively map your data into DOM has lead to vast amounts of increased complexity. The problem with this technique is that having two separate representations of the same thing is automatically going to be more bloated than a hypothetical alternate technique where there is only one such representation.

It turns out that it's actually much better if you make your ACCs accept input data in order render themselves. Then, you have some kind of save function that inspects the state of the DOM to produce a saveable chunk of data. This way, your source of truth doesn't have to synced with the DOM because your source of truth IS the DOM.

Inspect the following code example:

class FormComponent {
    readonly head;
    private readonly firstNameInput;
    private readonly lastNameInput;

    constructor(firstName: string, lastName: string) {
        this.head = raw.form(
            this.firstNameInput = raw.input({ type: "text", value: firstName }),
            this.lastNameInput = raw.input({ type: "text", value: lastName }),
            raw.button(
                raw.text("Save"),
                raw.on("submit", () => this.save())
            )
        );
    }

    private save() {
        const firstName = this.firstNameInput.value;
        const lastName = this.lastNameInput.value;
        SomeDatabaseSomewhere.save({ firstName, lastName });
        alert("Saved!");
    }
}
Enter fullscreen mode Exit fullscreen mode

See? You just store the values right in the DOM. In this case, we were using the value of a text input, but you could also store the data as HTML attributes, class names, or whatever makes sense.

Granted, there are cases where you need to store state that can't be broken down into strings, numbers, and booleans. I've also seen some cases where state is stored within properties within the ACC. Do whatever works for you.

Communication between components

There are situations where you may need to update multiple components in response to one action, or to more simply send messages between ACCs. HatJS can help with this.

Remember, ACCs create a kind of hidden controller hierarchy. You have your typical DOM hierarchy of elements, but only some elements are the head elements of an ACC. So this creates its own ACC hierarchy that is a strict subset of the whole DOM element hierarchy.

HatJS has functions to traverse the ACC hierarchy, and quickly capture the ACC instances that may or may not be sitting behind an element.

class ParentComponent {
    readonly head;
    constructor() {
        this.head = raw.div(
            new ChildComponent().head
        );

        // Call Hat.wear() to define the object as a "hat"
        // and make it discoverable by HatJS
        Hat.wear(this);
    }

    callAlert() {
        alert("Hello!");
    }
}

class ChildComponent {
    readonly head;
    constructor() {
        this.head = raw.div(
            raw.on("click", () => {
                // Hat.over finds the "Hat" (or the ACC) that exists
                // above the specified element in the hierarchy.
                // And passing ParentComponent gives you type-safe
                // tells HatJS what kind of component you're looking
                // for, and also gives you type-safe access to it.
                Hat.over(this, ParentComponent).callAlert()
            })
        );
    }
}
Enter fullscreen mode Exit fullscreen mode

In addition to Hat.over(), there is also Hat.under(), Hat.nearest(), and other methods to find other ACCs of specific types that may or may not exist in the DOM relative to specified elements.

Get excited!

So, have I convinced you to set your React app on fire and rebuild your life's work with vanilla using RawJS? Here's the RawJS website if you'd like to get started. The repo for RawJS is here, and the repo for HatJS is here

Top comments (235)

Collapse
 
runi profile image
Runi-c

Just in case anyone else got mislead by the deceptive way this article was written, RawJS and HatJS aren't "hidden gem" libraries you simply hadn't heard of yet, they are virtually unused & untested libraries written by the author of this blog. Similarly, "Anonymous Controller Classes" aren't a paradigm you simply haven't been exposed to before - they're another invention of the author.

I admit that this was quite appealing to me as I was reading, however half of that appeal was the feeling of discovering a new paradigm that had been battle-tested and is emerging as a contender in the field, like when I first discovered Rust. Going to the GitHub to see what the community was like and finding it utterly nonexistent - zero issues, zero PRs not by the author, zero discussion - makes me feel as though I've been deceived by clever wording. You should reword this to make it clear you're the author of these libraries and the ACC concept.

Collapse
 
paulgordon profile image
Paul Gordon

I'm sorry you were mislead but that wasn't the intention. It was clearly stated in my bio that I'm the author of RawJS. People are skipping over that and then assuming that I'm trying to deceive people.

RawJS has been in development for over a year, and it's been the subject of considerable pressure by numerous apps, from large to small, mobile (Capacitor) to web. It works. There are essentially no known bugs. Because the library is very tiny (2.3KB) and actually doesn't do much (by design) so it's not terribly difficult to get to that point. Everything that has been committed in the last little while has been minor enhancements to address edge-case scenarios that don't affect main-line development.

Nowhere in the article did I ever say that this technique was an "emerging as a contender in the field". I'm simply sharing my actual experiences, and being completely honest that I personally see no reason to use any framework ever again, and my observation is that I see a lot of people getting tired of React, and moving to vanilla JavaScript, either by inheriting from HTMLElement or otherwise.

My general take is that I came down too hard on people's sacred cows, and now I'm experiencing the brunt of it. Frameworks tend to be extremely territorial, because if one's framework of choice loses popularity or becomes seen as stale/old, this diminishes the value of their time investment. So when their framework of choice is threatened, some will kick into an emotional state and jump to all sorts of petty attacks, maybe without even realizing they're doing this.

Collapse
 
runi profile image
Runi-c • Edited

I'm glad the disclaimer is in your bio, unfortunately that doesn't show up on mobile so I never saw it.

When I say "battle-tested" I mean adopted by many people for many widely varied projects of various scales and requirements. It's great that you've fixed all the bugs you know about, but that speaks nothing to edge cases that haven't been tried yet or pain points encountered when people try to use your library for a specific use case. Every library has these pain points and I was very interested to read about yours. For example, Svelte has dozens of these, ranging from scoped styles not applying to components to a total lack of real error boundaries. Because your library has no discussion of these, I would have to take a gamble and discover the pain points for myself, along with workarounds since there'll be no supporting ecosystem around your library to tap into.

I struggle to believe the post wasn't worded the way it was with the intention of being deceptive. The article begins by comparing your discovery of TypeScript - an experience I'm familiar with - to your discovery of RawJS. But these experiences are nothing alike because you wrote RawJS to meet your needs. Furthermore, posing questions like "Why is no one talking about Anonymous Controller Classes?" implies that this is an established concept that you stumbled upon and believe is underrated. There are dozens of other ways to communicate this point that don't come off as deceptive, like "Introducing Anonymous Controller Classes" to make it clear that you are introducing a new concept to us.

I think it's unfortunate that you're choosing to deflect these criticisms from myself and other commenters by suggesting that we're unknowingly "kicking into an emotional state" in a territorial defense of our beloved frameworks. This is a way to at once dismiss our concerns and minimize our intellectual agency in making them. It's fine to disagree with my reading, but I'd prefer you leave it at that without attempting to gaslight me into believing I wrongly made the criticism while in an irrationally emotional state. I also just disagree wholeheartedly with this suggestion, because as mentioned in my first comment I was actually rather excited upon reading this, and I have no particular love for React specifically.

Thread Thread
 
paulgordon profile image
Paul Gordon

Sure, I guess that's reasonable that my comparison to TypeScript could have been misleading. Though I feel as though RawJS is a discovered technique. I'm certainly not the first to make a better document.createElement(). There are others, even some library authors of similar tools showing support in the comments.

I honestly don't know why other people aren't using Anonymous Controller Classes. It's a new term but I doubt it's a new thing. It's too basic. I understand how this could be deceptive... but does this really matter? It's a technique. It works for me and others. Do you think its dumb? No problem! Don't use it.

It's quite obvious that people are jumping to an emotional state.

A non-emotional comment looks like:
"Hmm interesting idea. How would you handle situation X?"

An emotional comment looks like:
"Your ideas are misguided. You don't know what you're talking about because I need feature X to handle situation Y".

Read through the comments. A lot of them read like the latter. You cannot reasonably deny that people are not jumping into an emotional state (though I will grant you that you seem like one of the more level-headed ones)

I find it hard to believe that people are getting worked up because some author made a disclosure in his bio, but didn't do so in the article when it was first posted. There is absolutely some amount of territorialism going on, though we may disagree on the degree.

And now you're accusing me of gaslighting you, without realizing that I've been the last 3 hours writing replies to every single person who responded, trying my best to handle their concerns (even the ones that are clearly out to attack me).

Thread Thread
 
jmorenn1993 profile image
Jarvis Morenn

I'm not going to jump down your throat or anything (seems like you've had enough of that), but I still will say that this response is a huge deflection. You strike me as an intelligent enough person, which is also why I know you're being intentionally obtuse. This is very clearly an article written from the perspective of someone who "discovered" a pre-existing technology as if they have had no prior exposure to it. The fact that you created the product means you have plenty of exposure to it. So why is the tone written as if you've never heard of it until now? Well, to market the product of course. And more power to you! Nothing wrong with marketing. But just own it I guess. The tone of the article is not written as a creator but a consumer.

That being said, RawJS sounds awesome! Good job. I look forward to following the progress.

Edit: Ah nevermind. The way you handled perfectly reasonable comments below changed my opinion again. No accountability whatsoever.

Thread Thread
 
paulgordon profile image
Paul Gordon • Edited

Please point out where I've taken "no accountability whatsoever". That is extremely unfair. It's 1:00 am, and I've been up since about 9:00am and I feel like I've literally done nothing but take accountability where it is due.

Thread Thread
 
paulgordon profile image
Paul Gordon

About "discovery", please understand where I'm coming from. I was the author of a real-time compiler for a "discovered" language rather than an "invented" one: (github.com/paul-go/truth) There is a difference between the two. I can agree this is an esoteric concept that most people don't have much exposure to.

Collapse
 
Sloan, the sloth mascot
Comment deleted
 
paulgordon profile image
Paul Gordon

Wow, this may be one of the first supportive comments I've received all day.

I don't know much about your project, but maybe you could start by taking a look at the sample app here:

rawjssample.pages.dev/

Thread Thread
 
webjose profile image
José Pablo Ramírez Vargas

Hey, I was supportive, wasn't I? I just said it felt too niche.

Thread Thread
 
paulgordon profile image
Paul Gordon

Lol yes, you were one of the better ones ;-)

You're probably right about it being niche, at least for now while the support / help base is low and the flex of the library is for situations where you're building UIs that diverge significantly from the usual business form-filling apps.

Collapse
 
ptejada profile image
Pablo Tejada

Well said and based. I was getting hyped myself for a second but it was shortlived. Just like he Paul G rawvolution 😅

Collapse
 
ceuk profile image
CEUK • Edited

I've been around long enough to have been uneasy from almost the moment I started reading this article. All the best pitches are boring, dull, nuanced affairs. They usually come with a deadpan delivery from someone who has been in the trenches looking at pros and cons for a few days/weeks/months. This kind of excitable, "omg this is so cool" dog with a bone kinda stuff is almost always biased/driven by something that the individual is intellectually enamored with rather than objectively appraising.

A bit of advice for others who find themselves doing this (as I have many times): don't sell your integrity for the sake of the latest thing you think is cool. You'll quickly get a reputation and people will stop trusting your ability to be objective.

The whole article is either incredibly naive or incredibly disingenuous. After finding out that the author wrote the library and given the way this article is written, I'm leaning towards the latter. This article could have been phrased as an honest exploration or a prompt for discussion. But it's not, it's written as a misrepresentative, one-sided sales pitch.

Further, if I try an put aside the skepticism and engage with the article itself, the whole thing is a bit bizarre.

Fundamentally, the big message in this article seems to be to eschew MVU/ELM architectures and state-driven applications in general. It's basically saying you can munge your model and your view into the same thing.. I almost don't know what to say to that.

The class-based "component" was already worrying (we moved away from them in React for some very good reasons..) but then the idea of having to constantly dive into the DOM to ascertain state is just too much. Do people not remember the jQuery days? I almost can't believe that such a step backwards is being unironically espoused in 2024.

The author calls React bloated, but at its core, the premise of React is incredibly simple, and a decade or so ago, was the answer to many of the issues that the approaches being pitched here were causing when trying to build large web applications:

view = function(state)
Enter fullscreen mode Exit fullscreen mode

All a React component is, is something that transforms state into a view. The author calls the view and the model (state) "two representations of the same thing" - but that's just not true. Why not just get rid of the database too? Data & presentation of data are two separate things. Why on God's green earth would I want to fetch a JSON array from an API, map it to DOM nodes to present it, then traverse those same nodes and transform them back into data (and pray nothing else had touched them) every time I want to access or manipulate the list somehow?

You wouldn't want to use the DOM as your source of truth for the same reason you wouldn't monkeypatch shared globals. You don't own it, it's too easy for things to change unexpectedly. There are a myriad of reasons why a browser, browser extension, user script etc would want to touch/manipulate the DOM. Not only is it a rubbish format for data storage, it's also an very brittle medium.

I've not even talked about so many other things like how imperative this approach is, how much time you'd waste with low-level concerns that can be abstracted instead of writing actual business logic etc

This whole thing smells of Not Invented Here syndrome. Sorry.

Collapse
 
jongtelles profile image
Jon Telles

You nailed it, couldn't agree more.

Collapse
 
paulgordon profile image
Paul Gordon

All I can say in response to this is: tell me without telling me you simply don't know how to build a well-organized vanilla JavaScript app.

You're not the target market. You want a framework to tell you what to do. A lot of developers fall into this category. You should keep doing that, it sounds like it's working out for you. For the stuff I build, I need freedom and control.

Collapse
 
ceuk profile image
CEUK

simply don't know how to build a well-organized vanilla JavaScript app.

I've been developing for the web long before anything you could call a framework even existed but that's not the point. It doesn't matter whether I do or don't. You're saying "build a well-organized vanilla JavaScript app" but you're not talking about vanilla JS. You're just talking about a different framework (one that you apparently built). I mean FFS the whole thing is Typescript-based, and you're calling it "Raw JS".

Let's be clear, you're not asking people to move away from React and co into the absence of anything at all (which would be a big enough waste of time) - you're just asking people to trade their mature, battle-tested patterns and approaches to come play in your sandbox.

You want a framework to tell you what to do

What a weird thing to say about React. In all your criticisms of React you failed to mention one of its biggest failings: it's actually so unopinionated that every project seems to have a different set of patterns/standards.

But that aside, you're damn right I want a framework to tell me what to do, just like I want strong patterns and good abstractions of low-level common implementation details. Like most developers, my day job is writing business logic, not imperatively reinvent the wheel to fix problems that don't exist/matter.

Thread Thread
 
paulgordon profile image
Paul Gordon

TypeScript is optional. You don't need to use it with RawJS if you don't want. This is the first I've heard of someone who understands "vanilla JavaScript" to mean: no TypeScript, no tailwind, no outside help from anything at all. It usually means "no frameworks that force upon you data-binding, state management, and a multitude of other things".

"you're just asking people to trade their mature, battle-tested patterns and approaches to come play in your sandbox."

No. "My sandbox" in this case is the W3C DOM. I don't own that. I think you're thinking that RawJS is just some other framework that might as well just be another React or Svelte, though one that has fewer features. This is wrong. It's a minimal document.createElement() abstraction, and the point of the article is that either this abstraction (or another, as some other library authors have commented), is all you really need.

"But that aside, you're damn right I want a framework to tell me what to do" <-- This wasn't a knock.

Thread Thread
 
ceuk profile image
CEUK • Edited

If it's not a framework or something that can be "implemented" then what are you even pitching here? A bespoke approach to every project?

Also.. of course it's minimal, it's a borderline proof-of-concept piece. You're not comparing apples and apples.

If this is really to be a serious approach for building complex web applications for large, diverse groups of people you'll have to solve all of the same problems as the major frameworks.

It's basically the 80/20 rule. I'm sure I could write a version of React that delivers 80% of the functionality with 20% of the code size (Isn't that basically what Svelte is? :D). But that last 20% is what makes it a robust solution for enterprises and SMEs around the world.

Just in your first example alone it's so easy to read ahead and see how quickly that would baloon out and become just as complex (likely more-so) than modern React and co once you start scaling up.

You're not the first person to come up with this, e.g. xxxxx (edit: company name redacted just in case) rolled their own typescript-first "no framework" approach when Flash died. It's eerily similar in intent and approach to what you propose. So what challenges do they have a decade or so in?

  • It's an incredibly WET (as in, not DRY) codebase. The codebase has over a million lines of code and takes a team of almost 1000 developers to maintain.
  • They have a huge amount of tech debt. So many of the things they could have got for free but reinvented due to chasing the "clean room" dragon are now languishing. Critical dependencies are outdated and in need of upgrade but they don't have the expertise or bandwidth to do it.
  • Onboarding new developers is a nightmare. No one has used their "framework" before (obviously) and it's not what modern developers are used to (think React.createElement era).
  • They can't hire in outside experts (there aren't any) so they are massively dependent on a couple of "resource silo" individuals.

If your message is meant to be that this is a great approach for quick prototyping or proof-of-concepts, then great. But bespoke code is always a dream at first. It's after none of the original developers are left and you've had to extend the functionality and refactor it a few times that you see if it's worth anything. Too much of what I see here is too similar to stuff I spent a lot of time trying to get away from for my comfort.

Thread Thread
 
li2go profile image
li2go

Pertinent, objective and to the point.

Collapse
 
jongtelles profile image
Jon Telles

This is such a telling response to solid and reasonable criticism.

Thread Thread
 
paulgordon profile image
Paul Gordon

It wasn't reasonable though. It was laced with insults and excessive disagreeableness, and was written like you assumed I started programming 6 months ago. So I returned the favour.

It's like this––I've gone down every single path of reasoning you've articulated. Every one of the points you've brought up are reasonable objections, but as a person with many years of large-scale vanilla JavaScript app development under my belt, I've spent the time to develop a number of strategies to mitigate them. Hence the reply "tell me without telling me..."

A proper response to these objections probably requires an entire dev.to article. Which I plan to write some day.

Thread Thread
 
sgammon profile image
Comment marked as low quality/non-constructive by the community. View Code of Conduct
Sam Gammon

Bro is this you? Being reasonable

Image description

Collapse
 
le00 profile image
le0-0

His arguments for why one shouldn't store state in the DOM are completely right, and you don't even attempt to refute them. After anyone has read the arguments and understand them, attacking the person who first uttered them does not resolve the criticism.

Thread Thread
 
paulgordon profile image
Paul Gordon

A new article will be coming that covers the omissions made in this one. Give me a follow if interested! 👍

(That said, there is a thread somewhere in the depths of this comment section where there is some discussion about storing local component state within the DOM with good success)

Collapse
 
gregorygaines profile image
Gregory Gaines • Edited

I was curious about the progress of your framework, but this some of the most pretentious, degrading, and disingenuous replies I've ever read in my short career as an engineer.

@ceuk provided honest, sound, and respectful criticism even though he didn't have to.

I will be blocking you and hope to never see any technology or article of yours going forward.

Thread Thread
 
paulgordon profile image
Paul Gordon

I found his tone to be quite unwilling to engage in productive ideation, he had clearly already made up his mind to be dismissive, so I chose not to respond with anything meaningful (that, and there were about 50 other comments I needed to get through at the time). If he wants to come back and have an open-minded back and forth, I'm all ears!

Collapse
 
midwestdevopsdude profile image
william jenkins

It’s a super interesting concept but after reading through comments and investigating GitHub, I agree this is a pitch by the author of the project and this design called ACC. You still need typescript, this isn’t even written in vanilla JavaScript itself. That’s the biggest anti-pattern in the article.

Kind of glaring to call it RawJS and give very few examples, not to mention it’s a library, not a actual new thing. Your article is written as someone discovering the project and using it. It’s fine to be proud but it’s deceitful for the article to be written this way. I can’t even find any real world examples besides some color swatches on a page that actually doesn’t operate correctly. Big ideas for something clearly not vetted, reviewed, or have contributors.

Collapse
 
paulgordon profile image
Paul Gordon

It was an oversight. The article was updated.

"Vanilla JavaScript" usually doesn't preclude TypeScript. It typically means "no react / vue / whatever".

Collapse
 
sampsonprojects profile image
Sampson Crowley

Vanilla js is vanilla js. Typescript is a superset of vanilla js, and is not vanilla js. It typically means "no framework". RawJS is a framework and is not vanilla js. Saying your framework is vanilla is like saying jquery is vanilla. It's not. It's a framework.

Vanilla "typically" means "raw". Build using the engine provided APIs. Just because you call it "RawJS" doesn't make it so.

Thread Thread
 
paulgordon profile image
Paul Gordon

RawJS isn't a framework. Its a micro-library. There is a difference. There are other micro-libraries that solve a similar problem set as RawJS. Some are linked in this comment section.

Using your vocabulary, if I use even a single dependency, I've now exited the realm of vanilla JavaScript. This is a bit silly.

Thread Thread
 
sampsonprojects profile image
Sampson Crowley • Edited

😂 using a dependent is not vanilla js. They're not exclusive. That runs through a library that doesn't exist in the engine is not vanilla. Your module is no less a framework than react is. Where exactly do you draw the line that is "micro"? Exactly how many lines is that?

Your code doesnt do one thing and one thing well. It is a framework for DOM management. Just because it's not using a virtual dom doesn't make it not a framework.

Thread Thread
 
paulgordon profile image
Paul Gordon

function createDiv() { return document.createElement("div"); } OMG FRAMEWORK WHERE DID VANILLA JS GO??

You very obviously don't understand what RawJS does, possibly some of that is my fault for not explaining things better, but either way I'm done with this childish conversation.

Thread Thread
 
sampsonprojects profile image
Sampson Crowley • Edited

Your inability to accept reality and immediately getting angry and defensive with every single person who disagree with you is hilarious

Thread Thread
 
jef_283c8da2 profile image
JeF

I do not think RawJS is a framework. It’s a library (which is different from a framework).
Your code calls a library.
In a framework you will have some inversion of control happening (your code is called by the framework).

Thread Thread
 
paulgordon profile image
Paul Gordon

Thank you for the reasonable explanation. The phrase "inversion of control" escaped me 👍

Collapse
 
Sloan, the sloth mascot
Comment deleted
Collapse
 
salcarluccio profile image
Sal Carluccio

OMG… take it easy with your judgement, mate!!! I think this is an excellent opportunity to start thinking about what really React and similar libraries are all about and maybe have an independent mindset. The complexity and all the prerequisites that a developer needs just to run React is absurd so well done for proposing a new way forward.

Collapse
 
juanmendes profile image
juanmendes

I disagree. If you're the author of a library, this post must say that. The way it is written, it is deceitful.

Thread Thread
 
salcarluccio profile image
Sal Carluccio • Edited

Maybe so, but I believe there are better ways to communicate your disagreement within an open community. If you have a look at the author’s profile at the bottom of this post you’ll find the mention that you are looking for.

Happy New Year

Thread Thread
 
paulgordon profile image
Paul Gordon

I updated the article. It was an oversight. People need to chill.

Thread Thread
 
mreed4 profile image
Matthew

As interesting as your take is, especially on React and all of its faults, you kinda shot yourself in the foot with the clickbait title and not initially mentioning you are the author of the tech that you are praising. In a sense the damage has been done. I'd take this as a learning opportunity.

Thread Thread
 
paulgordon profile image
Paul Gordon

I'll take the point as a learning opportunity, but it's been in my bio the whole time that I'm the author of RawJS.

Thread Thread
 
sampsonprojects profile image
Sampson Crowley • Edited

Nobody is reading your bio before reading the article. Most people don't care enough about you to even click it at all. They're here for the article and your defense that "it's in my bio" doesn't change anything

Thread Thread
 
paulgordon profile image
Paul Gordon

Ok bud. You got me. I guess I'm a snake oil salesman. Those MIT-licensed open source libraries with zero profit potential are really raking in the bucks for me.

Thread Thread
 
sampsonprojects profile image
Sampson Crowley

The fact that you're so defensive about it is proof in itself. You really think people read your bio? Are you reading the author bio of every article you read?

You're projecting your own insecurities on things that are never said. I stated the facts, and that's it.

Have fun using your unproven self written framework in production. The rest of us will be using battle tested libraries for real projects

Collapse
 
webjose profile image
José Pablo Ramírez Vargas • Edited

Hello! I like this very much. I must say, though, that I don't think people will happily embrace it, not to the scale of state-driven frameworks like Svelte or React. Why? Because people don't like it when they have to write code. Sad, but true. People love their JSX and their template-based component files. Hell, I cannot deny how beautiful it is not to think recursively when building DOM's. Having VS Code + Emmet + Svelte extension to help me write HTML is far more appealing that recursion-like calls to create it.

The use of classes you present is very nice: You are reusing DOM elements via containment to make sure none of the DOM complications get out, and work your way around to only expose what you will be needing. It is very nice indeed. Again, the average developer won't like it.

Finally, the last point: State-driven development arose for a very good and strong reason: Simplicity. You are asking the state-driven addicts to leave their drug forever and come back to imperative programming.

Finally, a question: You stated that the object created from the class would have the same lifecycle as the contained DOM element, but I see no code that backs this up. Omission in the examples? Or did I miss something?

Collapse
 
paulgordon profile image
Paul Gordon

A developer colleague of mine recently threw out a Svelte app and rewrote the thing with RawJS because he was so impressed with it. His RawJS version is about the same amount of code as the Svelte version. So at least from that data-point the "its more code" argument didn't hold, assuming the measure is total number of lines.

RawJS has full support for JSX if you want to use it. I probably should have covered that in the article. Though I don't really like JSX so I omitted it.

I think you mean "nested function calls" rather than "recursion". In any event, it's actually less characters to use the nested function calls rather than JSX. And because its just plain-old functions, you get VS Code's intellisense for free.

State-driven development is easy until it's not. That was the point I was hoping to make in the article.

About the lifecycle of the DOM elements... assuming you don't store references around, it would garbage collect. I'm not sure how you would show that other than to just say it.

Collapse
 
webjose profile image
José Pablo Ramírez Vargas

Hello. It is not the number of lines of code, and it is not the number of characters you type. It is the simplicity of state-driven programming versus imperative programming. People moved to state-driven because nobody liked imperative once you reach a certain point (in application code size). So no, we cannot measure this by lines of code.

Yes, "nested". Apologies, English is not my mother tongue. Sometimes my brain malfunctions.

As stated, I think you have something really nice here, but I don't see how this can compete in the open. This looks very niche to me. For example, from what I read, how would you open and close dialogs? How do you show a validation error conditionally? How do you manage table rows, or list items? It is not obvious, and I fear it will require pretty much all the imperative programming we used to see 20 years ago, before the jQuery era but without the browser differences and a friendlier DOM API.

To be more concrete: Your code samples have no indication of how one should program a TableRow component that is meant to be dynamically created based on a mutable list of items. Should we add a dispose() method of some sort to this and all components to properly remove DOM elements? As far as I can see, RawJS helps in the creation of elements, not in the cleanup of elements. Must I provide this? If yes, why don't RawJS provide, as other libraries do? I don't see the complete lifecycle management here. These and several others are the things that people will miss for sure.

Thread Thread
 
paulgordon profile image
Paul Gordon

Yeah, I would agree there's very few examples here which is a buzz killer. I've built a few different large-scale apps with RawJS so far (one is open source), so I can say first-hand that the stuff you mentioned doesn't create the feeling of pre-jQuery bookkeeping.

There's a simple demo RawJS app here that covers at least some of your concerns:
rawjssample.pages.dev/

(repo)
github.com/squaresapp/rawjs-sample...

I probably should have included that in the article.
Of course this demo app doesn't show how things scale. For that you'd need to see the Squares app source code.

I appreciate this feedback, by the way 👍

Collapse
 
simiacode profile image
Akshat

I don't really like JSX so I omitted it.

Thank you. The world went loopy with JSX. And the current paradigm of functions that produce JSX that has embedded JS that calls functions that output JSX gives me extremely traumatic flashbacks of JSP

Collapse
 
ohidere profile image
ohidere • Edited

Good luck. I'll stick to React.

Edit: read through the article and wonder how anyone could take so many steps back into history. There's a reason for React and other framework's existence. Embrace it.

Collapse
 
kinnell profile image
Kinnell Shah

If you're wondering why anyone would, they wouldn't and they haven't. @paulgordon is the author of the library. His lack of candor in not being forthcoming about that should tell you how seriously anyone should take him. His aim is clearly deception.

Maybe he should have looked inwards when it comes to finding the biggest tool.

Collapse
 
paulgordon profile image
Paul Gordon

Work on your judgement bud. I updated the article to indicate that I'm the author.

Collapse
 
andrianarivo profile image
David Andrianarivo

Me too. I'm currently learning Next.js and I enjoy it. I must admit, reading this article made me remember the feeling about writing some monolithic apps with RoR. It just feels simple and welcoming. With time I understand the downfall of such simplicity. It lacks the tools you need to quickly inhance the UX. Think of framer-motion, routing capabilities (how else are you going to make routing feels nice 👍), caching, suspense - for skeletons - and content streaming.

Don't get me wrong, I enjoyed reading this article. Keep up the good work 💪💯.

But it's probably wise for me to stick with Next.js.

Collapse
 
g0d profile image
George Delaportas (ViR4X)

Dear Paul,

A more direct approach with much less complexity and powerful utilities is the Vulcan. I've working on this since 2012 among other projects.

It's blazingly fast, easy and follows the principle "write less, do more". It has almost no overhead and provides useful tools for everyday web development.

Vulcan is part of micro-MVC framework and is being used by thousands of companies.

Check it out at github.com/g0d/Vulcan

Collapse
 
paulgordon profile image
Paul Gordon

Thousands of companies and 2 stars?
(Actually 3 stars now... I just threw one in the bin)

Collapse
 
g0d profile image
George Delaportas (ViR4X)

It' irrelevant. We do not do marketing. We care about the actual business. It delivers and that matters!

Thread Thread
 
paulgordon profile image
Paul Gordon

Fair enough... but you've got to admit it looks a bit weird.

Thread Thread
 
g0d profile image
George Delaportas (ViR4X)

Check the parent project and see what we also built on top of that github.com/g0d/micro-MVC

Check github.com/g0d/GreyOS
It doesn't get better more awesome I guess ;)

Thread Thread
 
paulgordon profile image
Paul Gordon

See, this is the kind of stuff that I'd say you need direct DOM access for.

Thread Thread
 
g0d profile image
George Delaportas (ViR4X)

That's why I built Vulcan.js and micro-MVC.... I wouldn't be able to build GreyOS... All the tools that I see in the market are totally useless for that kind of hard work. You can check the performance and stability yourself!

Collapse
 
palalet profile image
RadekHavelka • Edited

Any documentation? I dont see any

Collapse
 
g0d profile image
George Delaportas (ViR4X)

Please check the parent project which includes it as well.

github.com/g0d/micro-MVC

Collapse
 
darkwiiplayer profile image
𒎏Wii 🏳️‍⚧️ • Edited

It's fascinating to me how every new "hipster" framework that pops up as of late seems to be doing the exact same thing I've also been working on roughly for the same time as most of these frameworks seem to have been around as well.

Simple libraries that fill the gaps in what the browsers already provide. Instead of adding a new layer of completely new abstractions, that get translated to the browser's model of the website, they just make interacting with this model more ergonomic.


Although this article attempts to make the strongest case possible for using the DOM APIs directly, one area where these APIs absolutely fall flat is in the area of constructing complex DOM hierarchies with attributes, styling, and event attachments.

Yep. I couldn't have said it any better. The way I described my own library with a similar aim is that it "aims to be what document.createElement should have been. It creates a node, sets classes and attributes, inserts content and attaches event listeners."

Collapse
 
paulgordon profile image
Paul Gordon

What's your library? Is it open source? Link it here if so.

Collapse
 
darkwiiplayer profile image
𒎏Wii 🏳️‍⚧️

It's just barely done at the moment and I haven't used it enough to confidently recommend it for production, and the website is still very much work in progress, but here it is: darkwiiplayer.github.io/skooma-js/

Thread Thread
 
paulgordon profile image
Paul Gordon

Cool, it seems we're on the same wavelength.

Collapse
 
gunslingor profile image
gunslingor

Wait a minute... your propomoting a library called raw js, not just using raw js as in js js?

That's insaine. I'll never use a lib named raw js, next we'll have raw typescript and c, c+, c++, raw c++.net... I know where the word game goes, and the tech world is too big for it these days... waste of time already.

Raw js, what a bunch of tricksters... certainly would trust em with my code... its a 3D online animator, I think I'll call it "raw Adobe flash" lol.

Collapse
 
paulgordon profile image
Paul Gordon

Ok.. so what else should I call it?

(I think your argument would probably hold better if I had called the library "VanillaJS")

Collapse
 
gunslingor profile image
gunslingor

Both are bad naming policies, marketing over engineering. But also deceptive, trying to direct true js programmers to it by confusing search. I honestly thoguht you were promoting no lib js. Tbh, I never interpreted vanillaJS to imply raw JS... I interpreted to be the opposite of chocolateJS... so in that regard, maybe the opposite of your intended meaning for RawJS would be CookedJS, ehich is a better and likely more accurate name anyway... just realize, many people have been saying raw js for decades now... I wouldn't be surprised if it turns out to be completely untrademarkable uncopywritable, not saying you would want to... but why eliminate the possibility for deceptive marketing. Cookedjs is better.

Thread Thread
 
paulgordon profile image
Paul Gordon

Well, somehow I've been in this game for quite a while I'm yet to hear anyone say "raw js" meaning "no framework". I've always just heard "vanilla js" or "vanilla javascript". I tried to pick something that was suggestive of vanilla that wasn't actually "vanilla", and wasn't something dumb like "Unflavoured.js".

Thread Thread
 
gunslingor profile image
gunslingor

Lol, love unflavored... you can't use vanilla already taken. It just it depends whether you like deserts or meat which is better, lol. No frame work, js, raw/vanilla/plain/es6 js all pretty much mean the same to my ears.

In the end, only reason to use someone else's framework is for standardization and speed, without a quantitative analysis proving yours is better in that regard, I just use an existing or built custom when needed... doing that now... crazy company is on bootstrap 2, had to build custom react component framework.

Thread Thread
 
dtasev profile image
Dimitar

Unflavoured.js is unironically a pretty catchy name

Thread Thread
 
gunslingor profile image
gunslingor

I've been programming for 20 years... I gave up on developers when I came across ANT, Another Neat Tool.

It's nuts... I've only sort of jokingly been trying to convince people we should name our software latin and classify it like they organisms, or physics theories, organs.

I wanna see names where you know what it is just by looking at it, and what similar options exist that overlap with that from someone else.

I.e. a universal ID system.

Too many libs don't play nicely with each other because of this issue, and too many companies end up in a partial migration state... ive seen react and angular in the same app... built with web pack.

Like for God sakes dudes, lol. I mean, I'm an engineer, when I need a ball valve I got 50 vendors I could go to, but they don't call it "another neat widget" or "maven the raven" or "gradle the... mavel?"... 😆 🤣.

I guess I'm always science over marketing... and naming is import in science. "To name a thing is everything, to name a thing is to truly know it". God help us on component naming.

Collapse
 
lebbe profile image
Lars-Erik Bruce

I embrace the idea of using native js, and the DOM API more. At the same time, I also like to use MARKUP for my documents, not javascript. If I can't have some templating that looks like jsx/php/jsp/etc, where I can also just inline plain vanilla HTML as I please, I just won't buy it, I'm afraid.

Interestingly enough, it looks like the quite opposite of the idea brought forth in this blog post, is the html-first principles, which shy away from JS, and use HTML attributes for dynamic behaviour. With the help of a JS library of course, named htmx.

I think RawJS and htmx are two extremes, where the ideal is in a middle ground: Give me access to the DOM API and all the other nifty web APIs modern browsers provide (which RawJS provides, but html-first rips away). But also, give me a HTML-like templating language, to describe my documents (which RawJS shreads to pieces).

PS: First thing I find when searching RawJS is a library that tries to replace lodash and moment.

Collapse
 
paulgordon profile image
Paul Gordon

RawJS supports JSX. Use it if that's your thing. I just don't like it myself. And I've found that more people dislike JSX than not.

Collapse
 
lebbe profile image
Lars-Erik Bruce

My thing is writing documents with a template language. If I can write pure HTML that would be even better.

Some comments may only be visible to logged-in visitors. Sign in to view all comments.