Concepts behind modern frameworks
Alex Lohr

Alex Lohr @lexlohr

About: ...former musician, voice actor, martial artist, started coding 38 years ago and turned front-end developer 25+ years ago.

Location:
Germany
Joined:
Jun 13, 2017

Concepts behind modern frameworks

Publish Date: Dec 19 '22
335 62

Many beginners ask "which framework should I learn?" and "How much JS or TS do I need to learn before a framework?" - countless opinionated articles go into promoting the advantages of the author's preferred framework or library, instead of demonstrating the readers the concepts behind them to allow for an informed decision. So let us get the second question out of the way first:

"How much JS/TS to learn before a framework?"

As much as allows you to understand the concepts they are based on. You will need knowledge of the basic data types, functions, basic operators and of the document object model (DOM), which is the representation of your HTML and CSS inside your JS. While everything beyond that will not hurt, it is not strictly required to become proficient with a framework or library.

If you are a complete beginner, JS for cats might be a good resource for your first steps. Keep going until you feel confident, then continue until you stop feeling confident again. That's when you know enough JS/TS and can move on to a framework. The rest you can learn on the go.

"Which concepts do you mean?"

  • State
  • Effects
  • Memoization
  • Templating and rendering

All modern frameworks derive their functionality from these concepts.

State

State is just the data powering your application. It may be on a global level, for a larger part of the application, or for a single component. Let us take a simple counter as an example. The count it keeps is the state. We can read the state and write to it to increase the count.

The simplest representation is usually a variable containing the data that our state consists of:

let count = 0;
const increment = () => { count++; };
const button = document.createElement('button');
button.textContent = count;
button.addEventListener('click', increment);
document.body.appendChild(button);
Enter fullscreen mode Exit fullscreen mode

But this code has a problem: changes to count, like those made by increment, are not updating the text content of the button. We could manually update everything, but that doesn't scale well for more complex use cases.

The ability for count to update its users is called reactivity. This works by subscribing and re-running the subscribed parts of your application to updates.

Almost every modern front-end framework and library has a way to manage state reactively. There are three parts to the solution, and at least one of them or a mix is employed:

  • Observables / Signals
  • Reconciliation of immutable updates
  • Transpilation

Observables / Signals

Observables are basically structures that allow to read via a function that subscribes the readers. The subscribers are then re-run on update:

const state = (initialValue) => ({
  _value: initialValue,
  get: function() {
    /* subscribe */;
    return this._value; 
  },
  set: function(value) {
    this._value = value;
    /* re-run subscribers */;
  }
});
Enter fullscreen mode Exit fullscreen mode

One of the first uses of this concept was in knockout, which used the same function with and without arguments for write/read access.

This pattern is currently seeing a revival as signals, for example in Solid.js and preact signals, but the same pattern is used under the hood of Vue and Svelte. RxJS, which powers the reactive layer of Angular, is an extension of this principle beyond simple state, but one could argue that its ability to model complexity is a whole arsenal of guns aimed at your feet. Solid.js also comes with further abstractions of these signals in the form of stores (objects that can be manipulated through a setter) and mutables (objects that can be used like normal JS objects or the state in Vue to handle nested state objects.

Reconciliation of immutable states

Immutability means that if the property of an object changes, the whole object reference must change, so a simple comparison of references can easily detect if there are changes, which is what the reconciler does.

const state1 = {
  todos: [{ text: 'understand immutability', complete: false }],
  currentText: ''
};
// updating the current text:
const state2 = {
  todos: state1.todos,
  currentText: 'understand reconciliation'
};
// adding a to-do:
const state3 = {
  todos: [
    state.todos[0],
    { text: 'understand reconciliation', complete: true }
  ],
  currentText: ''
};

// this breaks immutability:
state3.currentText = 'I am not immutable!';
Enter fullscreen mode Exit fullscreen mode

As you can see, references of unchanged items are re-used. If the reconciler detects different object references, it runs all components using the state (props, memos, effects, context) again. Since the read access is passive, this requires the manual specification of dependencies to reactive values.

Obviously, you are not defining state that way. You either construct it from existing properties or use a so-called reducer. A reducer is a function that takes one state and returns another one.

This pattern is used by react and preact. It lends itself to being used with a vDOM, which we will explore later when templating is described.

Not every framework uses its vDOM to make the state fully reactive. Mithril.JS, for example, updates from state changes after the events set in the component; otherwise you have to trigger m.redraw() manually.

Transpilation

Transpilation is a build step that rewrites our code to make it run on older browsers or give it extra abilities; in this case, the technique is employed to change a simple variable into a part of a reactive system.

Svelte is based on a transpiler that also powers their reactive system from seemingly simple variable declaration and access.

As an aside, Solid.js uses transpilation, but not for its state, only for the templating.

Effects

In most cases, we need to do more with our reactive state than deriving from it and render it into the DOM. We have to manage side effects, which are all things that happen due to state changes beyond updates to the view (though some frameworks like Solid.js treat view changes as effects as well).

Remember the first example from state where the subscription handling was intentionally left out? Let us fill this in to handle effects as a reaction to updates:

const context = [];

const state = (initialValue) => ({
  _subscribers: new Set(),
  _value: initialValue,
  get: function() {
    const current = context.at(-1);
    if (current) { this._subscribers.add(current); }
    return this._value;
  },
  set: function(value) {
    if (this._value === value) { return; }
    this._value = value;
    this._subscribers.forEach(sub => sub());
  }
});

const effect = (fn) => {
  const execute = () => {
    context.push(execute);
    try { fn(); } finally { context.pop(); }
  };
  execute();
};
Enter fullscreen mode Exit fullscreen mode

This is basically a simplification of the reactive state in preact signals or Solid.js without error handling and state mutation pattern (using a function that receives the previous value and returns the next), but that would be easy to add.

It allows us to make the previous example reactive:

const count = state(0);
const increment = () => count.set(count.get() + 1);
const button = document.createElement('button');
effect(() => {
  button.textContent = count.get();
});
button.addEventListener('click', increment);
document.body.appendChild(button);
Enter fullscreen mode Exit fullscreen mode

☝ Try out the above two code blocks in an empty page using your developer tools.

In most cases, the frameworks allow for different timings to let the effects run before, during or after rendering the DOM.

Memoization

Memoization means caching of values computed from state, to be updated when the state it is derived from changes. It is basically an effect that returns a derived state.

In frameworks that re-run their component functions, like react and preact, this allows to opt out parts of the components again when the state it depends on does not change.

For other frameworks, it is the opposite: it allows you to opt in parts of the component to reactive updates, while caching the previous computation.

For our simple reactive system, memo looks like this:

const memo = (fn) => {
  let memoized;
  effect(() => {
    if (memoized) {
      memoized.set(fn());
    } else {
      memoized = state(fn());
    }
  });
  return memoized.get;
};
Enter fullscreen mode Exit fullscreen mode

Templating and rendering

Now that we have state in pure, derived and cached form, we want to show it to the user. In our example, we used the DOM directly to add a button and update its text content.

To be more developer-friendly, almost all modern frameworks support some domain-specific language to write something similar to the desired output inside your code. Even though there are different flavors, like .jsx, .vue or .svelte files, it all comes down to a representation of the DOM in code that resembles HTML, so that basically

<div>Hello, World</div>

// in your JS
// becomes in your HTML:

<div>Hello, World</div>
Enter fullscreen mode Exit fullscreen mode

"Where do I put my state?" you may ask. Excellent question. In most cases, {} are used to express dynamic content, both in attributes and around nodes.

The most used templating language extension to JS is undoubtedly JSX. For react, it is compiled to plain JavaScript in a way that allows it to create a virtual representation of the DOM, an internal view state called virtual document object model or vDOM for short.

This is based on the premise that creating objects is much, much faster than accessing the DOM, so if you can replace the latter with the current, you save time. However, if you either have numerous DOM changes in any case or create countless objects for no changes, the benefits of this solution are easily turned into a disadvantage that has to be circumvented through memoization.

// original code
<div>Hello, {name}</div>

// transpiled to js
createElement("div", null, "Hello, ", name);

// executed js
{
  "$$typeof": Symbol(react.element),
  "type": "div",
  "key": null,
  "ref": null,
  "props": {
    "children": "Hello, World"
  },
  "_owner": null
}

// rendered vdom
/* HTMLDivElement */<div>Hello, World</div>
Enter fullscreen mode Exit fullscreen mode

JSX is not limited to react, though. Solid, for example, uses its transpiler to change the code more drastically:

// 1. original code
<div>Hello, {name()}</div>

// 2. transpiled to js
const _tmpl$ = /*#__PURE__*/_$template(`<div>Hello, </div>`, 2);
(() => {
  const _el$ = _tmpl$.cloneNode(true),
    _el$2 = _el$.firstChild;
  _$insert(_el$, name, null);
  return _el$;
})();

// 3. executed js code
/* HTMLDivElement */<div>Hello, World</div>
Enter fullscreen mode Exit fullscreen mode

While the transpiled code may look daunting at first, it is rather simple to explain what happens here. First, the template with all the static parts is created, then it is cloned to create a new instance of its contents and the dynamic parts are added and wired to update on state changes.

Svelte goes even further and transpiles not only the templates, but also the state.

// 1. original code
<script>
let name = 'World';
setTimeout(() => { name = 'you'; }, 1000);
</script>

<div>Hello, {name}</div>

// 2. transpiled to js
/* generated by Svelte v3.55.0 */
import {
        SvelteComponent,
        append,
        detach,
        element,
        init,
        insert,
        noop,
        safe_not_equal,
        set_data,
        text
} from "svelte/internal";

function create_fragment(ctx) {
        let div;
        let t0;
        let t1;

        return {
                c() {
                        div = element("div");
                        t0 = text("Hello, ");
                        t1 = text(/*name*/ ctx[0]);
                },
                m(target, anchor) {
                        insert(target, div, anchor);
                        append(div, t0);
                        append(div, t1);
                },
                p(ctx, [dirty]) {
                        if (dirty & /*name*/ 1) set_data(t1, /*name*/ ctx[0]);
                },
                i: noop,
                o: noop,
                d(detaching) {
                        if (detaching) detach(div);
                }
        };
}

function instance($$self, $$props, $$invalidate) {
        let name = 'World';

        setTimeout(
                () => {
                        $$invalidate(0, name = 'you');
                },
                1000
        );

        return [name];
}

class Component extends SvelteComponent {
        constructor(options) {
                super();
                init(this, options, instance, create_fragment, safe_not_equal, {});
        }
}

export default Component;

// 3. executed JS code
/* HTMLDivElement */<div>Hello, World</div>
Enter fullscreen mode Exit fullscreen mode

There are exceptions. In Mithril.js, for example, while it is possible to use JSX, you are encouraged to write JS:

// 1. original JS code
const Hello = {
  name: 'World',
  oninit: () => setTimeout(() => {
    Hello.name = 'you';
    m.redraw();
  }, 1000),
  view: () => m('div', 'Hello, ' + Hello.name + '!')
};

// 2. executed JS code
/* HTMLDivElement */<div>Hello, World</div>
Enter fullscreen mode Exit fullscreen mode

While most people will find the developer experience lacking, others prefer full control over their code. Depending on which issue they aim to solve, the lack of a transpilation step might even be beneficial.

Many other frameworks allow for usage without transpilation, though it is rarely recommended like that.

"And what framework or library should I learn now?"

I have some good news and some bad news for you.

The bad news is: there is no silver bullet. No framework will be much better than all others in every single aspect. Each one of them has their advantages and compromises. React has its hook rules, Angular a lack of simple signals, Vue lacks backwards compatibility and Svelte don't scale too well, Solid.js forbids destructuring and Mithril.js is not really reactive, just to name a few.

The good news is: there is no wrong choice – at least, unless the requirements of a project are really limited, be it in terms of bundle size or performance. Every framework will do its job. Some may require working around their design decisions, which might slow you down a bit, but you should be able to get a working result in any case.

That being said, going without a framework might be a viable choice, too. Many projects are spoiled by overuse of JavaScript, when static pages with a sprinkle of interactivity would have done the job as well.

Now that you know the concepts that are applied by these frameworks and libraries, choose those which are the best fit for your current task. Do not be afraid to switch frameworks in your next project. It is not necessary to learn all of them.

If you try a new framework, one of the things I found most helpful is to connect to its community, be it on social media, discord, github or elsewhere. They can tell you which approaches are idiomatic for their framework, which will help you to get better solutions faster.

"Come on, you must have a personal preference!"

If your main goal is to become employed, I would suggest learning react. If you want a great experience of effortless performance and control, try Solid.js; you might meet me on Solid's Discord.

But please bear in mind that all other choices are equally valid. You should not choose a framework because I say so, instead use one that works best for you.

If you got through the whole text, thank you for your patience. I hope it was helpful for you. Leave a comment while you're here and have a nice day!

Comments 62 total

  • Damian Tarnawski
    Damian TarnawskiDec 19, 2022

    I like how the one solid's compromise you decided to point out was that it "forbids destructuring". Point to voby I guess :D

    • Alex Lohr
      Alex LohrDec 19, 2022

      That's the point we get most complaints about, I guess.

      • David Di Biase
        David Di BiaseDec 19, 2022

        You should mentioned the understructure plugins :p that's our usual response to the complaints, heh.

  • Rense Bakker
    Rense BakkerDec 19, 2022

    Awesome in depth analysis! 👍

  • Fyodor
    FyodorDec 19, 2022

    Awesome, thanks 👍 that’s what I always try to explain to dev folks but cannot find proper words for

  • timsar2
    timsar2Dec 19, 2022

    look at signal(action) in rx-angular please.
    we can now build push-based and zoneless high performance angular application

    • Alex Lohr
      Alex LohrDec 19, 2022

      Thanks for your comment. I meant the simplicity of simple signals, not that you can emulate it with RxJS, as is elaborated more in this post .

  • Thorsten Hirsch
    Thorsten HirschDec 19, 2022

    Oh... wow, I've never seen such a great overview of the technical concepts of all these frontend frameworks! Thank you so much, Alex!

  • Sumit Saurabh
    Sumit SaurabhDec 20, 2022

    Love this article. Reading it made me feel like I’m getting a bird’s eye view of everything!

  • raviklog
    raviklogDec 20, 2022

    Nice Article...good start for someone new to these frameworks to think in terms of the concepts that you have presented.

  • Neo Sibanda
    Neo SibandaDec 20, 2022

    Love this article,its a great overview of the technical concepts of these modern frameworks.

  • Jaxongir
    JaxongirDec 20, 2022

    This is one of the most important and useful posts in 2022

  • hazre
    hazreDec 20, 2022

    Vue and Svelte don't scale too well

    Can you actually back this up? I know for a fact Vue scales well and it's used in large real world applications and there hasn't been too many big projects with Svelte to even state that.

    • Alex Lohr
      Alex LohrDec 20, 2022

      Good question. In fact, I do, thanks to the work of Ryan Carniato who took the pains to make precise measurements: dev.to/this-is-learning/javascript....

      That being said, not too well doesn't mean that this would be automatically prohibitive for it's use in larger projects. As so often in development, it depends.

      • peerreynders
        peerreyndersDec 20, 2022

        At 80 components Vue is in the Preact, SolidJS ballpark.

        Vue simply had a higher overhead per component than those two for lower component counts.

        From that perspective Vue scales as well as Preact and SolidJS for high component counts.

        Vue and Preact always fare better than React while it takes at least 1080 components before React requires less code than SolidJS.

        Svelte's per component overhead doesn't seem to amortize (as quickly?) at higher component counts.

        • Alex Lohr
          Alex LohrDec 20, 2022

          Does 80 components already count as big? That's probably arguable.

          • peerreynders
            peerreyndersDec 20, 2022

            As far as I understand it, in the context of the article it's 80 identical components rather than total number (though not really sure if it matters).

            • Ideally each (duplicated) component should require little additional overhead per instance.
            • The runtime should be as small as possible so that it's cost amortizes quickly as the number of components grow.

            I think the criticism of Vue was related to the hybrid approach of mixing reactive/vDOM, locking itself out of optimal runtime scenarios for either.

            The argument is that reactivity scales best when it isn't tied to components.

            • Ryan Carniato
              Ryan CarniatoDec 20, 2022

              Yeah Vue scales well on component size. If you go far enough it will be smaller than all the others. 80 "components" is loose. That might be accurate for like SFC styles but I'd say like in React the equivalent of those 80 components is more like 200 components because they tend to come smaller. I only went that far because for a single page load that is about as far as I'd want to go. Obviously apps will be larger with code splitting.

              So any concern I had with Vue scaling would be on reactivity + VDOM overhead, but I haven't actually benchmarked Vue that way to an extreme so I can't speak to it.

              • Alex Lohr
                Alex LohrDec 21, 2022

                Another concern with Vue is backwards compatibility, something react is surprisingly good with. There are many Vue 2 apps without a strategy to move forward.

                • peerreynders
                  peerreyndersDec 21, 2022

                  React may still support class components but in the case of Etsy:

                  Migrating from v15.6.2 to v16.13.1 would require a significant time commitment, due to the large number of breaking changes which have occurred in intervening versions.

                  was enough to tip the scale towards migrating to Preact v10.x instead.

                  So even with React there is continual pressure to modernise the code base just to be able to stay on a supported version.

                  • Alex Lohr
                    Alex LohrDec 21, 2022

                    I remember a similar migration, but we had only three instances of changed behavior, which were fixed in a few hours. It probably depends how much you rely on internal workings of the framework/library.

                    Still, with Vue 2, migration to v3 basically means a rewrite of the whole state and logic.

                    • Kasope Johnson
                      Kasope Johnson Dec 21, 2022

                      I will disagree with this, Alex
                      Vue 3 supports Options API fully (which is what Vue 2 is based on). The only major things that change are how the app is instantiated and how global configs and plugins are set into the parent Vue object instance.
                      There's a handy @vue/compat package that detects where critical changes need to be made to make this migration process easier

  • Friday candour
    Friday candourDec 20, 2022

    Checkout project cradova

    github.com/FridayCandour/cradova
    Image description

    • Alex Lohr
      Alex LohrDec 21, 2022

      As I already remarked, no framework is a silver bullet. I'm pretty sure yours is no exception. There were others before you claiming to have found the ultimate solution (the last one I remember was the guy who wrote fre – not that it's bad, but it's no silver bullet either) and there will be more after you. Still, you may have chosen other great compromises that could benefit your users.

      The first step to get this into everybody's hand is to finalize your repo, add sufficient documentation and learning materials and announce your framework everywhere, here, on Twitter, YouTube, whatever. The second step is listen to the community, but find a balance between accepting criticism and not changing features on a whim. The third step is a lot of patience.

      • Friday candour
        Friday candourJan 1, 2023

        Yeah that's true, cradova is fast and easy to use, that's it's whins, a few Compromise.

  • Benny Schuetz
    Benny SchuetzDec 20, 2022

    Very interesting article with a different focus compared to other articles of this topic.

    Thanks for sharing.

  • Mike Holloway
    Mike HollowayDec 21, 2022

    Interesting read. Thanks.

    I've been using React & React Native for some years now & I think it's a great tool. That being said, I have experienced the pain of things being re-rendered unexpectedly (usually down to using context or useEffect wrong) and have decided to try SolidJs recently.

    It has a very familiar feel, I think that mostly comes from the React side of things, but I also spent years with Knockout too. I remember disliking the latter because it got a bit obscure what was causing a state change in a complex system.

    Not sure why I'm sharing this, other than to say to someone new that they're pretty similar. Once you've learnt one, the skills are mostly transferrable to another & as long as you have several ideas, it becomes quicker each time to prototype with a new/different library/framework.

    Go for the one that looks the most fun.

    • Alex Lohr
      Alex LohrDec 21, 2022

      While react and Solid.js look superficially similar, under the hood, they are polar opposites.

      React uses reconciliation of immutable state, effects, refs and memos opt out of its reactivity and it re-runs components to fill it's vDOM. Solid uses signals, effects, memos, variable props and JSX expressions opt into its reactivity and components are rendered once without a vDOM.

      Don't be afraid of choosing a new framework. You might find new patterns that work well even in other frameworks.

  • Brian Kirkpatrick
    Brian KirkpatrickDec 21, 2022

    This is a great article, and a good summary of some stuff I didn't know (will have to check out Mithril).

    We avoid React because the build step and abstraction buy-in just isn't worth it. Instead, we use smaller modules (RequireJS-based, but migrating to ES6) with Handlebars-based templating. There's also a singular-CSS assertion. Event bindings map pretty well but the property listeners leave something to be desired.

    • Alex Lohr
      Alex LohrDec 21, 2022

      Thank you for your feedback.

      While I've included Mithril solely to show the opposite of the reactive spectrum, I'm sure it'll do its job – especially if most of your interaction is based on events anyways. I only ever played around with it, but it is actively used, so I guess it can't be too bad.

      If no-compilation remains a hard requirement and you want to try something really reactive, Solid.js has you covered, too.

      In any case, good luck!

      • Brian Kirkpatrick
        Brian KirkpatrickDec 21, 2022

        Of course! Ymmv, and every project works under different constraints that lead to different choices of technology.

  • Sandor | tutorialhell.dev
    Sandor | tutorialhell.devDec 22, 2022

    Are you saying that it's all you need to master to become efficient with lib or fw?

    What about the fundamental JavaScript concepts eg. Call Stack and Event Loop?
    Asynchronous Communication?
    OOP and functional prgramming in JS?
    Scope, closure?
    Error handling?

    • Alex Lohr
      Alex LohrDec 22, 2022

      I don't think that you will stop feeling confident until you started to understand these at least partially.

      Usually, you start with ignorance about a topic, then you gain a sufficient superficial understanding to feel confident, then after some time you learn about the concepts you didn't know that you didn't know and your confidence is replaced by more understanding.

      • Sandor | tutorialhell.dev
        Sandor | tutorialhell.devDec 22, 2022

        I can only say that this basic knowledge is a must for working with frameworks. I should add design patterns too. Sadly, none of this was mentioned in your article.

        One should learn the underlying technology before using tools built with this technology. My takaway after 12 years in FE.

        • Alex Lohr
          Alex LohrDec 22, 2022

          25 years of FE taught me that most people are using only about ½ of the underlying technology most of the time anyways – but depending on your use cases, these might be different parts.

          Also, I wanted to keep the part intentionally short and encouraging, that's why I remarked on overcoming your initial confidence instead of mentioning a discouragingly long list explicit skills.

          Lastly, a lot of people use their favorite patterns like a hammer, even if their task is to fix some screws. Yes, learning patterns can help, but every framework usually already comes with its own set of idiomatic patterns that are more important than learning about a factory pattern that you're never going to use with that framework.

          • Sandor | tutorialhell.dev
            Sandor | tutorialhell.devDec 22, 2022

            That makes me even more sad. You're set for disaster if you don't know JavaScript being a FE dev.

            Not using is not the same as not knowing about what is actually happening under the hood. We don't use frameworks because we need shortcuts.

            • Alex Lohr
              Alex LohrDec 22, 2022

              Do you know 100% of JavaScript? You can answer every question of ydkjs-exercises.com/ correct without thinking twice? I can't do that, and I'm longer in that game than you. I'm still confident that I can solve every front-end problem even without a framework.

              To start with a framework, you don't need 100%. Getting over your initial confidence means you are usually somewhere around 50-60% of the language and its concepts and the rest that is important to work with the framework, you can pick up on the go.

              We don't need gatekeepers for frameworks. Our community should be inclusive, not exklusive. In due time, every front-end developer should master their tools, but I don't expect anybody from waiting to use a framework before they mastered JS.

              And weren't you basically saying the same?

              • Sandor | tutorialhell.dev
                Sandor | tutorialhell.devDec 22, 2022

                You're comparing apples and oranges.

                Firstly, I am not talking about your knowledge and experience. I am talking about a mere fact that this article is not mentioning important JS fundamentals and encourages devs to jump on FW unprepared. It's a huge red flag for any developer.

                *Facebook hires devs without React knowledge but with JS knowledge because they believe if you know JS, you will figure out React. But not the other way around. *

                I only know that I know very little, but I do know JS fundamentals and this knowledge has helped me countless times with being efficient with any JS based tool.

                There is no way to be proficient with a framework if you don't know the fundamentals of a language, be it JS or any other language.

                • Alex Lohr
                  Alex LohrDec 22, 2022

                  You're still not getting the point. If you overcome your initial confidence, by then you will have learned, yet not mastered JS. That's how learning works: 1. You get an initial understanding and feel confident, 2. You actually learn and lose previous confidence and 3. You master it and become confident again.

                  By including a long checklist, I would have increased the length of this already long article and would have discouraged beginners. Do you really think that's worth it? You call yourself a mentor, don't you?

                  • Sandor | tutorialhell.dev
                    Sandor | tutorialhell.devDec 22, 2022

                    No need to include long lists - only include what really matters. Fundamentals do matter.

                    A beginner/junior with solid knowledge of fundamentals but without a framework knowledge is on his/her path to success.

                    Beginners are discouraged when they grab a framework and struggle with it all the time because they think they know it but they lack understanding of language fundamentals which are a prerequisite for using a framework.

                    Let me give you an example:
                    Hooks embrace JavaScript closures and avoid introducing React-specific APIs where JavaScript already provides a solution.
                    Source reactjs.org/docs/hooks-effect.html

                    It's a clear example where knowing JS closures helps with understanding how hooks work in React.

                    Notice "React-specific APIs"... All frameworks and libs have a lot of specific stuff that is not directly transferable from frameworks to framework. So imagine a beginner using hooks in React and then switching to another framework and using a similar solution that is abstracted away in a different way. Same stuff but named and approached differently. But a beginner will have no clue because of lack of understanding of JavaScript closures...

                    You get the idea.

                    Yes, I am a mentor. And I speak from experience.

                    And if you tell you've mentored hundreds of juniors successfully, I will not doubt it even for a second because I am 100% sure that you mentored them explaining what really matters, even if subconsciously.

                    • Alex Lohr
                      Alex LohrDec 22, 2022

                      The docs for react have been rewritten from scratch exactly for that reason: that they implied too much prior knowledge to be inclusive for beginners.

                      I'm not saying "fundamentals don't matter", I'm asserting that you should have learned most of them by the point you overcame your initial confidence.

                      The junior devs I have mentored learned about closures as a part of the way functions work before they lost their confidence in their initial knowledge. How do you teach functions (one of the basic data types I explicitly mentioned in the article) without explaining scope and closures?

  • b1bxonty
    b1bxontyDec 22, 2022

    very helpful

  • artydev
    artydevDec 23, 2022

    Very useful thank you

  • Andy Maleh
    Andy MalehDec 23, 2022

    In most business apps, none of the JS frameworks even matter. The interactions are simple and fast enough that all discussions of JS frameworks are moot. It would be much better to learn software engineering skills instead, to know when to use the right tool for the job for a specific project instead of over-engineering with cookie cutter techniques like JS frameworks (usually lower level developers who don’t question anything fall blindly for them).

    Also, what you describe as “reactivity” is actually known since way before JS frameworks were created as the Observer Design Pattern (aka Listener), which is a fundamental part of the MVC (Model-View-Component) Architectural Pattern. JS frameworks didn’t invent these concepts. They’ve been part of the web (e.g. onclick) since the beginning and they’ve been around since the first GUI showed up in Smalltalk-MVC in the 80s. All what these JS frameworks (e.g. React) do is mimic MVC in JavaScript, that’s all. Components is an ancient concept too (aka Software Modules) that was always used to build desktop GUI apps.

    Anyways, if you have to think in a low level way away from reality in terms of states, hooks, and effects, then your code is so over engineered and distanced from reality that you already lost half the battle in meeting business goals in a web app in a short amount of time with a lower budget.

    And, if you have to worry about pointless restrictions like immutable values or static typing in TypeScript, then you’re also encumbering development by 50% at least. Most of the benefits of such techniques compared to not using, never really materialize, and only proper software engineers with good experience could easily navigate around them by focusing on what’s practical, not theoretical, thus developing much more productively. Many people who fall for such bad techniques do so because they’ve read about them in a blog article or heard of them in a lecture, but blindly accepted them without questioning anything or thinking for themselves. And, they didn’t try to compare using them to not using them and seeing if the latter resulted in better productivity. Again, proper software engineers who avoid immutability and static typing can deliver faster without any real problems assuming they design their JavaScript with proper object oriented design and design patterns.

    Also, by dropping even lower to the level of math by using reducers when we’re building standard business apps that have little math except in the backend, you also end up with code that is very distanced from reality and is thus much more expensive to maintain. Math techniques must only be used for math domain problems. Otherwise, it is better to use patterns like MVC and object oriented abstractions that act like simple encapsulated real concepts without being forced to work with cumbersome low level things like states, hooks, and effects, which make code 4 times more complicated at least than necessary.

    React code is garbage , but most of its brainwashed users are like frogs getting boiled gradually without realizing they are getting burned by all the extra unnecessary expensive code they’re writing (probably because they look at others around them who happen to be boiling frogs too, so they think everything is normal instead of thinking for themselves and realizing the truth). It’s sadly a BIFI culture, meaning By Idiots For Idiots. None of its users have the intelligence to question things outside the box, so they just worship the overlords of React at Facebook (a very unethical company) while getting owned by their own idiocy in very large numbers. In fact, some of them literally think that a more popular technology is a better technology and that if a technology comes from a giant like Facebook, then it has to be good (the Facebook web app obviously sucks though and everybody knows it). That’s how they choose technologies, not by thinking for themselves. It’s very sad. That’s because in fact, more often than not, more popular technologies are popular because the majority of mediocre developers could use them as opposed to the minority of excellent software engineers. So, mediocre work is produced by them that hurts deadlines, expenses, and quality for customers compared to excellent work produced without them by the minority of excellent software engineers out there.

    But, that raises the value of true software engineers who could write 10% of the code or less and get the job done much more cheaply, on time, and with higher quality, without using any JS frameworks.

    • Alex Lohr
      Alex LohrDec 23, 2022

      Thank you for your criticism. Let me address your points one by one.

      In most business apps, none of the JS frameworks even matter.

      Last time I checked, Jira, BitBucket, Slack, all business apps, are using JS frameworks to make their front-end development scalable. And since an increasing number of business apps are going the SaaS route into the cloud, they are going to matter even more.

      The interactions are simple and fast enough that all discussions of JS frameworks are moot.

      Most of the interactions may look like simple events, but accessible solutions that work both on mobile and desktop are sometimes more of a challenge than a back-end engineer like yourself could even imagine.

      You can do all of this with vanilla JS (I've done this before and even mentioned it as an option at the end), but it's much harder to do so in a reusable, composable way outside of a framework.

      It would be much better to learn software engineering skills instead, to know when to use the right tool for the job for a specific project instead of over-engineering with cookie cutter techniques like JS frameworks (usually lower level developers who don’t question anything fall blindly for them).

      While some people needlessly jumped on the PWA-train where a MPA would have done a better job, I wouldn't say those were in the majority. Most of us have a background in full-stack. And there are certainly use cases that warrant the development of a web app with a JS framework. So I'd say this is a bit of a prejudice from you.

      And, if you have to worry about pointless restrictions like immutable values or static typing in TypeScript, then you’re also encumbering development by 50% at least.

      With JS frameworks, you almost always have a choice. Only Angular forces you to use TypeScript, everywhere else, it's an option. Immutability is only required in reconciler-based frameworks, because they need the reference comparison for their state-tree walkers.

      In larger projects, the benefits of TS outweighs the overhead by far. So I have to assume you never saw a large-scale frontend project from the inside.

      Also, what you describe as “reactivity” is actually known way before JS was invented as the Observer Design Pattern...

      This is as true as it would be confusing to the beginners this post was aimed at to gain a basic understanding of the common principles of front-end frameworks.

      Anyways, if you have to think in a low level way away from reality in terms of states, hooks, and effects, then your code is so over engineered and distanced from reality that you already lost half the battle in meeting business goals in a web app in a short amount of time with a lower budget.

      Point taken on the over engineering in some cases (I'm looking at RxJS specifically), but isn't it strange that people still save time and effort by using frameworks and their ecosystems? Maybe there are other factors playing a major role in this case. Maybe your point of view is to one-dimensional.

      Again, proper software engineers who avoid immutability and static typing can deliver faster

      You should definitely have a look at Solid.js. It avoids immutability in favor of fine-grained reactivity and static typing is supported yet optional. It's right there in my article. You might have missed it.

      Though static types seems to become all the rage in proper systems development too, with Rust having an elegant and powerful type system.

      Also, by dropping even lower to the level of math by using reducers when we’re building standard business apps that have little math except in the backend, you also end up with code that is very distanced from reality and is thus much more expensive to maintain.

      You don't even need to use reducers in react, they are an option. I also see them as unnecessarily boilerplate, so no argument from me here.

      ...object oriented abstractions that act like simple encapsulated real concepts without being forced to work with cumbersome low level things like states, hooks, and effects, which make code 4 times more complicated at least than necessary.

      Strange. If I look at efficient functional solutions, it becomes apparent that OOP abstractions are mostly unnecessary overhead, which easily make code 4 times more complicated at least than necessary. Perspective can be a powerful thing.

      React code is garbage...

      I've had to read though the code of react. There's certainly a lot of unused code in there, but it is not garbage, but more the reason that react hasn't been completely abysmal in terms of backwards compatibility. Yes, the react team has taken some questionable design decisions, but there are always reasons behind them – like having also to work with native and some internal legacy projects.

      Granted, react is no work of art, but it's also not garbage It's a work of work. And yes, Meta is bad. So what? You can still switch to preact at any point.

      But, that raises the value of true software engineers who could write 10% of the code or less and get the job done much more cheaply, on time, and with higher quality, without using any JS frameworks.

      Apart from the no true Scotsman fallacy here, that would work if you could hire those by the dozens. You can hire react devs much cheaper and scale up and down the whole development process using react/Vue/etc. developers instead and they're much cheaper and easier to work with, because few of them are opinionated as heck and too full of themselves than would allow to team them up at all.

      I've worked in front-end with and without frameworks for over 25 years. At the end of the day, it's a business decision. Yes, most businesses will initially fall for the lie of synergy effects of reusable code, but will stay for the truth of scalable development.

      As I remarked at the end, frameworks are no silver bullets – but they do have their merits. And if you understand the concepts behind them, it may help you to make better choices – even the one to forgo a framework and go vanilla instead. That's what this article is about, a point that seemed to have gone completely over your head.

      That being said, it would be interesting to read how you as a "real" developer would think front-end development should work.

    • Filipe Costa
      Filipe CostaDec 28, 2022

      True software engineers are like those guys that build an entire house with just an hammer in a couple of days.
      They are strong, fast, don't require fancy tools (apart from VIM), they never do mistakes and they are never wrong. Actuality they don't even need tests because they really don't create any type of bugs.
      And if a true software engineer decides he can do a much better React in 10 days, with a single hand... 🦄

      I'm doing frontend code for 20 years and I can tell you that you don't really know what you're talking about.
      The amount of code you need to implement a complex SPA with or without a framework has no possible comparison... Not talking about maintenance and performance.

      Regarding Typescript, I've done very big projects with and without it, and it's really hard to understand who thinks Typescript doesn't help in large projects.

      I understand some of your frustrations, namely with React, but it looks like you're rejecting any type of innovation just because you're afraid of something and that's generally not good for your professional development.

      Fortunately there are good frameworks out there, not perfect... yet... But very far away from the time we needed to update the DOM state manually, or just recreate all the elements on each update.

  • Thomas Lepérou
    Thomas LepérouDec 24, 2022

    get fun and explore amazing possibilities --> Qwik

    • Alex Lohr
      Alex LohrDec 24, 2022

      Or Astro. Or something else. Or go vanilla. The point here is not to promote a single framework, but to help understand them good enough to help distinguish marketing bullshit from verified claims.

  • Merc Opolo
    Merc OpoloDec 24, 2022

    Good post

  • Alex Lohr
    Alex LohrDec 24, 2022

    You probably mean Mitosis? An interesting project, but I haven't found the time to take a closer look. Maybe for the next article.

  • fruntend
    fruntendDec 26, 2022

    Сongratulations 🥳! Your article hit the top posts for the week - dev.to/fruntend/top-10-posts-for-f...
    Keep it up 👍

  • magicwalter15
    magicwalter15Jan 4, 2023

    This is a really nice article... I enjoyed reading it

  • Mustafa_A
    Mustafa_AMar 29, 2023

    … instead of demonstrating the readers the concepts behind them to allow for an informed decision

    Great root-cause analysis followed by a great elaboration.
    With that you lived up to the implicit promise of your introduction.
    Thanks for sharing. I enjoyed it very much.

  • LMugget
    LMuggetJun 7, 2023

    Great article, very enlightening.

  • Eckehard
    EckehardJul 23, 2023

    Hy Alex,

    before mentioning any framework, we should ask for the task you need to solve. I suppose, it depends much on the kind and size of your application, if a framework plays well or not. For a large scale app with millions of users, the perfect tooling might be different than for a private homepage.

    So, possibly we should first ask for the task before recommending something.

    • Alex Lohr
      Alex LohrJul 23, 2023

      It gets even more interesting if you go another step back and ask which properties of the large-scale app or the private homepage are significant factors for the choice?

      Then you find that the number of concurrent views, the complexity of interactions, the amount of changes at the same time and the performance of the clients you expect become very interesting.

      For example, a shopping homepage will be much faster if it shuns MVC frameworks and instead start out as MPA with only the minimal required interactions. A conference app on the other hand wouldn't work as anything but an SPA.

      • Eckehard
        EckehardJul 23, 2023

        But is there any real measure? How much performance do you really need?

        Most people will not have so many friends that the number of concurrent views really matters. And if their hompage is boring slow, this will possibly not a result of the wrong framework but of the wrong provider.

        Your initial question was: Many beginners ask "which framework should I learn?"

        My first questions would be:

        a) What do you want to do
        b) How much time do you have to learn

        I assume, there is also a big difference in the performance, how long it takes to get a "beginner" up and running. Maybe he or she can do the job in Svelte after 2 weeks, but doing the same in React will take 2 month, which is the better choice?

        • Alex Lohr
          Alex LohrJul 23, 2023

          a) might not be a coherent answer like "I want to build my own homepage". I would expect it to be much more complex, for example "I want to build my own homepage that serves as example for my skills if I apply for a job that requires me to build much more complex, performant, scalable apps, since those pay better."

          Also, if you need much longer to learn react than svelte, there's something wrong with your learning material. The way those frameworks handle their tasks are extremely different, but the tasks (receiving interactions, managing state, rendering view) are very much the same.

Add comment