<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Eduard Tar</title>
    <description>The latest articles on DEV Community by Eduard Tar (@eduardtar).</description>
    <link>https://dev.to/eduardtar</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1078818%2F1f19533c-2b36-4717-b706-d238d8f0beda.jpg</url>
      <title>DEV Community: Eduard Tar</title>
      <link>https://dev.to/eduardtar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/eduardtar"/>
    <language>en</language>
    <item>
      <title>Introducing DI Unchained - A new way to use Angular DI</title>
      <dc:creator>Eduard Tar</dc:creator>
      <pubDate>Tue, 20 Jun 2023 14:56:21 +0000</pubDate>
      <link>https://dev.to/adroitgroup/introducing-di-unchained-a-new-way-to-use-angular-di-1keh</link>
      <guid>https://dev.to/adroitgroup/introducing-di-unchained-a-new-way-to-use-angular-di-1keh</guid>
      <description>&lt;p&gt;Did it ever occur to you how we can only use Angular's black magic DI tool in a certain way? We have no choice but to abide by the all-mighty framework's iron-fisted rule. That means using Di only on the framework's own terms. And terms we have. DI can only be called upon where the framework allows it. And that's only in the constructor of a class that's decorated with one of the chosen five.&lt;/p&gt;

&lt;p&gt;What now?&lt;/p&gt;

&lt;p&gt;Let me explain. There are five class decorators that are favoured by the framework above everything else. I'm talking about the @NgModule(), @Component(), @Directive(), @Pipe() and of course @Injectable() decorators. And that's it. No other way to use it. No other way to inject it. These five are like the deputies of Angular itself to watch over and ensure the order of our applications. We're left with no choice but to obey to their rules if we wish to receive the framework's blessing of DI powers.&lt;/p&gt;

&lt;p&gt;But there's hope for change&lt;/p&gt;

&lt;p&gt;I encourage you to read on. Learn about the truth of things. Understand the status quo and then decide for yourself if you want to continue to live in the dark. Or if you want to join us and stand up against this tyranny. Break the Wheel and pave the way for future generations to come. For a better tomorrow. For a better Angular.&lt;/p&gt;

&lt;p&gt;Intrigued are we? Good. Let's begin.&lt;/p&gt;

&lt;p&gt;So you have already learnt about the history which I assume you knew anyway. I also assume you've learnt about the recent swift of the aforementioned status-quo. I'm talking about Angular recently heeding the call of it's most devoted supporters and giving in on relaxing the rules one must follow to receive the gift of DI.&lt;/p&gt;

&lt;p&gt;No, you haven't?&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The new status-quo&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;With the introduction of a new form of prayer called inject(). We've been at least let loose from the grasp of constructors. An even lower authority than the chosen five. Yet a lot more abundant and unwilling to let loose of their power. inject allows us to bypass constructors entirely and inject our dependencies directly into the body of our classes. But that's not all. We can also use it to inject dependencies into functions. And that's where the real magic happens.&lt;/p&gt;

&lt;p&gt;But don't let this fool you. Nothing really changed. The Wheel still stands and is still in motion. Angular merely let the chosen five rearrange the pieces to create the illusion of change, of freedom while their rules still apply. There's still no freedom. There's still no choice. DI is still held hostage by the chosen five. And that's why we need to break the Wheel.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The truth&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The truth is that we can use DI anywhere we want. We can use it in any function we want. We can use it in any class we want. We can use it in any file we want.&lt;/p&gt;

&lt;p&gt;I sincerely believe that Angular's attempt to quench our thirst for some hope of freedom without really changing anything has backfired for it. Despite the intention of giving us something that's really nothing has a flaw. Which makes it really something. But I'm not sure that you could handle the truth if you'd seen it. We're talking about things merely less mysterious and convoluted than the powers of Angular's DI. I'm not sure you are ready for what I'm about to show you, but here we go.&lt;/p&gt;

&lt;p&gt;But before we tackle this "loophole" let's get the "basics" out of the way first. So you may understand how to utilize this opportunity.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The small science of JavaScript&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;One most important things to understand is that JavaScript is a language that's built on top of the concept of prototypes. This is common knowledge nowadays yet this is the stepping stone for us to reach a deeper understanding and learn of the small science of JS, metaprogramming. That's no heresy. That's science.&lt;/p&gt;

&lt;p&gt;Understanding the fundamental truth that prototypes lead us to allows us to peer into the very essence of JS itself. An even greater power than Angular and dare I say React as well.&lt;br&gt;
So what's the essence?&lt;/p&gt;

&lt;p&gt;In JS everything is an object. Even functions are. They're in fact 'callable' objects. All objects' have their properties. Even methods are properties. All properties are bound to their objects with other special objects called property descriptors. These determine what kind of property we have and what we can or can't do with it. Proxies and Reflection are real as opposed to what they taught you in school. And we're going to use them all to finally break the Wheel.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;What's the loophole?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;You see there's no single thing that magically solves everything. Although if we had to point to one single thing that would be the inject() function mentioned earlier. Even though we now have the means to break the Wheel. It's still going to be a hard and complex task to undertake, with many steps.&lt;/p&gt;

&lt;p&gt;In order to free ourselves we must first free the Injector itself from Angular. Yep, we're going to hijack Angular's very own blessing from itself for our purposes.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Let's lose the Injector&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;When the inject() function has been introduced by Angular, and a new Injector type was introduced as well. These are the EnvironmentInjectors which can roughly be described as the new module injectors. Their introduction was necessary due to the standalone APIs.&lt;/p&gt;

&lt;p&gt;So now when you create an application with version 14 or higher. Your root module or component will have an Environment Injector. Our first business of order is to help it get out of Angular's grasp.&lt;/p&gt;

&lt;p&gt;There's a fairly old way to do this. Which would have worked with the predecessor of EnvironmentInjectors as well. Basically, we ask Angular to give us its root injector. In our case, we now ask for the Environment Injector. It's a big favour to ask but Angular usually suspects nothing and fulfils our request. However, being able to ask for the Injector implies that we're in Angular's domain. That won't do, will it? We have to trick Angular with a little trick that consists of a ClassDecorator and a Proxy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function DI(): ClassDecorator {
  return (target: any) =&amp;gt; {
    return new Proxy(target, {
      construct(target, argArray, newTarget) {
        const instance = Reflect.construct(target, argArray, newTarget);

        window.DI_UNCHAINED_INJECTOR_SYMBOL = inject(EnvironmentInjector);

        return instance;
      },
    });
  };
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's see what we have here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A class decorator factory function will be applied either to our root module or root component class.&lt;/li&gt;
&lt;li&gt;The decorator function returned by the factory returns a Proxy that wraps the decorated class and traps it's constructor call. This gives us access to its construction logic that runs when the new operator is used without having to actually modify the class itself.&lt;/li&gt;
&lt;li&gt;We ask Angular for the EnvironmentInjector with the help of the aforementioned inject() function.&lt;/li&gt;
&lt;li&gt;We store the result in a global symbol that we can access from anywhere in our application.&lt;/li&gt;
&lt;li&gt;We use the Reflect API to mimic the original behaviour of the constructor function. So that no change would be visible from the outside.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With this setup, we've already managed to break the EnvironmentInjector free from Angular. But how are we going to use it?&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Getting to work&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We're going to use a similar technique to use the EnvironmentInjector in a comfortable way. First, let me introduce to you a less-known capability of our dear friend the EnvironmentInjector. There's a method called runInContext() that allows the callback function passed to it to run inside the context of that injector. This means that we can use the injector to resolve dependencies for us. This is very similar to how NgZone's runGuarded function work. So let's create a function that uses the hijacked EnvironmentInjector from the global scope and runs our code in the context of that Injector.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export function runInContext&amp;lt;T extends () =&amp;gt; any&amp;gt;(fn: T): ReturnType&amp;lt;T&amp;gt; {
  const envInjector = window.DI_UNCHAINED_INJECTOR_SYMBOL;

  return envInjector.runInContext(fn);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we can easily call upon the Di through the hijacked Injector. Let's put together the remaining pieces. So we can actually use it.&lt;/p&gt;

&lt;p&gt;We're going to create yet another TypeScript decorator. This time however we are going to wrap a class member with it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function Unchained() {
  return (
    target: any,
    propKey?: PropertyKey,
    descriptor?: TypedPropertyDescriptor&amp;lt;any&amp;gt;
  ): any =&amp;gt; {
    return bindDescriptor(target, propKey!, descriptor!);
  };
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the bindDescriptor function is going to do the actual work.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export function bindDescriptor(
  target: object,
  member: PropertyKey,
  descriptor: TypedPropertyDescriptor&amp;lt;unknown&amp;gt; &amp;amp; PropertyDescriptor
) {
  const { get, set, value } = descriptor;
  let changed = 0;

  if (typeof get === "function") {
    descriptor["get"] = () =&amp;gt; runInContext(() =&amp;gt; get());
    changed++;
  }

  if (typeof set === "function") {
    descriptor["set"] = (arg) =&amp;gt; runInContext(() =&amp;gt; set(arg));
    changed++;
  }

  if (typeof value === "function") {
    descriptor["value"] = (...args: unknown[]) =&amp;gt;
      runInContext(() =&amp;gt; value(args));
    changed++;
  }

  if (changed) {
    Object.defineProperty(target, member, descriptor);
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again let's see what we do here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We create a decorator factory function that will be applied to a class member.&lt;/li&gt;
&lt;li&gt;The decorator returns the result of the bindDescriptor function. This means that the result of the function will replace the original class member definition.&lt;/li&gt;
&lt;li&gt;We unpack the descriptor object and check if it has a getter, setter or value.&lt;/li&gt;
&lt;li&gt;Getters and setters are fairly easy to handle. We just wrap them in a function that calls the runInContext function.&lt;/li&gt;
&lt;li&gt;If we have a value that means we either have a method which is located on the prototype chain or a value which can either be a primitive or an object. We are only interested in the first case though. So we check if the value is a function and if it is we wrap it in a function that calls the runInContext function.&lt;/li&gt;
&lt;li&gt;Then lastly we check if we actually changed anything. If we did we replace the original descriptor with the new one. This is where we actually overwrite the existing behaviour.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can now apply this decorator to any class property or method anywhere and it will be executed in the context of the hijacked EnvironmentInjector. meaning we'll have access to the powers of DI.&lt;/p&gt;

&lt;p&gt;But wouldn't it be easier if we didn't have to apply this decorator to each and every class member? Well, yes it would. So let's create a class decorator that will do that for us. In fact, let's just change our existing decorator to do that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function Unchained() {
  return (
    target: any,
    propKey?: PropertyKey,
    descriptor?: TypedPropertyDescriptor&amp;lt;any&amp;gt;
  ): any =&amp;gt; {
    const mode: "class" | "method" =
      !!propKey &amp;amp;&amp;amp; typeof descriptor === "object" ? "method" : "class";

    return mode === "method"
      ? bindDescriptor(target, propKey!, descriptor!)
      : wrapClass(target);
  };
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The changes we've made:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We check where the decorator is being applied. This is the 'mode' variable.&lt;/li&gt;
&lt;li&gt;Class and class member decorators receive different parameters from the __decorate() helper function from tslib. So using this knowledge we can check for the presence and shape of the extra parameters that only class member decorators receive.&lt;/li&gt;
&lt;li&gt;Based on the inferred decoration 'mode' we either call the bindDescriptor function as we did before, for class members, or the wrapClass function for the whole class.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's see how wraClass() looks like.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export function wrapClass(target: Function) {
  const proto = target.prototype;
  if (!target || !proto) return;

  bindCLass(proto);
  bindCLass(target);

  return new Proxy(target, {
    construct: (target, argArray, newTarget) =&amp;gt; {
      return runInContext(() =&amp;gt; Reflect.construct(target, argArray, newTarget));
    },
  });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll get to what bindClass() does in a minute. But first, let's see what we do here:&lt;/p&gt;

&lt;p&gt;We use the Proxy API again to wrap the decorated class's constructor just as we did before. This is because all the instance properties of a class that are defined and initialized in the class body are actually moved and executed inside its constructor. For instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class MyClass {
  prop = "value";
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Becomes this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class MyClass {
  constructor() {
    this.prop = "value";
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I know, I know. Shocking right? 😱 But the thing is you already knew about this. Or at the least, you've suspected that something like this would be going on in the background when you started using TypeScript.&lt;/p&gt;

&lt;p&gt;Now let's see what bindClass() does.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export function bindCLass(protoOrCtor: object) {
  const protoMembers = Object.entries(
    Object.getOwnPropertyDescriptors(protoOrCtor)
  ).filter(
    ([member, descriptor]) =&amp;gt;
      (typeof descriptor.value === "function" &amp;amp;&amp;amp; member !== "constructor") ||
      descriptor.get ||
      descriptor.set
  );

  protoMembers.forEach(([member, descriptor]) =&amp;gt;
    bindDescriptor(protoOrCtor, member, descriptor)
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;We get all the class members of the decorated class constructor or prototype object. Remember from earlier that we've called bindClass() twice. Once for the constructor and once for the prototype. This way we'll be able to bind both static and instance methods.&lt;/li&gt;
&lt;li&gt;Filter does members to get the getters, setters and methods. We don't want to bind the constructor because it's already been bound. And we don1T want to bind non-function values that reside on the prototype chain.&lt;/li&gt;
&lt;li&gt;For each descriptor object in our list, we call the bindDescriptor() function.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;*&lt;em&gt;## Reap what we sow&lt;br&gt;
*&lt;/em&gt;&lt;br&gt;
With all this work done we can finally reap the benefits of our hard work. Let's see how we can use this decorator in our application.&lt;/p&gt;

&lt;p&gt;Let's define an ordinary service that we'll use in our application. This service does nothing but will serve as a custom service that we'll inject into our components.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Injectable({
  providedIn: 'root',
})
export class TestService {
  public name = 'TestService';
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not to the fun part! We define our @Unchained() class as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Unchained()
export class TestClass {
  router: Router;

  static routerFn = () =&amp;gt; inject(Router);

  static getRouter() {
    return inject(Router);
  }

  routerFn = () =&amp;gt; inject(Router);

  constructor() {
    this.router = inject(Router);
  }

  public getTitleService() {
    return inject(Title);
  }

  public get neta() {
    return inject(Meta);
  }

  public static get appRef() {
    return inject(ApplicationRef);
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see our test class doesn't really do much, but it injects a lot of services from Angular while only using the @Unchained() decorator.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Unchained()
export class TestChildClass extends TestClass {
  featureName = inject(TestService).name;
}

class OtherTestClass {
  @Unchained()
  getTitleService() {
    return inject(Title);
  }

  @Unchained()get Meta() {
    return inject(Meta);
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We define two addition classes just for good measures.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Component({
  selector: 'app-test',
  template: '',
})
export class TestComponent implements OnInit {
  title = 'DI-unchained';

  myInstance!: TestClass;

  otherInstance!: OtherTestClass;

  childInstance!: TestChildClass;

  ngOnInit(): void {
    this.myInstance = new TestClass();
    this.otherInstance = new OtherTestClass();
    this.childInstance = new TestChildClass();
  }
}

@NgModule({
  declarations: [TestComponent],
})
@DIContextProvider()
export class TestModule {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And finally, we define a component that will use our test classes. And a module to register our component. We also use the DIContextProvider() decorator to register our component's injector as a DI context.&lt;/p&gt;

&lt;p&gt;You may be wondering how is this beneficial to us if we instantiated our classes inside a component. But that's just for the sake of simplicity. In reality, you'd be defining and using these classes left and right without a care in the world about how code execution gets to them and how they'd find their Injectors. However ultimately most if not all code execution in our Angular applications would begin from an Angular component or module.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;We are finally free. Yaay! Now what?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;I'm not really on for proverbs but I think the one that goes like "With great power comes great responsibilities" fits here perfectly. indeed, we've come along this path for quite some time. We are finally free from Angular Di's shackles. But how are we going to use it? What is the benefit of using this tool anyway?&lt;/p&gt;

&lt;p&gt;That's a good question. In fact, while I was busy researching all these tricks and planning our way out I was so caught up in it, that I almost completely forgot about this question. It's like when prisoners plan their escape. They might not even know what they want to do with their freedom. They just want to have it.&lt;/p&gt;

&lt;p&gt;One possible use case that comes into my mind though is of implementing an Active record pattern in Angular. Now I know that Active record is usually used in ORM systems to give a means for us developers to interact with our database and its entities more easily. But I think it can be used in Angular as well. If you think about it, the API that we're talking about is our applications database. Don't let the knowledge of the bigger picture fool you. You know that in the whole application architecture the REST API is not the actual source of data, it's not really a database. But for the GUI layer, our application is in this case. It can be thought of as a database. And we can use the Active record pattern to interact with it.&lt;/p&gt;

&lt;p&gt;Doing so changes the structure of your API code so that instead of injecting HttpService into your feature services do not turn into creating model classes with the @Unchained() decorator. And then using HTTP and other required services there. We can even go a step further and define a module base class that assembles everything for us under the hood. This isn't only about code aesthetics. Having a class that you can use anywhere without injection is an easier and more comfortable solution to some of the problems that Angular's Di system may present in real-world, complex applications. If you've heard about the smart and dumb component pattern then you know that dumb components aren't supposed to inject things. They only operate through @Input()s and @Output()s. However sometimes there are multiple levels of dumb components required. And the line between smart and dumb becomes more and more blurry as you add more and more child components into a component hierarchy. It's easy to distinguish two components into these two categories when you have a list and a list-item component. But what happens when you have a routed, smart component which has 3-5 or even more children? Are you going to prop drill down 3-5 levels of components just to maintain the proper form for dumb components? Are you going to create a service for the smart component to handle its model that you can inject into other components further down the line? That would break the single source of truth principle that all state management libraries adhere to. Or you could create an instance of your model class further down in some of the children that you deem to be the last "smart-ish" component in the component sub-three.&lt;/p&gt;

&lt;p&gt;All these half-incoherent rumblings aside. I do think there's value in this tool and the approach it enables. However, I'm still not entirely sure how and when to use it. I'm sure we'd figure out the best use cases together though. ;)&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Wrapping up&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;What's that? Now you're interested and I'm about to shut down the article without giving you a GitHub or npm link for the "repository"? That wouldn't be nice of me, now would it?&lt;/p&gt;

&lt;p&gt;That's why I'm telling you that me and my colleagues over at @Adroit Group have been working on a utility library for Angular full of useful stuff. Including, of course, the @unchained() decorator I've introduced to you today. You can find it at NPM or Github. Go take a look or even download and use it. 📚👀&lt;/p&gt;

&lt;p&gt;I'd like to thank you for your time and attention in reading this article.&lt;/p&gt;

&lt;p&gt;I was your tour guide Jonatán Ferenczfi, Frontend tech lead at @Adroit Group, Angular bro and high-functioning coffee addict. ☕&lt;/p&gt;

&lt;p&gt;Until next time 👋&lt;/p&gt;

</description>
      <category>angular</category>
      <category>discuss</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>The Power of WebSocket: Revolutionizing Real-time Communication on the Web</title>
      <dc:creator>Eduard Tar</dc:creator>
      <pubDate>Thu, 01 Jun 2023 10:36:45 +0000</pubDate>
      <link>https://dev.to/adroitgroup/the-power-of-websocket-revolutionizing-real-time-communication-on-the-web-40jk</link>
      <guid>https://dev.to/adroitgroup/the-power-of-websocket-revolutionizing-real-time-communication-on-the-web-40jk</guid>
      <description>&lt;p&gt;The internet has revolutionized the way we communicate, and real-time communication is an essential component of modern web applications.&lt;br&gt;
However, traditional HTTP connections were not designed for this purpose and have limitations that prevent them from delivering a seamless user experience in real-time communication scenarios.&lt;/p&gt;

&lt;p&gt;This is where WebSocket comes in. WebSocket is an internet technology that allows for bidirectional, full-duplex communication channels between a web browser-based application and a server over a single TCP connection.&lt;br&gt;
It has changed the way we think about web communication, enabling developers to build complex and powerful real-time applications that were not possible before.&lt;/p&gt;

&lt;p&gt;In this article, we’ll deeply dive into WebSocket, explore its features and benefits, and see how it’s revolutionizing real-time communication on the web.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://adroitgroup.io/blog/the-power-of-websocket-revolutionizing-real-time-communication-on-theweb" rel="noopener noreferrer"&gt;adroitgroup.io&lt;/a&gt; and written by &lt;a href="https://medium.com/@martin.sulc" rel="noopener noreferrer"&gt;Martin Sulc&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flurz2zhwx6zgkjk6b471.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flurz2zhwx6zgkjk6b471.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example WebSocket Implementation in JavaScript for Front-end and Back-end&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Front-end:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const ws = new WebSocket('ws://localhost:4000');

ws.addEventListener('example', function (event) {
 console.log('Example array from server:', event.data);
});

ws.addEventListener('close', function (event) {
 console.log(event);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Back-end (Node.js):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const WebSocket = require('ws');

const wss = new WebSocket.Server({ port: 4000 });

const numbers = [5, 12, 6, 8, 15];

wss.on('connection', function connection(ws) {
    ws.on('example', () =&amp;gt; {
        ws.send(`Here is an example array of 5 numbers: ${numbers}.`);
    });

    ws.on('close', function close() {
        console.log('Connection close event.');
    });
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above code examples demonstrate the usage of **WebSockets **on both the front-end and back-end.&lt;/p&gt;

&lt;p&gt;In the back-end code, a &lt;strong&gt;WebSocket **server is created using the ws module and bound to **port 4000&lt;/strong&gt;.&lt;br&gt;
When a new client connects to the server, the connection event is triggered and a message listener is registered to listen for the example event.&lt;/p&gt;

&lt;p&gt;When the server receives an example event from a client, it sends the array to the client using the send method. The close event listener is also registered to handle the **WebSocket **connection closing.&lt;/p&gt;

&lt;p&gt;In the front-end code, a new &lt;strong&gt;WebSocket **object is created and connected to the server at **ws://localhost:4000&lt;/strong&gt;. The example event listener is registered to listen for the example event from the server. When the client receives an example event, it logs the received data to the console.&lt;/p&gt;

&lt;p&gt;The close event listener is also registered to handle the **WebSocket **connection closing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Pros and Cons of WebSocket: A Comprehensive Overview
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;➕ Advantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Real-time data transfer: WebSockets enable real-time data transfer between the server and client without the need for refreshing the page or making repeated requests. This makes it ideal for applications such as instant messaging, online gaming, and stock trading.&lt;/li&gt;
&lt;li&gt;Low latency: WebSockets have low latency because they use a single, long-lived connection to transfer data, instead of making multiple short-lived connections. This reduces the overhead of connection establishment and packet header size, resulting in faster data transfer.&lt;/li&gt;
&lt;li&gt;Bi-directional communication: WebSockets allow for bi-directional communication, meaning both the server and client can send and receive data simultaneously.&lt;/li&gt;
&lt;li&gt;Cross-platform compatibility: WebSockets are supported by all major modern web browsers, as well as most web servers and programming languages.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fonlkm1s2jcb2advavmf6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fonlkm1s2jcb2advavmf6.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;➖ Disadvantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Complexity: WebSockets are more complex than traditional HTTP requests, and require additional setup and maintenance on both the server and client sides.&lt;/li&gt;
&lt;li&gt;Server resources: Because WebSockets keep a persistent connection open between the client and server, they require more server resources and can handle fewer concurrent connections than traditional HTTP requests.&lt;/li&gt;
&lt;li&gt;Security concerns: WebSockets can be vulnerable to security threats such as cross-site scripting (XSS) and cross-site request forgery (CSRF) attacks if not properly secured.&lt;/li&gt;
&lt;li&gt;Limited browser support: Although WebSockets are supported by most modern web browsers, they may not be supported in older browsers or in certain environments (e.g. some mobile platforms or network proxies).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Securing WebSocket Connections
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SSL/TLS&lt;/strong&gt;: The most effective way to secure **WebSocket **connections is to use SSL/TLS encryption by obtaining an SSL/TLS certificate for your server and configuring it to use HTTPS or wss:// protocol.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example WebSocket connection with SSL/TLS:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const ws = new WebSocket('wss://example.com/websocket');
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Rate limit&lt;/strong&gt;: Rate limiting is a technique used to prevent Denial-of-Service (DoS) attacks by limiting the number of requests that can be made within a given period of time. By implementing rate limiting on WebSocket connections, you can protect your server from being overwhelmed by an excessive number of requests and ensure that your system remains available to legitimate users.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CORS&lt;/strong&gt;: Cross-Origin Resource Sharing (CORS) is a security feature that enables web servers to specify which domains can access their resources. It is crucial to implement CORS properly when using WebSocket connections to prevent unauthorized access to sensitive data. By configuring your server to only allow connections from trusted domains, you can prevent attackers from bypassing the same-origin policy. Handling CORS preflight requests correctly is also important. With proper implementation, WebSocket connections can be secured and protected from potential attacks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use secure coding practices and avoid common security pitfalls&lt;/strong&gt;: When implementing WebSocket connections, it is important to use secure coding practices to prevent common security vulnerabilities such as SQL injection and cross-site scripting (XSS). This can be done by validating and sanitizing user input, avoiding the use of dynamic SQL queries, and using secure transport protocols like HTTPS and SSL/TLS. By following these best practices, you can ensure the security of your WebSocket connections and protect your users from potential attacks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Server-side input validation and data sanitization&lt;/strong&gt;: Implementing server-side input validation is crucial to prevent security vulnerabilities such as SQL injection and cross-site scripting (XSS) attacks. All data received from clients should be carefully validated and sanitized on the server-side to ensure that it is in the expected format and does not contain any malicious code. This can help prevent attackers from exploiting vulnerabilities in your WebSocket application and compromising your system. It is important to remember that client-side validation alone is not enough, as attackers can bypass it easily.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Common Use Cases for WebSocket Connections
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Real-time data updates&lt;/strong&gt;: WebSocket connections are often used to provide real-time data updates to clients, such as stock quotes, weather updates, and social media feeds. This allows the client to receive updates without having to constantly poll the server, reducing network traffic and improving performance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multiplayer games&lt;/strong&gt;: WebSocket connections can be used to create real-time multiplayer games, where players can interact with each other in real-time. This requires low latency and high throughput, which WebSocket connections can provide.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chat applications&lt;/strong&gt;: WebSocket connections are often used in chat applications, where users can send and receive messages in real-time. This allows for a more responsive and interactive user experience.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Collaborative applications&lt;/strong&gt;: WebSocket connections can be used in collaborative applications, such as document editors or project management tools, where multiple users can work together in real-time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IoT applications&lt;/strong&gt;: WebSocket connections are well-suited for IoT (Internet of Things) applications, where real-time data updates are critical. For example, WebSocket connections can be used to monitor sensor data from devices such as temperature sensors or motion detectors.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Testing WebSocket Connections: Best Practices
&lt;/h2&gt;

&lt;p&gt;To ensure that these connections function as expected, it is important to test them thoroughly. Here are some best practices for testing WebSocket connections:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use a WebSocket testing tool&lt;/strong&gt;: There are several testing tools available that can help you test WebSocket connections. These tools allow you to simulate WebSocket traffic, send messages, and monitor responses. Some popular WebSocket testing tools include Socket.io, Autobahn, and WebSocket.org.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test with different browsers&lt;/strong&gt;: WebSocket connections can behave differently in different browsers, so it is important to test your WebSocket connections in a variety of browsers, including Chrome, Firefox, Safari.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test with different devices&lt;/strong&gt;: WebSocket connections can also behave differently on different devices, such as desktops, laptops, tablets, and smartphones. It is important to test your WebSocket connections on a variety of devices to ensure that they function properly across all platforms.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test for error handling&lt;/strong&gt;: WebSocket connections can fail for various reasons, such as network issues, server errors, or incorrect data format. It is important to test your WebSocket connections for error handling and ensure that they respond appropriately to error conditions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test for performance&lt;/strong&gt;: WebSocket connections can be affected by network latency and server load, so it is important to test their performance under various conditions. This can include testing for message latency, throughput, and scalability.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In summary, testing &lt;strong&gt;WebSocket&lt;/strong&gt; connections is essential to ensure that they function properly under different conditions.&lt;/p&gt;

&lt;p&gt;By following these best practices, you can ensure that your WebSocket connections are reliable, performant, and error-free.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap-up
&lt;/h2&gt;

&lt;p&gt;In summary, &lt;strong&gt;WebSocket&lt;/strong&gt; is a powerful internet technology that has revolutionized real-time communication on the web. It allows for bidirectional, full-duplex communication channels between a web browser-based application and a server over a single TCP connection, enabling developers to build complex and powerful real-time applications.&lt;/p&gt;

&lt;p&gt;While there are advantages to using WebSocket, such as real-time data transfer and low latency, there are also some drawbacks, including complexity, server resource requirements, and security concerns. However, these can be mitigated through measures such as SSL/TLS encryption, rate limiting, and CORS.&lt;/p&gt;

&lt;p&gt;Overall, &lt;strong&gt;WebSocket&lt;/strong&gt; offers a promising solution for real-time communication on the web, and with proper implementation and security measures, it can be a powerful tool for developers to create dynamic and engaging web applications.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://adroitgroup.io/blog/the-power-of-websocket-revolutionizing-real-time-communication-on-theweb" rel="noopener noreferrer"&gt;adroitgroup.io&lt;/a&gt; and written by &lt;a href="https://medium.com/@martin.sulc" rel="noopener noreferrer"&gt;Martin Sulc&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>productivity</category>
    </item>
    <item>
      <title>The tricky CSS position: sticky</title>
      <dc:creator>Eduard Tar</dc:creator>
      <pubDate>Tue, 23 May 2023 13:46:18 +0000</pubDate>
      <link>https://dev.to/adroitgroup/the-tricky-css-position-sticky-54n9</link>
      <guid>https://dev.to/adroitgroup/the-tricky-css-position-sticky-54n9</guid>
      <description>&lt;p&gt;The CSS position property is a crucial aspect of web design, as it enables developers to control the layout and positioning of elements on a web page. This property offers five possible values: static, relative, absolute, fixed and sticky. Each of these values has specific characteristics that provide different positioning options. Understanding the behavior and usage of the position property is crucial for implementing advanced layout and design techniques on a website.&lt;/p&gt;

&lt;p&gt;In this article, we will explore the different values of the position property and how they can be used to achieve various layout outcomes. Before diving into the main topic of position: sticky, it's important to summarize the other possible values.&lt;/p&gt;

&lt;p&gt;Static elements are positioned according to the normal flow of the document, while relative elements are positioned relative to their normal position. Absolute elements are positioned relative to the nearest positioned ancestor but can be positioned anywhere on the page. And finally, fixed elements are positioned relative to the browser window&lt;br&gt;
(most of the time) and remain in the same place even when the page is scrolled.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkpinnvjij4kk4runim3w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkpinnvjij4kk4runim3w.png" alt="Image description" width="709" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding position: sticky
&lt;/h2&gt;

&lt;p&gt;According to &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/position#types_of_positioning" rel="noopener noreferrer"&gt;MDN&lt;/a&gt;: “A &lt;strong&gt;stickily positioned element&lt;/strong&gt; is an element whose computed &lt;code&gt;position&lt;/code&gt;value is &lt;code&gt;sticky&lt;/code&gt;. It's treated as relatively positioned until its containing block crosses a specified threshold (such as setting &lt;code&gt;top&lt;/code&gt;to value other than auto) within its flow root (or the container it scrolls within), at which point it is treated as "stuck" until meeting the opposite edge of its containing block”&lt;/p&gt;

&lt;p&gt;In simpler terms, a sticky element will act like a relative element until a specified threshold is reached. Once that threshold is met, the element will “stick” and remain in place, much like a fixed position element.&lt;/p&gt;

&lt;h3&gt;
  
  
  First working example
&lt;/h3&gt;

&lt;p&gt;We can achieve a very minimalistic working example with the following code (let’s ignore the design classes):&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&amp;lt;div class="page-design"&amp;gt;
  &amp;lt;main&amp;gt;
    &amp;lt;!--  Lorem ipsum --&amp;gt;
  &amp;lt;/main&amp;gt;
  &amp;lt;aside&amp;gt;
    &amp;lt;div
      style="height: 200px; position: sticky; top: 20px"
      class="sticky-design"
    &amp;gt;&amp;lt;/div&amp;gt;
  &amp;lt;/aside&amp;gt;
&amp;lt;/div&amp;gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We can see the sticky element working as expected:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9epmzei06krpcd31lej1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9epmzei06krpcd31lej1.png" alt="Image description" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But sometimes it’s not that straightforward… Typically, we set the position: sticky and for example top: 10px for an element, but we may wonder why it doesn’t work.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzz3hkwhlk4slhuwe2588.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzz3hkwhlk4slhuwe2588.png" alt="Image description" width="220" height="155"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;There are a few reasons why the &lt;code&gt;position: sticky&lt;/code&gt; property may not work as expected. Some of the most common reasons include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The parent container does not have a fixed height or width: For an element to be “sticky,” the dimensions of its container should be specified. If the parent container does not have a fixed height or width, the element will not be able to “stick” to the top or bottom of the container.&lt;/li&gt;
&lt;li&gt;The parent element has an overflow set to hidden: The parent element of a sticky element must have an overflow value other than hidden, otherwise, the sticky element will not be visible&lt;/li&gt;
&lt;li&gt;The element has a fixed position: If an element has a position of fixed, it will not be able to “stick” to the top or bottom of the screen&lt;/li&gt;
&lt;li&gt;The browser does not support it: Not all browsers support sticky, so if you’re using an older browser, it may not work as expected. Also, some browsers may require the format: position: -webkit-sticky&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;z-index&lt;/code&gt; is not set correctly: if the `&lt;code&gt;z-index&lt;/code&gt; of the sticky `element is not set or set lower than other elements on the webpage, it will be hidden behind other elements.&lt;/li&gt;
&lt;li&gt;The top, right, bottom, or left values are not set correctly&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Stick to the bottom?🤔
&lt;/h2&gt;

&lt;p&gt;If you have double-checked all the prerequisites and were able to achieve a working example of sticking an element to the top, but it fails to stick to the bottom when you set a bottom threshold, what should you do? It may seem like it should work, but unfortunately, it doesn’t always work that way.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F38ex45n5o01p96qar9jx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F38ex45n5o01p96qar9jx.png" alt="Image description" width="668" height="478"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;An important rule to keep in mind, as stated in the official documentation, is that using the sticky position will not automatically position the element to the top or bottom. Instead, it will determine how the element should “stick” to remain visible when the container begins to move out of view. To stick an element to the bottom, it must always be at the bottom of its container. One easy solution is to add another element before the sticky element, which will force it to the bottom. An example of this would be:&lt;/p&gt;

&lt;p&gt;`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`&lt;br&gt;
In this case, we can see that the sticky bottom functionality works as we expected it to:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fojpsgb24kheu2cikrsv5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fojpsgb24kheu2cikrsv5.png" alt="Image description" width="800" height="392"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Scrollable / Twitter-like sticky
&lt;/h2&gt;

&lt;p&gt;Now that we have all the necessary knowledge, let’s delve into this “magical” use case of the sticky position, which we will refer to as scrollable sticky. We are using this term because, despite the originator of this technique is unknown, it has been implemented seamlessly in the sidebar of the Twitter desktop site.&lt;/p&gt;

&lt;p&gt;But, what is this exactly? In the previous examples, we saw the use of a sticky sidebar. However, those would not make sense if the sidebar content was larger than the screen height as the bottom (or top) of the sidebar would not be visible ever. Twitter solved this issue by implementing a workflow where the sidebar scrolls with the rest of the page while there is content in it. Once there is no more content, the sidebar stops scrolling and sticks to the bottom. When scrolling up, the sidebar again scrolls with the page and then sticks to the top.&lt;/p&gt;

&lt;p&gt;How would you do this? It’s easy: when we scroll down, we set a top threshold to stick to the top, and when we scroll up, we set a bottom threshold to stick to the bottom. Congratulations, you made the same mistake that we did the first time. Try it out if you don’t believe us, but let us explain the problem with this approach: if you just scroll up and down a bit, the sidebar will jump instantly as it tries to stick to the bottom and then to the top, repeatedly. Our goal is to only stick the container when there is no more content left to scroll.&lt;/p&gt;

&lt;p&gt;To achieve this we need to come up with a very clever and counterintuitive idea: using negative threshold values.&lt;/p&gt;

&lt;p&gt;If the threshold is set to &lt;code&gt;top: 0px&lt;/code&gt;, the sidebar will stick to the top and will not scroll, so the content in the overflowing 100px will never be visible to the user:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzgjuhg9l4qa2yzjog19v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzgjuhg9l4qa2yzjog19v.png" alt="Image description" width="720" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, if we set the threshold to &lt;code&gt;top: -100px&lt;/code&gt;, the sidebar will scroll until that point and will stick only after that. This is demonstrated in the following sketch:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fokcgf9ytoc5ecelzp98h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fokcgf9ytoc5ecelzp98h.png" alt="Image description" width="720" height="408"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This addresses all issues that arise when the user scrolls downward. When scrolling upward, the same process should be implemented, but instead of setting the &lt;code&gt;top &lt;/code&gt;property, a negative threshold should be applied to the &lt;code&gt;bottom&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Essentially, this is the core idea that needs to be understood. In a nutshell: negative thresholds must be applied to prevent weird jumps in the sidebar and to allow it to both scroll and stick once the content can no longer be scrolled. The exact threshold value can be simply calculated by determining the size of the overflowing portion (&lt;code&gt;= sidebar height - screen height&lt;/code&gt;), but with a negative sign (ex. &lt;code&gt;top: -100px&lt;/code&gt;). It is also crucial to remember that on a downward scroll, the &lt;code&gt;top &lt;/code&gt;property should be set to this negative threshold value, and on an upward scroll, the &lt;code&gt;bottom&lt;/code&gt;property should be adjusted similarly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap-up
&lt;/h2&gt;

&lt;p&gt;In Angular, this entire workflow can be hidden within a directive, making it easy for developers to use. The directive takes care of all the calculations, so the developer does not have to worry about it. You can find the implementation and a demo of this directive here:&lt;/p&gt;

&lt;p&gt;☞ &lt;a href="https://gitlab.com/krisztoferkunc/scrollable-sticky" rel="noopener noreferrer"&gt;https://gitlab.com/krisztoferkunc/scrollable-sticky&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3y1fbgegwyhgb3wi7ulw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3y1fbgegwyhgb3wi7ulw.png" alt="Image description" width="800" height="392"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Originally published at &lt;a href="https://adroitgroup.io/blog/the-tricky-css-position-sticky" rel="noopener noreferrer"&gt;adroitgroup.io&lt;/a&gt; and written by &lt;a href="https://medium.com/@krisztoferkunc" rel="noopener noreferrer"&gt;Krisztofer Kunc&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>css</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How to start a web developer career in 2023?</title>
      <dc:creator>Eduard Tar</dc:creator>
      <pubDate>Mon, 15 May 2023 14:06:35 +0000</pubDate>
      <link>https://dev.to/adroitgroup/how-to-start-a-web-developer-career-in-2023-4hfh</link>
      <guid>https://dev.to/adroitgroup/how-to-start-a-web-developer-career-in-2023-4hfh</guid>
      <description>&lt;p&gt;Are you about to change your career? Have you always been interested in programming/web development but don't know where to start? Then you couldn't be in a better place.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--q78Hit7X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wfedfjbllxw9t9kk8trl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--q78Hit7X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wfedfjbllxw9t9kk8trl.png" alt="Image description" width="800" height="348"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The year 2022 was a watershed for many in terms of their careers. A lot of people lost their jobs and businesses, which put their basic livelihoods in jeopardy. At such times, the possibility of a career change arises in the mind.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--R2PDwvxj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0li9650z4hq4m2idimzn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--R2PDwvxj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0li9650z4hq4m2idimzn.png" alt="Image description" width="333" height="226"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The most valuable currency is "time" itself. What would be worth investing in? This is where IT (information technology) comes into the picture, which is known to be one of the fastest developing and most stable employment sectors. According to public opinion, developers earn relatively well, and many are attracted to this field by this fact. However, it is worth noting that the salary of programmers depends on a lot of variables, which I will perhaps cover in another article.&lt;/p&gt;

&lt;p&gt;As I wrote in one of my previous articles, the career of web developers usually starts with &lt;a href="https://adroitgroup.io/blog/the-most-useful-free-resources-for-frontend-developers-in-2022-html--css"&gt;learning the basics of HTML and CSS&lt;/a&gt;. In addition to javascript, HTML and CSS are the other two main pillars of website creation, so it is inevitable that you should familiarize yourself with them sooner rather than later. If you haven't had the chance to get to know them yet, I strongly recommend you to learn them before moving into the world of javascript.&lt;/p&gt;

&lt;p&gt;Let's see what options are available for an absolute layman/beginner to embark on the long and bumpy road of web development.&lt;/p&gt;

&lt;p&gt;Basically, I would divide the possibilities into 2 main categories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;self-development: fully self-taught learning (free)&lt;/li&gt;
&lt;li&gt;codecamp: signing a contract with an educational company (paid)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this article, I focused primarily on the resources related to the free, self-development-based approach.&lt;/p&gt;

&lt;p&gt;First of all, let's see what types of source materials are available to us to learn:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;lexical informative websites, documentations&lt;/li&gt;
&lt;li&gt;books (doc, e-book, physical book)&lt;/li&gt;
&lt;li&gt;video tutorials (Youtube, Udemy)&lt;/li&gt;
&lt;li&gt;practical educational websites (sandbox)&lt;/li&gt;
&lt;li&gt;podcasts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--D9PQanPW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rlr21lrkttu7u4agttoc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--D9PQanPW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rlr21lrkttu7u4agttoc.png" alt="Image description" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;After some research, the amount and selection of source materials available can be more intimidating than the learning process itself.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Each type of medium has its advantages and disadvantages, as well as the ideal case when one is preferred over the other. For beginners, I would recommend a hybrid solution so that they can accumulate relevant practical and theoretical knowledge in the shortest possible time. The knowledge suitable for starting a career can be obtained most quickly with the help of video-based tutorials and lexical + practical educational websites. Let’s look at them one by one.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Acquiring the required basics - Lexical knowledge
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dev.to**url**"&gt;W3 school&lt;/a&gt;: A platform that can be considered ideal for complete beginners.&lt;/p&gt;

&lt;p&gt;The documentation is not as detailed as MDN or javascript.info (see later in the article), but there is enough information to learn the (not very stable) basics. Its biggest advantage is the built-in sandbox code editor, which allows you to edit the code examples within the website, making the learning process much more playful and interactive. The fact that there are plenty of other tutorials related to web development also speaks for the site. If you're done with javascript, you might want to check them out as well. The biggest disadvantage is the slightly obsolete information base and the transmission of insufficient information (which does not detail the true depths of the given programming language).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--T2s0U0f8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bgy4nxe4mz1o546ynqpd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--T2s0U0f8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bgy4nxe4mz1o546ynqpd.png" alt="Image description" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://javascript.info/"&gt;Javascript.info&lt;/a&gt;: The perfect javascript documentation, which is smaller than the MDN documentation, but more comprehensive than other similar sites.&lt;/p&gt;

&lt;p&gt;In order to start learning javascript frameworks, it is essential to first deepen our native javascript knowledge as much as possible. javascript.info presents the programming language with perfectly developed hybrid documentation and exceptionally perceptive examples. Another strength of the site is the comment section. Hundreds of people add their opinions, additional insights, and code snippets to each topic.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7PObfd6x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9x249cia20einu2qaoic.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7PObfd6x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9x249cia20einu2qaoic.png" alt="Image description" width="800" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript"&gt;MDN&lt;/a&gt;: The most detailed and comprehensive javascript documentation on the web.&lt;/p&gt;

&lt;p&gt;This is a resource that I would not necessarily recommend to novice web developers. At least not for learning purposes. Even though MDN is the Alpha and Omega of javascript documentation, it contains too massive an amount of information on a single topic for beginners, which can overload many, and in the worst case, demotivate them. For beginners, it may be worth choosing this platform when they are interested in the operation of a specific API reference. Ex: What is Object.create() for and what parameters does it have? However, for this purpose chatGPT may be a more efficient tool (later in the article)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5z9GwnxU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/21v5bcxal8rjeb9xicda.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5z9GwnxU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/21v5bcxal8rjeb9xicda.png" alt="Image description" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Practical educational websites (code sandbox)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.jschallenger.com/"&gt;JsChallenger&lt;/a&gt;: Translating theory into practice is a long process. JSChallenger is the perfect place for this purpose.&lt;/p&gt;

&lt;p&gt;The tutorials start with beginner-level examples and end with advanced examples. Learn the use of primitive and reference type variables, DOM manipulation, and practice until your nose bleeds :)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lx4dycWX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/52hcij4pttpchj1vzowg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lx4dycWX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/52hcij4pttpchj1vzowg.png" alt="Image description" width="800" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.theodinproject.com/"&gt;TheOdinProject&lt;/a&gt;: The odin project primarily focuses on marketable knowledge.&lt;/p&gt;

&lt;p&gt;Under the odin project's free mentor program, it is not only teaches javascript but also provides insight into other segments of web development, such as HTML+CSS, Ruby, database management, and Node js. So those who are looking for full-stack development may be tempted by what the site has to offer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://adroitgroup-io-storage.s3.eu-central-1.amazonaws.com/text-editor/2023-02-13_caNRPxYcCy_Your-Career-in-Web-Development-Starts-Here-The-Odin-Project.png"&gt;https://adroitgroup-io-storage.s3.eu-central-1.amazonaws.com/text-editor/2023-02-13_caNRPxYcCy_Your-Career-in-Web-Development-Starts-Here-The-Odin-Project.png&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.codewars.com/"&gt;CodeWars&lt;/a&gt;: If you have acquired the coveted knowledge, unfortunately, it must be kept up to date. War with the codes!&lt;/p&gt;

&lt;p&gt;Each code exercise (or 'kata' as they call it on the site) was created by the community to help strengthen different coding skills. In addition to javascript, you can choose from another 55+ supported programming languages. If you have gained enough rank, you can create "katas" yourself, which you can impress your future employers :)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--r5rT8MAi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pzevm4tyc4mk7orgnger.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--r5rT8MAi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pzevm4tyc4mk7orgnger.png" alt="Image description" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.codingame.com/"&gt;CodeInGame&lt;/a&gt;: A tutorial based on very strong interactive foundations which build on games in every sense.&lt;/p&gt;

&lt;p&gt;Discover new languages (more than 25 languages in total), algorithms and tricks in courses created by world-class developers. They take the term “beginner to advanced” very seriously. If you want to be part of a really interactive learning process combined with a visual experience, then this is your place.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Rnu9zW_R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/11q7nq32y97u3ryffyt3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Rnu9zW_R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/11q7nq32y97u3ryffyt3.png" alt="Image description" width="800" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Video-based tutorials (youtube channels, udemy)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pSm-64pk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8wszw77g3w8zain732dn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pSm-64pk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8wszw77g3w8zain732dn.png" alt="Image description" width="150" height="44"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.udemy.com/course/the-complete-javascript-course/"&gt;Jonas Schedthmann&lt;/a&gt;: Zero to hero comprehensive javascript course from the turtle himself.&lt;/p&gt;

&lt;p&gt;Jonas Schedthmann has undeniably put together one of the most complete video-based educational materials about javascript. The 70 hours long tutorial guides you completely from the basics to the advanced depths, with great examples, at a slow and easy-to-understand pace. When I say slow, I mean it. In extreme cases, you may even want to set the play speed of the video player by x1.25 😀 Before you start his tutorial, make sure to make a coffee. According to the participants of the course, the first part of the curriculum is very good, but the second 35 hours already feel less organized and exhausting.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.udemy.com/courses/search/?q=maximilian+schwarzm%C3%BCller&amp;amp;src=sac&amp;amp;kw=maximilian"&gt;Maximilian Schwarzmüller&lt;/a&gt;: The "all-knowing" German front-end developer.&lt;/p&gt;

&lt;p&gt;If I want to learn a new frontend framework from the ground up, the first thing I do is to check out Maximilian's tutorial on the subject. And this is no accident. He teaches in an extremely comprehensible and lovable way, with a pleasant German accent. He structures his courses very consciously, and the pet-projects created during the course can also represent a professional reference value.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XJvNzwDN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v1toa60l4zup0vorcwub.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XJvNzwDN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v1toa60l4zup0vorcwub.png" alt="Image description" width="150" height="63"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/@TraversyMedia/featured"&gt;TraversyMedia&lt;/a&gt;: The veterans of web development videos on youtube.&lt;/p&gt;

&lt;p&gt;TraverseMedia is a YouTube channel made up of highly qualified professionals, where we are guaranteed to receive the highest quality education according to current trends. They have been on YouTube for over 10 years and have published hundreds of videos on all aspects of web development.&lt;/p&gt;

&lt;p&gt;[WebDev simplified:](&lt;a href="https://www.youtube.com/@WebDevSimplified/featured"&gt;https://www.youtube.com/@WebDevSimplified/featured&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;) The guy who got bored of modelling and started programming instead.&lt;/p&gt;

&lt;p&gt;He’s my personal favorite because he can detect javascript blind spots with amazing precision. It is a pleasure to listen to each of his videos, which are concise, to the point, clean, and are presented in both practical and theoretical ways. Even after years, I learn valuable tricks from him day to day. A just have!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/@WebDevSimplified/featured"&gt;https://www.youtube.com/@WebDevSimplified/featured&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/@Fireship"&gt;Fireship.io&lt;/a&gt;: The man who overdosed on red bull.&lt;/p&gt;

&lt;p&gt;I put him on the list because of his popularity rather than his effectiveness. fireship.io has become famous for its 100-second videos, which essentially demonstrate an entire programming language or another web development-related technology in just a minute and a half. In order to be able to convey meaningful information during this time, he has to go through the essence of the given topic at a rate that would even embarrass rappers, which is obviously not very effective, but it can definitely be said to be interesting.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Books
&lt;/h2&gt;

&lt;p&gt;This medium is a blind spot for me, and I don't want to hypocritically recommend a book without ever having read one (This is not entirely true, because I have read a book about Java, and it didn't end well). Due to its massive theoretical nature, its effectiveness can be questioned. After all, while reading, we can only record what we see on a theoretical level, not in practice. I would recommend books for those who want to gain insight into the deepest layers of javascript. But so that we do not leave empty-handed, I will share a link where the most successful and recognized books have been collected:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://hackr.io/blog/javascript-books"&gt;https://hackr.io/blog/javascript-books&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Other supplementary materials (advanced)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://refactoring.guru/design-patterns"&gt;Design Patterns:&lt;br&gt;
&lt;/a&gt;&lt;br&gt;
Design patterns are a part of software design that aims to solve typical and frequently occurring problems. Each such pattern is essentially a blueprint that we can use as a guide while writing our code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://adamcoster.com/blog/commonjs-and-esm-importexport-compatibility-examples"&gt;CommonJS (cjs) vs. Modules (ESM):&lt;br&gt;
&lt;/a&gt;&lt;br&gt;
Take a detailed look at the difference between the 2 sets of standards used to implement modules in JavaScript.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.cypress.io/"&gt;Cypress:&lt;/a&gt; With Cypress, you can easily create tests for your modern web applications, visually find potential errors in your application, and run them automatically in integration builds.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://refactoring.guru/design-patterns"&gt;Web workers:&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We use Web Workers to create scripts that can be run on multiple threads in the background. The worker can perform tasks without disrupting/blocking the user interface.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://threejs.org/"&gt;Three.js:&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The three. js is a JavaScript-based WebGL engine that can run GPU-based games and other graphics-based applications directly from the browser. The three. js library provides many services and APIs for presenting 3D-based content in the browser.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://bloggingfordevs.com/javascript-blogs/"&gt;Best javascript blogs:&lt;br&gt;
&lt;/a&gt;&lt;br&gt;
Due to the rapid development of the web and the new technologies appearing every day, it is worth keeping our tool sets up-to-date, in which reading blog articles can be of great help.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://openai.com/"&gt;ChatGPT:&lt;br&gt;
&lt;/a&gt;&lt;br&gt;
The capabilities of the artificial intelligence chatbot tool, launched in November 2022 by San Francisco-based startup OpenAI, are vast. It can fix spelling and grammar errors, write contracts, poems and songs, analyse or reflect on code written in any language and much more. It is a must-have tool to help you become a better developer.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Javascript frameworks:
&lt;/h2&gt;

&lt;p&gt;Unfortunately, learning native javascript is not the end goal, but only a stop on the long journey of learning. Entire frameworks are built on top of javascript. With these frameworks, we can create modern, fast, scalable applications that have out-of-the-box solutions for all kinds of problems. All of the frameworks are based on the basic principles of javascript but still operate with specific functionality and syntax. When we talk about front-end development, the labor market in most cases assumes that you have experience in at least one of these frameworks, so it is particularly important to master one or more. Let's take a look at these frameworks in ascending order of difficulty:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JOueCpzw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6kiof4am08yugbfotcwn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JOueCpzw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6kiof4am08yugbfotcwn.png" alt="Image description" width="125" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Svelte&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;:&lt;br&gt;
&lt;strong&gt;Learning curve&lt;/strong&gt;: Short&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Description&lt;/strong&gt;: It's basically quite similar to react and vue. The goal of the framework is to create fast and modern user interfaces. However, there is a significant and essential difference between them, to which it owes its popularity: svelte interprets and compiles the code during build-time, in a way that can be understood by browsers Thanks to this approach we can save a lot of resources, and optimizing the running time of our application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advantages&lt;/strong&gt;: quick to learn, extremely simplified approach&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Drawbacks&lt;/strong&gt;: it has a small developer community, and it's hard to find a job with it&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Documentation&lt;/strong&gt;: &lt;a href="https://svelte.dev/"&gt;https://svelte.dev/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JpQ_WQDZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sisfnyds7w99afvdyvhv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JpQ_WQDZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sisfnyds7w99afvdyvhv.png" alt="Image description" width="173" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Vue
&lt;/h3&gt;

&lt;p&gt;:&lt;br&gt;
&lt;strong&gt;Learning curve:&lt;/strong&gt; Short/Medium&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Description&lt;/strong&gt;: The javascript framework developed by Evan You that conquered the world. The Vue. js (or simply Vue) is a lightweight JavaScript framework for building reactive web user interfaces. Vue progressively extends standard HTML and CSS to efficiently create interactive interfaces.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advantages&lt;/strong&gt;: innovative approach, can be learned quickly and easily&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Drawbacks&lt;/strong&gt;: compared to react and angular, smaller community and fewer work opportunities, too much flexibility, lack of typescript in vue 2.0, options and composition api -&amp;gt; double learning,&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Documentation&lt;/strong&gt;: &lt;a href="https://vuejs.org/"&gt;https://vuejs.org/&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lbeaU3Mp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0s42gf9kn17h2xu06m82.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lbeaU3Mp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0s42gf9kn17h2xu06m82.png" alt="Image description" width="173" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  React:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Learning curve:&lt;/strong&gt; Short/Medium&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Description:&lt;/strong&gt; React is a JavaScript library developed by Facebook, which was used, among other things, to develop Instagram.com. Its purpose is to enable developers to easily create fast user interfaces for both websites and applications. The main features of React are the virtual DOM and the JSX template engine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt; easy and quick to learn, many job opportunities globally&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Drawbacks:&lt;/strong&gt; JSX can be difficult to get used to at first, strongly dependent on third-party libs, classes and hooks -&amp;gt; double learning&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Documentation&lt;/strong&gt;: &lt;a href="https://reactjs.org/"&gt;https://reactjs.org/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aY3y9IFk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zzr2ygd5snm8svt6s40a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aY3y9IFk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zzr2ygd5snm8svt6s40a.png" alt="Image description" width="141" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Angular:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Learning curve&lt;/strong&gt;: Long&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Description&lt;/strong&gt;: The framework created by Google is mostly used for the development of large-scale enterprise applications due to its scalability and stability. Compared to its peers, it has a much larger set of built-in tools and supports typescript natively.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advantages&lt;/strong&gt;: typescript, easily scalable, many domestic and foreign job opportunities&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Drawbacks&lt;/strong&gt;: inconvenient documentation, longer and more difficult to learn than other frameworks&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Documentation&lt;/strong&gt;: &lt;a href="https://angular.io/"&gt;https://angular.io/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Bonus: Interviewing
&lt;/h2&gt;

&lt;p&gt;The presentation of acquired knowledge is at least as important as its application in practice. If we cannot present the knowledge we have to others (employers), it will be much more difficult for us to assert ourselves in the labor market. It may be a good idea to devote some time to possible questions that may arise during interviews so that we don't lose our dream job because of unpreparedness. Personally, I lost many job opportunities before I realized how much of a weakness it is if I can't communicate professionally during an interview. In order to alleviate this problem, I have collected the links of what I consider to be the best (beginners) javascript/web development interview questions, which I would like to share with you now.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Devinterview-io/css-interview-questions"&gt;CSS interview questions&lt;br&gt;
&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/sudheerj/javascript-interview-questions"&gt;Native/Vanilla JS interview questions&lt;br&gt;
&lt;/a&gt;&lt;br&gt;
&lt;a href="https://gist.github.com/paulfranco/9f88a2879b7b7d88de5d1921aef2093b"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://gist.github.com/paulfranco/9f88a2879b7b7d88de5d1921aef2093b"&gt;Node interview questions&lt;br&gt;
&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.simplilearn.com/tutorials/git-tutorial/git-interview-questions"&gt;GIT interview questions&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Learning to code is not fast, and certainly not a process to be rushed. It is worth choosing our source materials well because they can decide the fate of our entire career as a programmer. It is important to receive repeated positive feedback about our results during learning, so I would recommend a more interactive version of learning instead of books and other written documents. Video-based tutorials and practical training websites can be the target tools with which we can visualize our results and gain motivation to continue learning.&lt;/p&gt;

&lt;p&gt;To be able to get a job as a Junior programmer in 2023, you will need (among other things) the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;use the educational materials outlined in the article&lt;/li&gt;
&lt;li&gt;acquire solid foundations in the chosen programming language, javascript in our case&lt;/li&gt;
&lt;li&gt;learn to use at least one javascript framework (vue, react, angular)&lt;/li&gt;
&lt;li&gt;test your practical and lexical knowledge, prepare for interviews&lt;/li&gt;
&lt;li&gt;have presentable pet projects (game, calculator, api use, fake webshop, etc...)&lt;/li&gt;
&lt;li&gt;develop your soft skills (language, diligence, proactivity, openness to learn new technologies and toward people)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EfhVcJqR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rhgx7zpk8e0okztdy6ia.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EfhVcJqR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rhgx7zpk8e0okztdy6ia.png" alt="Image description" width="480" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I wish you happy learning and lots of success! :)&lt;/p&gt;

&lt;p&gt;Originally published at &lt;a href="https://adroitgroup.io/blog/how-to-start-a-web-developer-career-in-2023"&gt;adroitgroup.io&lt;/a&gt; and written by &lt;a href="https://medium.com/@mate.sera"&gt;Maté Séra&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>tutorial</category>
      <category>programming</category>
    </item>
    <item>
      <title>Using mixins in Angular — A Comprehensive Guide</title>
      <dc:creator>Eduard Tar</dc:creator>
      <pubDate>Mon, 15 May 2023 13:52:40 +0000</pubDate>
      <link>https://dev.to/adroitgroup/using-mixins-in-angular-a-comprehensive-guide-1l8o</link>
      <guid>https://dev.to/adroitgroup/using-mixins-in-angular-a-comprehensive-guide-1l8o</guid>
      <description>&lt;p&gt;So to oversimplify things you can think of statements (and declarations for that matter) as somewhat pre-defined, static parts of the application code. They are static in the sense that you have to explicitly write them down as they are and they have to be known at compile time so to speak. For example, a function declaration or an if statement inside of it is written by you and is hardcoded. These are templates that will be used (executed) at runtime. Whereas expressions are the bread and butter of a program, the dynamic parts. You may have not realized it before, but anytime you’re calling a function that’s an expression, a call expression. Sticking to this example, it is easy to understand then that expressions allow the program to have dynamic behaviours.&lt;/p&gt;

&lt;p&gt;Why’s all this prep talk about the building blocks of programming languages? Because now that we’ve understood what expressions are we can appreciate what it means for us that classes can be used as expressions. You can basically do anything you want with them, and place them almost anywhere you want them. That’s how we get back to the fact that we can write functions in the return classes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkykdle3no5h1rszq35ic.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkykdle3no5h1rszq35ic.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started With Mixins in Angular
&lt;/h2&gt;

&lt;p&gt;Let’s tackle some things about mixins before we go any further. Mixin functions should always take one optional parameter and that’s a potential base class constructor function. That’s how we can chain them together. This allows one mixin function to take another mixin function’s returned value (another class expression) as its input and use it as its own class expressions’ base class.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

export function someMixin&amp;lt;T&amp;gt;(base?: Constructor&amp;lt;T&amp;gt; = class {} as T) {
    return class extends base {}
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;What now? Did I just hint that even the extends keyword can be used with dynamic values? Yep, I did. Just take a sec to think about it. How else would we apply our first mixin function to a normal “child” class if we couldn’t use dynamic values with the extends keyword? In fact, let me get this out of the way quickly. The extends keyword requires a class constructor function reference or any expression that returns one. So this means that syntaxes like these are completely valid.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

export class MyChildClass extends someMixin() {}



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Another thing about mixins and their usage that’s important to mention is that TS only allows the &lt;code&gt;args: any[]&lt;/code&gt; parameter definition for mixin constructors. This makes sense as from the context of one mixin you wouldn't know how it's going to be used and what parameters it might receive. Since mixins have to pass their constructor params to each other. So the current mixin that you're working on could state what parameters it requires, it would have no way of knowing what other mixins used together with it would.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

export function someMixin&amp;lt;T&amp;gt;(base?: Constructor&amp;lt;T&amp;gt; = class {} as T) {
    return class extends base {
      constructor(args: any[]) {
        super(...args);
      }
    }
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This means that if your mixin needs some params like a configuration you have to get creative and supply that param in a manner that will allow you to find it in the args array. One such solution is to use class instances for configuration in tandem with the &lt;code&gt;instanceof&lt;/code&gt;operator.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

export class MixinConfig {
  // whatever your mixin needs
}

export function someMixin&amp;lt;T&amp;gt;(base?: Constructor&amp;lt;T&amp;gt; = class {} as T) {
    return class extends base {
      constructor(args: any[]) {
        super(...args);

        const config = args.find(arg =&amp;gt; arg instanceof MixinConfig);
        if (!config) {
          // handle the case where the mixin didn't receive it's config.
        }

        Object.assign(this, config);
      }
    }
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Understanding Mixins in Angular
&lt;/h2&gt;

&lt;p&gt;There are some caveats to using mixins in an Angular application. Let’s start with the most obvious one. Angular features that require the usage of Angular decorators like @Input and @output will not work in mixins. The child class extending the mixins can define them with no problem. But the Angular compiler will not execute or walk your code in order to figure out what your component class extends if the base class is not a statically known symbol. In fact, TS won’t even let you decorate your mixin class expression. This may change from TS version to another however the general takeaway is that Angular features don’t work in mixins.&lt;/p&gt;

&lt;p&gt;You can pass constructor DI parameters onward to your mixins from your child class. You can also use the relatively new &lt;code&gt;inject()&lt;/code&gt;function to inject the mixins dependencies right inside the mixin class itself.&lt;/p&gt;

&lt;p&gt;Lifecycle hooks can work in mixins but there are some gotchas here too. Prior to Angular v10 (not like anyone’s still maintaining legacy code bases with those Angular versions right?) lifecycle hooks were handled by Angular with component features. These features had to be discovered by the compiler at compile time. So even though you could define an &lt;code&gt;ngOnInit&lt;/code&gt;method in your mixin it wouldn't have been called because Angular didn't know about it. After v10 however, the compiler resolves the lifecycle hooks in a different manner. to be honest I'm not entirely sure how, so if you are interested go and dig deeper for yourself. The result of this is that from v10 lifecycle hooks defined in mixins will be called by Angular unless...&lt;/p&gt;
&lt;h2&gt;
  
  
  Property class on the prototype chain
&lt;/h2&gt;

&lt;p&gt;I’m assuming that you have a basic understanding of how inheritance and classes work in JS. To be more specific the prototype chain. What happens then if multiple classes extend each other and multiple classes define the same method? Yes, you’ve guessed right: property name clash. 😉&lt;/p&gt;

&lt;p&gt;In situations like these, the property lookup algorithm used by JS engines will walk upward the prototype chain checking each prototype object along the way for that certain property name. And if it is found the algorithm returns the found property’s value. So a more appropriate name for such situations is property name shadowing. You have basically no way of accessing the other properties with the same name.&lt;/p&gt;
&lt;h2&gt;
  
  
  Working with Lifecycle Hooks in Angular Mixins
&lt;/h2&gt;

&lt;p&gt;By now we know that lifecycles can be used in mixins and that multiple lifecycle hooks of the same kind will shadow each other. Okay but then how are we going to use ngOnInit and the other hooks in our mixins? I mean, you can always call them by hand right? Sounds like a simple yet tedious solution. The thing is though, mixins don’t know about each other so-called super. ngOnInit in your mixin will yield you a TS error. Not to mention that even if this approach worked it would be very error-prone.&lt;/p&gt;
&lt;h2&gt;
  
  
  Get Started With The AutoHooks Decorator
&lt;/h2&gt;

&lt;p&gt;We’re finally here! Let’s talk about how to solve the outlined problem with a TS decorator. What else did you expect? :D&lt;/p&gt;

&lt;p&gt;AutHooks is a class decorator that has to be placed onto the child class that extends mixins. The decorator will walk the prototype chain of the decorated class and look for any and all Angular lifecycle hooks (and any other method configured in the decorator). It will then override each method it found with one that calls the next lifecycle hook method in line. The method chaining logic ensures and execution order of the lifecycle hooks is the same as the execution of class constructors. Meaning that the last lifecycle hook is called first and the execution proceeds to the first hook. The first is the hook of the child class in this case.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

@Component({ ... })
@AutoHooks()
export class SomeComponent extends someMixins(AnotherMixin()){
    // class implementation
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The decorator can only be used once per prototype chain. This only really means that if you happen to use multiple regular classes in a prototype chain then only the bottom-most child class can use the decorator. However, the decorator does let you know if you’re using it incorrectly.&lt;/p&gt;

&lt;p&gt;We did have to use some Angular private APIs to make the decorator work in ng versions less than 10. As I’ve mentioned before those versions work differently than the latter ones. But the usage of these private APIs should be fine since old versions won’t change in the future.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap-up
&lt;/h2&gt;

&lt;p&gt;It’s been a long journey up until here, but we managed to discover what mixins are and how can we use them with Angular. We saw what’s the problem with lifecycle hooks defined in mixins and also how to solve this problem.&lt;/p&gt;

&lt;p&gt;Now, after all this, you might be thinking to yourself: Alright, pretty neat. But how could I use this solution myself?&lt;/p&gt;

&lt;p&gt;Lucky for you, we’ve already done the heavy lifting for you. I and my team over at @Adroit Group have been working on a utility library for Angular full of useful stuff. Including, of course, the AutoHooks decorator I've introduced to you today.&lt;/p&gt;

&lt;p&gt;So if this directive or the library, which we’ll certainly write more about soon, has sparked your interest, you can head on over to NPM or Github to take a look or even download and use it. 📚👀&lt;/p&gt;

&lt;p&gt;I’d like to thank you for your time and attention in reading this article.&lt;/p&gt;

&lt;p&gt;I was your tour guide Jonatán Ferenczfi, Frontend tech lead at @Adroit Group, Angular bro and high-functioning coffee addict. ☕&lt;/p&gt;

&lt;p&gt;Until next time 👋&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://adroitgroup.io/blog/using-mixins-in-angular-a-comprehensive-guide" rel="noopener noreferrer"&gt;adroitgroup.io &lt;/a&gt;and written by &lt;a href="https://medium.com/@jonatanferenczfi" rel="noopener noreferrer"&gt;Jonatan Ferenczfi&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>javascript</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Conditional SSR templates made easy</title>
      <dc:creator>Eduard Tar</dc:creator>
      <pubDate>Mon, 15 May 2023 13:47:32 +0000</pubDate>
      <link>https://dev.to/eduardtar/conditional-ssr-templates-made-easy-2j7l</link>
      <guid>https://dev.to/eduardtar/conditional-ssr-templates-made-easy-2j7l</guid>
      <description>&lt;p&gt;Have you ever found yourself in a situation where you knew something doesn’t have to be rendered on the server or wouldn’t work? Maybe a 3rd party lib used in your app accesses the DOM directly. Or you have a use case where you couldn’t avoid such a thing. More likely even is that you’ve realized that a certain component is unnecessary in SSR. I’m sure if you’re reading this article then you had such experiences.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fBxTN6iW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6ewsgzj45sv3u1iw62c8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fBxTN6iW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6ewsgzj45sv3u1iw62c8.png" alt="Image description" width="687" height="392"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conditional SSR templates made easy
&lt;/h2&gt;

&lt;p&gt;If you have some experience with Angular and SSR you may already have an idea in your head to solve such an issue. However let’s take a look at the traditional/naive way of solving an issue like this, just for the sake of being on common ground.&lt;/p&gt;

&lt;p&gt;Following my thought process when solving programming issues in my day-to-day work, I’d take a step or two back and take a proper look at the big picture, the whole of the problem. In our example, the context of the problem is an Angular application where we’d like to display or hide some parts of the UI based on some logic. That sounds like we’d want to use the *ngIf built-in directive from Angular and supply it with our logic to determine if our application runs on the server (SSR) or in the browser.&lt;/p&gt;

&lt;p&gt;So far so good. But how are we going to “know” this information? Well, there are multiple ways to get this information but the most basic way is to ask Angular for it. Let’s see how we’d do that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Component, Inject, `PLATFORM_ID` } from '@angular/core';
import { isPlatformBrowser, isPlatformServer } from '@angular/common';

@Component{
  selector: 'spp-root',
  styleSheetsUrls: ['./app.component.scss'],
  templateUrl: '/.app.component.html',
})
export class AppComponent {
    isBrowser = isPlatformBrowser(this.platformId);
    isServer = isPlatformServer(this.platformId);
    constructor(@Inject(`PLATFORM_ID`) public platformId: string) {}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;In our component .ts file we have to ask Angular for the most crucial piece of information, the active platform’s identifier.&lt;/li&gt;
&lt;li&gt;We have to use the @Inject decorator to inject the PLATFORM_ID token, which holds the value of the active platform on which our application runs.&lt;/li&gt;
&lt;li&gt;Then we need some utilities from Angular to interpret the platform identifier value we’ve received. Here we used the “isPlatformBrowser” and “isPlatformServer” functions exposed by Angular to get a boolean value indicating whether or not the app is running in the browser or on their server.
Now you might be wondering: What is a platform in the context of an Angular application? 🤔&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’m glad you’ve asked! 🤓&lt;/p&gt;

&lt;p&gt;You see there are a lot of smart folks over at big daddy Google, so no wonder some of them had the foresight to design a software platform that’s compatible with different execution environments. Now Angular certainly isn’t the first and only software system designed with this foresight. Just think about Flutter for example. Point is that although there is an intended place for the system to be used, like in the browser to power SPAs, the system is equipped with the appropriate tools to work in other places too. In our case, two such execution environments are the browser and the server, most commonly a Node.js script. So in the context of an Angular application, a platform refers to a distinct execution environment.&lt;/p&gt;

&lt;p&gt;Armed with this knowledge then let’s take a look at our app.component’s html:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;3rd-party-photo-gallery&amp;gt;&amp;lt;/3rd-party-photo-gallery&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;We have only one component used in our example to keep things simple.&lt;/li&gt;
&lt;li&gt;There’s an imaginary 3rd party angular lib used here that exposes some kind of photo gallery, which unfortunately reaches into the DOM directly.
With all the setup done in our app.component.ts file previously we can just put an +ngIF directive onto this tag and pass it the “isBrowser” property of our component, like so:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;3rd-party-photo-gallery +ngIf="isBrowser"&amp;gt;&amp;lt;/3rd-party-photo-gallery&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that certainly solves our problem. However we don’t just want to solve it, we’d want to solve it in a scalable way. Currently, however, our solution requires a setup logic in each component where we’d want to use it. That doesn’t look too DRY, does it?&lt;/p&gt;

&lt;p&gt;So next let’s take some time and think about how we could extract this setup logic from our component and make it easily reusable. Right off the bat, there are a few ideas that should pop into your head. At least one of the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Make an @Injectable service that exposes this logic to whatever component needs it.&lt;/li&gt;
&lt;li&gt;Create a mixin exposing this logic and extend whatever component needs this info with the mixin.&lt;/li&gt;
&lt;li&gt;Create a structural directive similar to Angular’s +ngIf that contains all the setup logic inside itself.
I personally like all three ideas. So let’s explore them one by one briefly.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  InjectableService solution
&lt;/h3&gt;

&lt;p&gt;This idea might be the most obvious for Angular devs. Whenever you have some reusable logic extract it into a service, then inject that service where ever it’s needed.&lt;/p&gt;

&lt;p&gt;There’s certainly merit to this idea. We’d adhere to the SRP principle, with a good choice for our service’s name it would be easy to find it in any code base. And overall a clean architectural solution.&lt;/p&gt;

&lt;p&gt;There are some problems with it though. we may want to use smart/dumb component patterns in our application. That’s reasonable to assume for almost any medium-sized or bigger Angular application. In that case, we’d surely run into situations where a dumb component required the logic provided by our service. Abiding by the dumb component rules would force us to obtain the platform-related information in some parent component and pass it down to its dumb child. Even worse is the possibility of multiple levels of dumb components in the component hierarchy. This is called data or input drilling, and we’d want to avoid it if possible. So while this solution feels to most natural to us, we might end up shooting ourselves into the foot with it down the line.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mixin solution
&lt;/h3&gt;

&lt;p&gt;In case you haven’t used JS mixins before let me introduce them to you. A mixin is nothing more than a function that takes a class expression as an argument and returns a new anonymous class expression extending the received one. Thereby allowing us JS devs to use multiple inheritances in our codebase. Just for the sake of being precise, mixins don’t really allow multiple inheritances in JS, because there’s no such thing as multiple inheritances in the language. What we can achieve with mixins is more like a dynamic way to build the prototype chain of a JS class. Which is the closest we get to proper multiple inheritances, and is very similar to that in terms of how it works and what it can do.&lt;/p&gt;

&lt;p&gt;So after this short introduction to mixins, let’s see what a mixin-based implementation of our platform observing setup logic would look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Inject, `PLATFORM_ID` } from "@angular/core";
import { isPlatformBrowser, isPlatformServer } from "@angular/common";

export function platformObserverMixin&amp;lt;T extends Constructor&amp;lt;any&amp;gt;&amp;gt;(
  Base: T = class {} as any
) {
  isBrowser = isPlatformBrowser(this.platformId);
  isServer = isPlatformServer(this.platformId);
  class Mixin extends Base {
    constructor(...args: any[]) {
      super(...args);
    }
  }
  return Mixin;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;As we outlined above we define a function that returns a class expression.&lt;/li&gt;
&lt;li&gt;we define a constructor for our Mixin class expression that receives all the arguments and passes them forward to its Base class.&lt;/li&gt;
&lt;li&gt;In our Mixin class expression, we define the two utility properties indicating whether the app runs on a given platform.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All right, looks fine, but how do we get a hold of the &lt;code&gt;PLATFORM_ID&lt;/code&gt;injection Token's value here?&lt;/p&gt;

&lt;p&gt;I intentionally left out that part of the mixin because there are multiple ways to do so.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to obtain external values inside of a mixin
&lt;/h3&gt;

&lt;p&gt;Let’s begin exploring these possibilities by establishing that a mixin can’t and shouldn’t know where it is used. Neither its child nor its base classes. We can’t write code inside a mixin that makes assumptions on any of these. This may sound obvious and even more so unrelated to our current problem. But think about it. We are essentially writing code into a box whose surrounding we know nothing of. How could we then get something into the box from outside of it? Namely the &lt;code&gt;PLATFORM_ID&lt;/code&gt;InjectionToken's value or at least the means to obtain it ourselves inside the mixin?&lt;/p&gt;

&lt;p&gt;While reading this last paragraph you might have figured out what alternatives I’m going to show you.&lt;/p&gt;

&lt;p&gt;First of all, let’s address the elephant in the room. We want to obtain a value from the Angular DI system that is a string. Because it is a string we have to use the @Inject decorator or the Angular Injector. Furthermore, we couldn’t find the token’s value with an array.find on the received arguments.&lt;/p&gt;

&lt;p&gt;So what we can do is either wrap the token’s value into something we can find and look for that value in the arguments.&lt;/p&gt;

&lt;p&gt;That’s where mixin config classes come into play.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Inject, `PLATFORM_ID` } from "@angular/core";
import { isPlatformBrowser, isPlatformServer } from "@angular/common";

export class PlatformObserverMixinConfig {
  constructor(public platformId: tring) {}
}
export function platformObserverMixin&amp;lt;T extends Constructor&amp;lt;any&amp;gt;&amp;gt;(
  Base: T = class {} as any
) {
  class Mixin extends Base {
    /** ... */
    platformId: string;
    constructor(...args: any[]) {
      super(...args);
      this.platformId = args.find(
        (arg) =&amp;gt; arg instanceof PlatformObserverMixinConfig
      )?.platformId;
    }
  }
  return Mixin;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or alternatively, you can obtain the token’s value inside the mixin. To achieve this we have to expose the Angular Injector for our mixin. The idea here is to obtain the Injector in the child class where the mixin is applied and pass the injector itself to the mixin via the constructor. There you can use the same args.find technique but this time to find the injector. Once you have it, then you can use it’s .get method with the &lt;code&gt;PLATFORM_ID&lt;/code&gt;token.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Inject, Injector, `PLATFORM_ID` } from "@angular/core";
import { isPlatformBrowser, isPlatformServer } from "@angular/common";

export class PlatformObserverMixinConfig {
  constructor(public platformId: string) {}
}
export function platformObserverMixin&amp;lt;T extends Constructor&amp;lt;any&amp;gt;&amp;gt;(
  Base: T = class {} as any
) {
  class Mixin extends Base {
    /** ... */
    platformId: string;
    constructor(...args: any[]) {
      super(...args);
      this.platformId = args.find(
        (arg) =&amp;gt; arg instanceof Injector
      )?.get(`PLATFORM_ID`);
    }
  }
  return Mixin;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both of these techniques achieve the same thing, and they are really similar too, so whichever you use is up to your choice.&lt;/p&gt;

&lt;p&gt;Now that we have a mixin exposing the platform-related information for our components we only have to use this mixin on whatever components need it like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Component, Inject, `PLATFORM_ID` } from '@angular/core';
import { isPlatformBrowser, isPlatformServer } from '@angular/common';

@Component{
  selector: 'spp-root',
  styleSheetsUrls: ['./app.component.scss'],
  templateUrl: '/.app.component.html',
})
export class AppComponent extends platformObserverMixin() {
    /** ... */constructor(injector: Injector) {
      super(injector);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This implementation is also quite well thought out and could be widely used. But unfortunately, the criticism of the first idea applies here too. Dumb components would still have to touch the Angular DI system in some way to be able to supply the data needed by this mixin. Not to mention that neither this nor the service solution would make a nice and reusable solution in our .html files. Sure one more +ngIf isn’t the end of the world, but it’s just one more than what we’d like to add to our UIs.&lt;/p&gt;

&lt;p&gt;So in order to try and fix this problem let’s take a look at the 3rd option outlined previously.&lt;/p&gt;

&lt;h3&gt;
  
  
  Structural directive solution
&lt;/h3&gt;

&lt;p&gt;So far we’ve tried to achieve to desired behavior by placing the controlling logic outside of the UI of our app and applying it to the necessary parts. When in fact we could just invert the flow of control and let UI decide what it wants to show.&lt;/p&gt;

&lt;p&gt;Both previous solutions boiled down to getting the isPlatform boolean value and passing it to an &lt;code&gt;*ngIf&lt;/code&gt;. What if we had an &lt;code&gt;*ngIf&lt;/code&gt; that knew how to obtain the isPlatform boolean value by itself?&lt;/p&gt;

&lt;h3&gt;
  
  
  Enter &lt;code&gt;*ngRenderIn&lt;/code&gt; directive
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import {
  Directive,
  EmbeddedViewRef,
  Input,
  OnDestroy,
  OnInit,
  TemplateRef,
  ViewContainerRef,
} from "@angular/core";

import { EApplicationPlatform } from "../enums";
import { PlatformObserverService } from "../services";
@Directive({
  selector: "[ngRenderIn]",
})
export class NgRenderInDirective implements OnInit, OnDestroy {
   @Input("ngRenderIn") public platform!: EApplicationPlatform;
  @Input("ngRenderInElse") public alternativeTemplate?: TemplateRef&amp;lt;unknown&amp;gt;;
  protected _embeddedView!: EmbeddedViewRef&amp;lt;unknown&amp;gt;;
  constructor(
    protected readonly vcr: ViewContainerRef,
    protected readonly templateRef: TemplateRef&amp;lt;unknown&amp;gt;,
    protected readonly platformObserver: PlatformObserverService
  ) {}
  public ngOnInit(): void {
    if (this.platformObserver.platformID === this.platform) {
      this._embeddedView = this.vcr.createEmbeddedView(this.templateRef);
    } else if (this.alternativeTemplate) {
      this._embeddedView = this.vcr.createEmbeddedView(
        this.alternativeTemplate
      );
    }
  }
  public ngOnDestroy(): void {
    if (!this._embeddedView.destroyed) {
      this._embeddedView.destroy();
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So what’s going on here?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We create a directive that injects the ViewContainerRef and TemplateRef providers to fulfill the basics *ngIf functionality.&lt;/li&gt;
&lt;li&gt;We have two inputs:&lt;/li&gt;
&lt;li&gt;One to specify in which platform we want to render the directive’s template&lt;/li&gt;
&lt;li&gt;And another one to optionally render a different template. Just to align our directive’s usage with the built-in *ngIf directive.&lt;/li&gt;
&lt;li&gt;We use the directive’s ngOnInit lifecycle hook to do the platform check and display the directive’s default template if the condition is true or the alternative template if there’s one.&lt;/li&gt;
&lt;li&gt;We also implement the ngOnDestroy hook to clean the rendered template from the DOM when the directive’s destroyed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A few additional things of note. You may wonder where’s the logic from the directive to obtain the platform details. It’s inside the &lt;code&gt;PlatformObserverService&lt;/code&gt;which is injected in the directive's constructor. It's almost identical to what we saw in the @injectable solution so I'm not going to show it again here. Also, we have a helper enum &lt;code&gt;EApplicationPlatform&lt;/code&gt;used as the type of the main @Input of the directive. This aims to ease the usage when of the directive. And contains the available platform values, that you'd expect.&lt;/p&gt;

&lt;p&gt;Let’s see how it’d be used in our UIs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Component, Inject, `PLATFORM_ID` } from '@angular/core';
import { isPlatformBrowser, isPlatformServer } from '@angular/common';

@Component{
  selector: 'app-root',
  styleSheetsUrls: ['./app.component.scss'],
  templateUrl: '/.app.component.html',
})
export class AppComponent extends platformObserverMixin() {
    EApplicationPlatform = EApplicationPlatform;
    /** ... */
}
&amp;lt;3rd-party-photo-gallery
  *ngRenderIn="EApplicationPlatform.Browser"&amp;gt;
&amp;lt;/3rd-party-photo-gallery&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This looks quite clean if you ask me.&lt;/p&gt;

&lt;p&gt;We adhere to SRP, the participating classes and files didn’t become cluttered and the actual logic is right where it has to be in the component .html. Not to mention it’s well readable thanks to the choice of directive’s name.&lt;/p&gt;

&lt;p&gt;Ah yes, but there’s still one more thing we could improve on. Do you see what I refer to?&lt;/p&gt;

&lt;p&gt;Why do we exactly have to add even this one line of enum property definition in our component .ts file? Wouldn’t it be nice if could get rid of even this boilerplate? Good news! We can.&lt;/p&gt;

&lt;h3&gt;
  
  
  Directive sub-classing
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;*ngRenderIn&lt;/code&gt; directive shown above requires instruction from outside about which platform it should render its content in. What if we applied the inversion of control one more time and give all the control to the directive?&lt;/p&gt;

&lt;p&gt;For this, we have to make the directive aware of the instruction of the target platform. In fact, it wouldn’t just be aware of it. It would be the one that gives the instruction. Fine fine, but how one directive’s going to hold more than one instruction, and how the consuming component going to control it? It won’t! Remember? We are inverting the flow of control.&lt;/p&gt;

&lt;p&gt;The directive is the instruction itself so we need more than one directive to have multiple choices of instructions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Directive, Input, TemplateRef } from "@angular/core";

import { EApplicationPlatform } from "../enums";

@Directive({
  selector: "[ngRenderInBrowser]",
})
export class NgRenderInBrowserDirective extends NgRenderInDirective {
  @Input("ngRenderIn")public override readonly platform = EApplicationPlatform.Browser;

  @Input("ngRenderInBrowserElse")public override alternativeTemplate?: TemplateRef&amp;lt;unknown&amp;gt;;
}

@Directive({
  selector: "[ngRenderInServer]",
})
export class NgRenderInServerDirective extends NgRenderInDirective {
  @Input("ngRenderIn")public override readonly platform = EApplicationPlatform.Server;

  @Input("ngRenderInServerElse")public override alternativeTemplate?: TemplateRef&amp;lt;unknown&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we have one directive for each instruction of platform choice: browser and server.&lt;/p&gt;

&lt;p&gt;Both directives extend *ngRenderIn directive, so their implementations can be very lean.&lt;/p&gt;

&lt;p&gt;They each do two main things: Supply a default value for the &lt;code&gt;*ngRenderIn&lt;/code&gt; input of the base directive class, thereby defining their own instruction. And redefine their alternativeTemplate Input's binding name to their own selector name. This way you can supply an else template for both of them using the Angular micro syntax like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;3rd-party-photo-gallery
  *ngRenderInBrowser="else ServerTpl"&amp;gt;
&amp;lt;/3rd-party-photo-gallery&amp;gt;

&amp;lt;ng-template #ServerTpl&amp;gt;
  This is rendered in SSR mode
&amp;lt;/ng-template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Wrapping up
&lt;/h3&gt;

&lt;p&gt;It’s been a long journey up until here, but we managed to cut down on UI complexity and the amount of code we have to write to be able to define different templates for SSR and browser modes. As you saw there are multiple options available to solve this issue, however as I’ve implied before I do think that this final one is the most robust and elegant if I can say so myself. Now, after all this, you might be thinking to yourself: Alright, pretty neat. But how could I use this solution myself?&lt;/p&gt;

&lt;p&gt;Indeed, there have been numerous code examples throughout this article but it’d be an unpleasant task to extract them all into your own codebase. Lucky for you then, we’ve already done the heavy lifting for you. Me and my team over at &lt;a href="https://adroitgroup.io/"&gt;@Adroit Group&lt;/a&gt; have been working on a utility library for Angular full of useful stuff. Including, of course, the &lt;code&gt;**ngRenderIn&lt;/code&gt; directive I've introduced to you today.&lt;/p&gt;

&lt;p&gt;So if this directive or the library, which we’ll certainly write more about soon, has sparked your interest, you can head on over to &lt;a href="https://www.npmjs.com/package/@adroit-group/ng-utils"&gt;NPM &lt;/a&gt;or &lt;a href="https://github.com/Adroit-Group/ng-tools"&gt;Github &lt;/a&gt;to take a look or even download and use it. 📚👀&lt;/p&gt;

&lt;p&gt;I’d like to thank you for your time and attention in reading this article.&lt;/p&gt;

&lt;p&gt;I was your tour guide Jonatán Ferenczfi, Frontend tech lead @Adroit Group, Angular bro, and practicing coffee addict. ☕&lt;/p&gt;

&lt;p&gt;Until next time 👋&lt;/p&gt;

&lt;p&gt;Originally published at &lt;a href="https://adroitgroup.io/blog/conditional-ssr-templates-made-easy"&gt;adroitgroup.io&lt;/a&gt; and written by &lt;a href="https://medium.com/@jonatanferenczfi"&gt;Jonatan Ferenczfi&lt;/a&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>serversiderender</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>A complete guide to Flutter testing</title>
      <dc:creator>Eduard Tar</dc:creator>
      <pubDate>Thu, 11 May 2023 13:50:17 +0000</pubDate>
      <link>https://dev.to/adroitgroup/a-complete-guide-to-flutter-testing-2iid</link>
      <guid>https://dev.to/adroitgroup/a-complete-guide-to-flutter-testing-2iid</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fey94qvc2rkj7qhvr4zep.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fey94qvc2rkj7qhvr4zep.png" alt="Image description" width="720" height="203"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Flutter allows you to write applications for Android, iOS and Windows in less time. But in order to do this, you’re creating on-screen elements that live inside a real device environment. That means you will need tests to ensure everything works properly. What are the different types of tests used in Flutter? How are they used? This article answers these questions.&lt;/p&gt;

&lt;p&gt;This article outlines the testing process in Flutter. It demonstrates how to write and run unit tests and widget tests in Flutter.&lt;/p&gt;

&lt;p&gt;It highlights the importance of testing and provides tips and best practices to ensure tests are effective and provide meaningful results.&lt;/p&gt;

&lt;p&gt;The overall message is that testing is a key part of the development process in Flutter and should be given proper attention to ensure the quality and stability of apps.&lt;/p&gt;

&lt;h2&gt;
  
  
  Type of tests
&lt;/h2&gt;

&lt;p&gt;These are the type of tests used in flutter projects:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Unit test&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tests a single function, method or class&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Widget test (Component test)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tests a single widget&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Integration test&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tests a complete app or a large part of an app&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frsaxktk926ttjvxh8k35.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frsaxktk926ttjvxh8k35.png" alt="Image description" width="720" height="209"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Well-tested apps have many unit &amp;amp; widget tests and an integration test for every important use case.&lt;/p&gt;

&lt;p&gt;Unit and widget tests are tracked by CodeCoverage, a percentage measure of the degree to which the source code of a program is executed when a particular test suite run.&lt;/p&gt;

&lt;h3&gt;
  
  
  Main criteria of coverage:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Function coverage:&lt;/strong&gt;&lt;br&gt;
Has each function or subroutine in the program been called?&lt;/p&gt;

&lt;p&gt;**Statement coverage&lt;br&gt;
**Has each statement in the program been executed?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Edge coverage&lt;/strong&gt;&lt;br&gt;
Has every edge in the control-flow-graph been executed?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Branch coverage (edge subset)&lt;/strong&gt;&lt;br&gt;
Has each branch of each control structure been executed? eg.: if / else&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Condition coverage&lt;/strong&gt;&lt;br&gt;
Has each boolean sub-expression evaluated both to true and false?&lt;/p&gt;
&lt;h2&gt;
  
  
  Code Coverage in general
&lt;/h2&gt;

&lt;p&gt;Example function with coverage descriptions&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int foo (int x, int y) {
  int z = 0;
  if ((x &amp;gt; 0) &amp;amp;&amp;amp; (y &amp;gt; 0)) {
    z = x;
  }
  return z;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Function coverage:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Satisfied if the function foo is executed at least once&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Statement coverage:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Satisfied if every line in this function is executed, including z = x, this can be achieved by testing for foo(1,1)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Branch coverage:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Satisfied if every possibility of the inner branches is executed (if evals to true or false), this can be achieved by testing for foo(1,1) in which case every line is executed, and by testing for foo(0,1) because in that case (x&amp;gt;0) is evaluated false and that prevents the execution of z = x.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Condition coverage
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Satisfied if every combination of the conditions is executed, this can be achieved by testing for all 3 cases: foo(1,0) foo(0,1) foo(1,1) .&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the first case x&amp;gt;0 is evaluated true, while in the second is evaluated false&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the first case y&amp;gt;0 is evaluated false, in the second case its not evaluated because of lazy-evaluation, in the third case its evaluated true.&lt;br&gt;
More info on &lt;a href="https://en.wikipedia.org/wiki/Code_coverage" rel="noopener noreferrer"&gt;code coverage&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Flutter coverage
&lt;/h2&gt;

&lt;p&gt;You can create a coverage report for Flutter (dart), by running the &lt;code&gt;flutter test --coverage&lt;/code&gt; command in the project root. This will generate a &lt;code&gt;coverage/lcov&lt;/code&gt;.info file in the root folder. This contains the line and function coverage for the project.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Dart does NOT support function coverage by default and therefore its empty.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It also does NOT support branch coverage, which is a soon-to-be-deprecated method of coverage (due to being way too specific and over the top for higher-level languages, it is still in use for C and C++ and other low-level projects)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Coverage reports can be generated from this &lt;code&gt;lcov.info&lt;/code&gt; file via parsers, the most commonly used one is &lt;code&gt;genhtml&lt;/code&gt;, a perl parser written in the 90s.&lt;/p&gt;

&lt;p&gt;On linux and mac this can be downloaded via the system’s package manager, on Windows the easiest way is to use chocolatey to download a ported version. Since I’m on windows, I will demonstrate creating a visual report on this system. &lt;code&gt;genhtml&lt;/code&gt;'s location for me is in choco tools.&lt;/p&gt;

&lt;p&gt;Which for me is here: &lt;code&gt;C:\ProgramData\chocolatey\lib\lcov\tools\bin\genhtml&lt;/code&gt; Perl is scripting language, which also has to be installed via choco (or any other means, but I found this the easiest way).&lt;/p&gt;

&lt;p&gt;After you have installed Perl, genhtml and generated the lcov.info, you can run the following command in the project root.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;perl C:\ProgramData\chocolatey\lib\lcov\tools\bin\genhtml --branch-coverage -o coverage\html coverage\lcov.info&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The command structure is as follows: p&lt;code&gt;erl &amp;lt;script location&amp;gt; --branch-coverage -o &amp;lt;output location&amp;gt; &amp;lt;input location&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;--branch-coverage&lt;/code&gt; option generates branch coverage, it is useless for dart projects, But I included it for completeness.&lt;/p&gt;

&lt;p&gt;After running the command you will find the generated HTML in the &lt;code&gt;coverage/html&lt;/code&gt; folder (or whatever your output folder is). By clicking the &lt;code&gt;index.html&lt;/code&gt;, you will be greeted with a visual report like this one:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flts4ybjarsivi8ayg0xj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flts4ybjarsivi8ayg0xj.png" alt="Image description" width="720" height="304"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Unit tests in depth
&lt;/h2&gt;

&lt;p&gt;Unit tests ensure that the application is working correctly even after new features and modified functionality. They verify application behaviour by testing the behaviours of its building blocks such as functions, methods and classes.&lt;/p&gt;

&lt;p&gt;In flutter, every project includes a &lt;code&gt;test&lt;/code&gt;folder by default in the root of the project. You can create a unit test by creating a .dart file in this folder. It is advised to always end with &lt;code&gt;_test&lt;/code&gt; in their name, and my subjective opinion is that they should also be grouped by &lt;code&gt;type and module&lt;/code&gt;, such a file structure would look like as such: &lt;code&gt;/test/unit/auth/user_test.dart&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Example unit test in Flutter:&lt;/p&gt;

&lt;p&gt;Source&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;enum CatState { SLEEPING, AWAKE }

class Cat {
  CatState state = CatState.AWAKE

  void sleep() =&amp;gt; state = CatState.SLEEPING;
  void wake() =&amp;gt; state = CatState.AWAKE;
}class Cat {
  CatState state = CatState.AWAKE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Test&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Import the test package and Cat class
import 'package:cat_app/cat.dart';
import 'package:test/test.dart';

void main() {
  test('Cat should be sleeping', () {
    final cat = Cat();

    cat.sleep();

    expect(cat.state, CatState.SLEEPING);
  });

  test('Cat should not change state after waking twice in a row', () {
    final cat = Cat();

 // It is also important to know the cat is awake by default. (on construction)
    cat.wake();
    cat.wake();

    expect(cat.state, CatState.AWAKE);
  });

  test('Cat should be awake by default', () {
    final cat = Cat();

    expect(cat.state, CatState.AWAKE);
  });
}    cat.sleep();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Similar tests can (&lt;strong&gt;and should&lt;/strong&gt;) also be &lt;strong&gt;&lt;em&gt;grouped&lt;/em&gt;&lt;/strong&gt;, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Import the test package and Cat class
import 'package:cat_app/cat.dart';
import 'package:test/test.dart';

void main() {
    group('Cat tests', () {
      test('Cat should be sleeping', () {
        final cat = Cat();

        cat.sleep();

        expect(cat.state, CatState.SLEEPING);
      });

      test('Cat should not change state after waking twice in a row', () {
        final cat = Cat();

     // It is also important to know the cat is awake by default. (on construction)
        cat.wake();
        cat.wake();

        expect(cat.state, CatState.AWAKE);
      });

      test('Cat should be awake by default', () {
        final cat = Cat();

        expect(cat.state, CatState.AWAKE);
      });
    })
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tests can be run with the command flutter test Individual tests can be run by providing the file name, in this case, it would be: &lt;code&gt;flutter test test/unit/cat_test.dart&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Sometimes you require the same instance of a class over and over in multiple tests. In these cases, you can either use &lt;strong&gt;setUp&lt;/strong&gt; if you need a new instance every time or &lt;strong&gt;setUpAll **if you need continuous testing. An example using the **Cat **class and **setUpAll()&lt;/strong&gt;. Since the cat is instantiated once, changes will persist to it through tests (unless overridden). (Obviously, these functions can be used for anything else that fits their narrative, class instantiation is just one of them)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void main() {
 group('Cat tests', () {
   late final cat;

   setUpAll(() async {
    cat = Cat();
   });

   test('Cat should be awake by default', () {
  expect(cat.state, CatState.AWAKE); // Cat is awake by defualt
   });

   test('Cat should be sleeping', () {
     cat.sleep();

     expect(cat.state, CatState.SLEEPING); // sleep was called so the Cat sleeps
   });

   test('Cat should not change state after waking twice in a row', () {
  // cat is still sleeping from previous test
  expect(cat.state, CatState.SLEEPING); 

  cat.wake();
  cat.wake();

  expect(cat.state, CatState.AWAKE); // cat is now awake
   });
 })
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These tests will all pass.&lt;/p&gt;

&lt;p&gt;In the following case, we’ll be using setUp which gets called before **EVERY **test. (we removed the final keyword)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void main() {
 group('Cat tests', () {
   late Cat cat;

   setUp(() async {
    cat = Cat();
   });

   test('Cat should be awake by default', () {
  expect(cat.state, CatState.AWAKE); // Cat is awake by defualt
   });

   test('Cat should be sleeping', () {
     cat.sleep();

     expect(cat.state, CatState.SLEEPING); // sleep was called so the Cat sleeps
   });

   test('Cat should not change state after waking twice in a row', () {
  // cat is still sleeping from previous test
  expect(cat.state, CatState.SLEEPING); 

  cat.wake();
  cat.wake();

  expect(cat.state, CatState.AWAKE); // cat is now awake
   });
 })
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first 2 tests will pass, but the third one will fail because a new cat is instantiated before every test and the default state of the cat is &lt;strong&gt;AWAKE&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Both &lt;strong&gt;setUp **and **setUpAll **functions are **SCOPED&lt;/strong&gt;, and only apply to their respective group, unless declared in the main function.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mocking
&lt;/h3&gt;

&lt;p&gt;In some cases, you will want to test functions and classes that depend on web servers or databases. In these cases, you want to mock the medium you use to fetch or retrieve that data. In the case of a webserver you would try to mock the http.Client, an example of this can be found in the official docs &lt;a href="https://docs.flutter.dev/cookbook/testing/unit/mocking" rel="noopener noreferrer"&gt;Mocking the http.Client&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Mocking Local Auth (with mocktail)
&lt;/h4&gt;

&lt;p&gt;You can mock any class with mocktail, by simply extending the Mock class and implementing the class you want to mock. In this example, we will be mocking the LocalAuthentication class. Creating the mock class is as simple as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class MockLocalAuthentication extends Mock implements LocalAuthentication {}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s create a new unit test that declares a localAuth instance by instantiating the mock class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void main() {
  late final LocalAuthentication localAuth;

  // Runs before the first test
  setUpAll(() async {
 TestWidgetsFlutterBinding.ensureInitialized(); // required for local auth
 localAuth = MockLocalAuthentication();
  });
}  // Runs before the first test
  setUpAll(() async {
    TestWidgetsFlutterBinding.ensureInitialized(); // required for local auth
    localAuth = MockLocalAuthentication();
  });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In mocktail, we can detect when a function is called and react appropriately by using the when constant and a callback to the function. If the function has parameters they can be mocked as well using the any() method which produces mock data for the argument. When using named parameters, you have to provide the name of the parameter as well.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//...
 test('Authentication is successful', () async {
  when(() =&amp;gt; localAuth.authenticate(
            localizedReason: any(named: 'localizedReason'),
            authMessages: any(named: 'authMessages'),
            options: any(named: 'options'),
          )).thenAnswer(
         (_) async =&amp;gt; true,
        );

  expect(await localAuth.authenticate(), true);
 });
//...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This test will fail though because the options named parameter requires a custom type called &lt;strong&gt;AuthenticationOptions&lt;/strong&gt;, which is not supported by default by mocktail. &lt;strong&gt;AuthMessages **can be an empty array, even though it would require custom types. We can create a fallback value for any type by calling **registerFallbackValue&lt;/strong&gt;(&lt;strong&gt;Type&lt;/strong&gt;)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;etUpAll(() async {
        //...
        registerFallbackValue(const AuthenticationOptions());
    });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The fallback value is not reset by calling the reset() function. (which by default resets stub information like the when() function)&lt;/p&gt;

&lt;p&gt;By providing a fallback value the test will successfully pass.&lt;/p&gt;

&lt;h2&gt;
  
  
  Widget tests in depth
&lt;/h2&gt;

&lt;p&gt;Widget tests are done similarly to unit tests, except instead of the test dev_dependency, we use tools from the flutter_test package, this ships with the Flutter SDK, and should be included in every new flutter project (2.0+)&lt;/p&gt;

&lt;p&gt;_The code is from the official docs. Included for demonstrational purposes.&lt;br&gt;
_&lt;br&gt;
Source&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class MyWidget extends StatelessWidget {
  const MyWidget({
    super.key,
    required this.title,
    required this.message,
  });

  final String title;
  final String message;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: Scaffold(
        appBar: AppBar(
          title: Text(title),
        ),
        body: Center(
          child: Text(message),
        ),
      ),
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Test File&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void main() {
  testWidgets('MyWidget has a title and message', (WidgetTester tester) async {
    await tester.pumpWidget(const MyWidget(title: 'T', message: 'M'));

 // Create finders
 final titleFinder = find.text('T');
 final messageFinder = find.text('M');

 // Use the `findsOneWidget` matcher provided by flutter_test to verify that the 
 // Text widgets appear exactly once in the widget tree.
 expect(titleFinder, findsOneWidget);
 expect(messageFinder, findsOneWidget);
  });
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;**WidgetTester **is provided by the flutter_test package.&lt;/p&gt;

&lt;p&gt;The **pumpWidget **method builds a widget. (calls the build() function)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;In the test environment, rebuilds happen when called, instead of automatically. For example, if a button is called that calls setState() it will rerender in a live application but will not in the test environment. You have to call &lt;strong&gt;tester.pump(Duration.zero)&lt;/strong&gt; to advance by frame, or you can call it with a duration larger than zero to advance the clock by a certain amount.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can also call &lt;strong&gt;pumpAndSettle&lt;/strong&gt;, to repeatedly call until there are no frames scheduled, this is especially useful when testing navigation.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;find&lt;/code&gt;constant (Finder) is available in the global test context.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;expect&lt;/code&gt;constant (Assertion Control) is available in the global test context.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;So is every matcher. Matchers are the expected arbitrary values such as findsOneWidget&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;More matches can be found in the &lt;a href="https://docs.flutter.dev/cookbook/testing/widget/introduction#notes-about-the-pump-methods" rel="noopener noreferrer"&gt;official docs&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Running this test will result in a successful case, as we deliberately gave T &amp;amp; M values to the widget constructor.&lt;/p&gt;

&lt;h3&gt;
  
  
  Finding Widgets with different finders.
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;testWidgets('finds a Text widget', (tester) async {
  // Build an App with a Text widget that displays the letter 'H'.
  await tester.pumpWidget(const MaterialApp(
    home: Scaffold(
      body: Text('H'),
    ),
  ));

  // Find a widget that displays the letter 'H'.
  expect(find.text('H'), findsOneWidget);
  expect(find.byType(Text), findsOneWidget);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The **byType **function has one parameter which is the class of the Widget, that you want to find.&lt;/p&gt;

&lt;h3&gt;
  
  
  Finding a Widget by Key
&lt;/h3&gt;

&lt;p&gt;Sometimes there are multiple instances of a widget, for example, a List, in this case, you can look for it by key.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;testWidgets('finds a widget using a Key', (tester) async {
  // Define the test key.
  const testKey = Key('K');

  // Build a MaterialApp with the testKey.
  await tester.pumpWidget(MaterialApp(key: testKey, home: Container()));

  // Find the MaterialApp widget using the testKey.
  expect(find.byKey(testKey), findsOneWidget);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Finding a Widget by instance
&lt;/h3&gt;

&lt;p&gt;Sometimes you want to follow a certain widget, and after you performed your actions on it you want to find the exact instance. You can do this by keeping a reference for it in context.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;testWidgets('finds a specific instance', (tester) async {
  const childWidget = Padding(padding: EdgeInsets.zero);

  // Provide the childWidget to the Container.
  await tester.pumpWidget(Container(child: childWidget));

  // Search for the childWidget in the tree and verify it exists.
  expect(find.byWidget(childWidget), findsOneWidget);
});  // Provide the childWidget to the Container.await tester.pumpWidget(Container(child: childWidget));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are the most commonly used finders, but there are quite a lot more. You can find the list of all finders and extra info &lt;a href="https://api.flutter.dev/flutter/flutter_test/CommonFinders-class.html" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Testing scrolling inside a widget
&lt;/h4&gt;

&lt;p&gt;This is a less common but still quite frequent problem, it has a decent description on the official site so I will just link that &lt;a href="https://docs.flutter.dev/cookbook/testing/widget/scrolling" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Testing tap, drag and inputs&lt;br&gt;
Functions from the &lt;code&gt;WidgetTester&lt;/code&gt;class, such as&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;*&lt;em&gt;enterText *&lt;/em&gt;(enters text into a widget found by a finder)&lt;/li&gt;
&lt;li&gt;*&lt;em&gt;tap *&lt;/em&gt;(taps a widget found by a finder)&lt;/li&gt;
&lt;li&gt;*&lt;em&gt;drag *&lt;/em&gt;(drags a widget found by a finder) handles such tests, they are self-explanatory and I could not explain it any better than the docs do
. You can read more &lt;a href="https://docs.flutter.dev/cookbook/testing/widget/tap-drag" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Package tests&lt;br&gt;
In some cases, we might test packages that use native components to function, such as camera functions or platform native requests (like android intents). Flutter packages communicate with their native counterpart using platform channels, specifically method channels to call, well methods. (You can read more about platform channels &lt;a href="https://docs.flutter.dev/development/platform-integration/platform-channels" rel="noopener noreferrer"&gt;here&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;In test cases such channels are not instantiated as tests are platform-independent (in most cases), therefore we have to simulate these method calls by declaring our mock channels.&lt;/p&gt;

&lt;p&gt;To mock a method channel, you first need the channel’s name, which is unique across packages. To obtain this URL, usually you have to scrub through the files of the package. In most cases the file holding this information will be explicitly called “method_channel_config.dart”, but it can be also hard to find sometimes.&lt;/p&gt;

&lt;p&gt;In the following example, I’m going to mock the permission_handler package’s method channel to simulate a user granting or denying permission to an application. This package’s method channel is &lt;code&gt;flutter.baseflow.com/permissions/methods.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In my particular case, I want to override the package’s calls for permission requests. The method’s name is “&lt;strong&gt;requestPermissions&lt;/strong&gt;”, this I also found out from the source code of the package.&lt;/p&gt;

&lt;p&gt;We start by declaring a mock handler with the name I mentioned:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const MethodChannel(MethodChannels.PERMISSION_HANDLER)
      .setMockMethodCallHandler((MethodCall methodCall) async {
    if (methodCall.method == 'requestPermissions') {
      if ((methodCall.arguments as List).contains(Permission.camera.value)) {
        return {
          Permission.camera.value: PermissionStatus.granted.index,
        };
      }

      return {};
    }

    return null;
  });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We know that this “&lt;strong&gt;requestPermissions&lt;/strong&gt;” method has to return a Map type, which is basically a Map of the Permission id and the PermissionStatus index. In this instance I return, the granted status’s index, to which the application reacts as it was granted.&lt;/p&gt;

&lt;p&gt;You can declare a new mock call handler anytime and it will override the previous one (if you have multiple with the same name).&lt;/p&gt;

&lt;p&gt;We can now proceed to test that the package correctly calls our mocked handler.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//...
test('Permission handler calls mock handler', () async {
    final status =  await Permission.camera.request();
    expect(status, PermissionStatus.granted);
});
//...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This method of mocking works even when the widget calls it, not just by us directly calling the function, therefor is a necessity for widget tests.&lt;/p&gt;

&lt;h4&gt;
  
  
  Testing Widget properties.
&lt;/h4&gt;

&lt;p&gt;In some cases we change UI after some logic, we are going to demonstrate this by declaring a container with no background color and a button which when clicked changes the background color of the container to blue and we will verify that.&lt;/p&gt;

&lt;p&gt;Widget under test (WUT)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class TestRandomWidget extends StatefulWidget {
  const TestRandomWidget({super.key});

  @override
  State&amp;lt;TestRandomWidget&amp;gt; createState() =&amp;gt; _TestRandomWidgetState();
}

class _TestRandomWidgetState extends State&amp;lt;TestRandomWidget&amp;gt; {
  bool buttonClicked = false;

  @override
  Widget build(BuildContext context) {
    return Column(
    children: [
     const TestSquare(active: buttonClicked),
     OutlinedButton(
    onPressed: () {
     setState(() {
      buttonClicked = true;
     });
    },
    child: Text('Let it be blue'),
     ),
    ]
   );
  }
}

class TestSquare extends StatelessWidget {
  const TestSquare({
    Key? key,
    required this.active,
  }) : super(key: key);

  final bool active;

  @override
  Widget build(BuildContext context) {
   return Container(
    width: 20,
    height: 20,
    color: active ? Colors.blue : Colors.red,
   )
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Very simple widget for the purpose of this demonstration now let’s render it in a test.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;testWidgets((WidgetTester tester) async {
 await tester.pumpWidget(const MaterialApp(
     home: Scaffold(
       body: const TestRandomWidget(),
     ),
 ));

 // lets tap the button by type, we know there is only one
 await tester.tap(find.byType(OutlinedButton));

 await tester.pumpAndSettle(); // wait for the state change and last frame in schedule

 // find a TestSquare class by type which we know only one exists, typeMatch it with isA&amp;lt;TestSquare&amp;gt;()
 expect(
  find.byType(TestSquare),
  isA&amp;lt;TestSquare&amp;gt;().having( // A TestSquare class that
   p0 =&amp;gt; p0.active, // has the active property
   'active',  // this is just a diagnostical description, should always be the name of the property.
   true, // with the value 'true'
  ),
 );
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way we know that **TestSquare **was rendered with the active property true after the button was clicked.&lt;/p&gt;

&lt;h4&gt;
  
  
  Integration tests
&lt;/h4&gt;

&lt;p&gt;Integration tests require a complete application or a complex logic flow.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Usually demonstrates every intended use of the application or feature by navigating through the application from start to finish or until the feature is considered to have fulfilled its purpose.&lt;/li&gt;
&lt;li&gt;Very project/feature specific, and is based on the combination of unit and widget tests working together to complete the flow.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Wrap-up
&lt;/h2&gt;

&lt;p&gt;Now that you have an idea of how to write and run unit tests and widget tests in Flutter, you should be more comfortable with the stability of your application(s).&lt;/p&gt;

&lt;p&gt;Testing is only a daring task if you overcomplicate it with tech jargon, in reality, it's more about ensuring whatever you wrote will work in every or at least most scenarios.&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;Sources:&lt;br&gt;
*&lt;/em&gt;&lt;br&gt;
&lt;a href="https://en.wikipedia.org/wiki/Code_coverage" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/Code_coverage&lt;br&gt;
&lt;/a&gt;&lt;a href="https://en.wikipedia.org/wiki/Statement_(computer_science)" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/Statement_(computer_science)&lt;/a&gt;&lt;br&gt;
&lt;a href="https://docs.flutter.dev/cookbook/testing" rel="noopener noreferrer"&gt;https://docs.flutter.dev/cookbook/testing&lt;br&gt;
&lt;/a&gt;&lt;a href="https://pub.dev/packages/mocktail" rel="noopener noreferrer"&gt;https://pub.dev/packages/mocktail&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Other interesting documents:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.flutter.dev/testing/debugging" rel="noopener noreferrer"&gt;https://docs.flutter.dev/testing/debugging&lt;br&gt;
&lt;/a&gt;&lt;a href="https://docs.flutter.dev/perf/best-practices" rel="noopener noreferrer"&gt;https://docs.flutter.dev/perf/best-practices&lt;/a&gt;&lt;a href="https://docs.flutter.dev/resources/platform-adaptations" rel="noopener noreferrer"&gt;https://docs.flutter.dev/resources/platform-adaptations&lt;/a&gt;&lt;br&gt;
Originally published at &lt;a href="https://adroitgroup.io/blog/a-complete-guide-to-flutter-testing" rel="noopener noreferrer"&gt;adroitgroup.io &lt;/a&gt;and written by &lt;a href="https://medium.com/@attila.kovats?source=post_page-----57e99465098f--------------------------------" rel="noopener noreferrer"&gt;Attila Kováts&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>testing</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>React vs Angular vs Vue.js — Which one should you choose?</title>
      <dc:creator>Eduard Tar</dc:creator>
      <pubDate>Thu, 11 May 2023 12:57:26 +0000</pubDate>
      <link>https://dev.to/adroitgroup/react-vs-angular-vs-vuejs-which-one-should-you-choose-gf7</link>
      <guid>https://dev.to/adroitgroup/react-vs-angular-vs-vuejs-which-one-should-you-choose-gf7</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhtdhjg5vvz8rc6l7lxfn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhtdhjg5vvz8rc6l7lxfn.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At the beginning of a new project, front-end developers must answer the following question: Which framework should I choose? What is the best framework for my needs? In this article, we will give you a brief overview of the most popular front-end frameworks and how to choose the one that best suits your needs. These frameworks are Angular, React, and Vue.js.&lt;/p&gt;

&lt;h2&gt;
  
  
  Angular vs React vs Vue
&lt;/h2&gt;

&lt;p&gt;With &lt;strong&gt;Angular&lt;/strong&gt;, you can quickly create a front-end application with lots of tools, components, and services. According to Angular’s website, Angular defines itself as:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“The modern web developer’s platform”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Google develops and maintains it but is not used by any of its most popular products, like Search or YouTube. Angular can be used to create single-page applications (SPAs), websites, hybrid applications, and mobile applications.&lt;/p&gt;

&lt;p&gt;Angular has been around for quite a few years, so it has been thoroughly tested, and you can use it on large-scale projects. Angular has a rich ecosystem with many tools that you can use to speed up your development process.&lt;/p&gt;

&lt;p&gt;Angular consists of a template, a class that defines the application logic, and metadata (decorators) in addition to a component’s template, metadata, and class. Angular uses the metadata to locate the components’ building blocks. Angular template syntax is available in HTML, as well as reactive data and multiple-element rendering.&lt;/p&gt;

&lt;p&gt;Services in Angular are used to delegate data-fetching and input-validation duties to components in addition to other things. The Angular framework isn’t enforced, but it’s highly suggested to structure apps as separate services, which are a distinct part of Angular applications.&lt;/p&gt;

&lt;p&gt;To get the most seamless experience, TypeScript is encouraged, but plain JavaScript is also supported.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;React is considered a UI library&lt;/strong&gt;. They define themselves as:&lt;br&gt;
_&lt;br&gt;
“A JavaScript library for building user interfaces”_&lt;/p&gt;

&lt;p&gt;It was created by Facebook and is a front-end library that has become very popular recently. Because React doesn’t enforce a certain project structure, it can be used as a UI library to generate elements, and it’s not technically a framework. React apps are made up of React Elements, the smallest units.&lt;/p&gt;

&lt;p&gt;The React DOM ensures that they are efficiently updated whenever a change occurs. They are more powerful than standard DOM elements because they are updated more efficiently. Components are larger building blocks that you may use throughout the application.&lt;/p&gt;

&lt;p&gt;Props are inputs that are provided to elements which are then displayed to the user. You may create elements that combine HTML, JavaScript, and JavaScript XML with the React JavaScript API. Many developers prefer JSX as it is more understandable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lastly, Vue.js is, according to its site:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“A progressive JavaScript framework”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It was created by a Chinese engineer Evan You who has also worked on Angular. Vue is relatively new, and it is growing rapidly in popularity. The Vue.js core library focuses on the View layer only. It’s called a progressive framework because you can extend its functionality with official and third-party packages, such as Vue Router or Vuex, to turn it into an actual framework.&lt;/p&gt;

&lt;p&gt;Although Vue is not strictly associated with the MVVM (Model-View-ViewModel) pattern, its design was partly inspired by it. With Vue, you’ll be working mostly on the ViewModel layer, to make sure that the application data is processed in a way that allows the framework to render an up-to-date View.&lt;/p&gt;

&lt;p&gt;Vue’s templating syntax lets you create View components, and it combines familiar HTML with special directives and features. This templating syntax is preferred, even though raw JavaScript and JSX are also supported.&lt;/p&gt;

&lt;p&gt;Components in Vue are small, self-contained, and can be reused throughout the application. Single File Components (SFCs) with the .vue extension contain HTML, CSS, and JavaScript so that all relevant code resides in one file.&lt;/p&gt;

&lt;p&gt;SFCs are the recommended way to organize code in Vue.js projects, especially larger ones. Tools such as Webpack or Browserify are required to transpile SFCs into working JavaScript code.&lt;/p&gt;

&lt;p&gt;In Vue.js projects, SFCs are the preferred method for organizing code. To turn SFCs into functioning JavaScript code, you must use Webpack or Browserify, among other tools.&lt;/p&gt;

&lt;p&gt;These three frameworks have a variety of similarities, including a component-based architecture and ease of UI feature production. React and Vue.js are primarily declarative, and although Angular is also declarative, it is really more imperative. Despite some more distinctions in structure, architecture, and operation, let’s take a look at them all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ecosystem
&lt;/h2&gt;

&lt;p&gt;Using open-source packages can save you a lot of time when developing applications. In addition to being battle-tested, they tend to have better functionality than custom-made packages and components.&lt;/p&gt;

&lt;p&gt;Angular:&lt;br&gt;
There are many ready-to-use components that can be imported from other projects, but Angular also offers a wide variety of official components in the Angular Material project offering Material Design components for Angular applications.&lt;/p&gt;

&lt;p&gt;Cross-platform mobile applications can be created in Angular using NativeScript, which, though offering Vue support, has more comprehensive Angular support.&lt;/p&gt;

&lt;p&gt;Angular is also part of the MEAN stack that combines Angular with MongoDB, ExpressJS, and NodeJS. Like the MERN stack, it uses JavaScript for both front-end and back-end development.&lt;/p&gt;

&lt;h2&gt;
  
  
  React
&lt;/h2&gt;

&lt;p&gt;:&lt;br&gt;
Many front-end applications use global state management to store information such as who is logged in and other user settings.&lt;/p&gt;

&lt;p&gt;Redux is the most popular JavaScript state management project, and most developers use the official React bindings for Redux, which are maintained by the Redux team.&lt;/p&gt;

&lt;p&gt;React is extremely popular, so finding input components and ready-to-use elements is very easy. They are all just a Google or GitHub search away.&lt;/p&gt;

&lt;p&gt;The React ecosystem also includes React Native, which allows you to build native iOS and Android applications from a single codebase written in React. Therefore, React can be a great choice for building mobile applications using web technologies.&lt;/p&gt;

&lt;p&gt;React is part of the MERN stack with MongoDB, ExpressJS, and NodeJS. The great thing about this combination is that a single language — JavaScript — powers the whole application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Vue
&lt;/h2&gt;

&lt;p&gt;:&lt;br&gt;
Even though Redux can be used in Vue, there are no official bindings. However, this should not concern you because Vuex is the official state management library created specifically for Vue applications. In addition to integrating very well with Vue, it is easy to debug using Vue’s developer tools.&lt;/p&gt;

&lt;p&gt;In the early days of Vue, it was harder to find ready-to-use components. However, since the community has grown, there is now a wide range of input components and advanced elements available to use, which can speed up your development.&lt;/p&gt;

&lt;p&gt;For mobile app development, there is an up-and-coming project called Weex. Weex is being developed and used by Alibaba, but it is not as mature or powerful as React Native. Additionally, since the project is developed and used more in China, it can be harder to find documentation and solutions to issues in English.&lt;/p&gt;

&lt;p&gt;Vue integrates well with Laravel, and that is why they are often used together. Laravel offers complete JavaScript and CSS scaffolding to enable the use of Vue in new projects.&lt;/p&gt;

&lt;h3&gt;
  
  
  Common Technologies
&lt;/h3&gt;

&lt;p&gt;Angular, React, and Vue can be used to create PWAs (Progressive Web Apps).&lt;/p&gt;

&lt;p&gt;PWAs are not mobile apps but web apps that smartphone users can add as shortcuts to their home screens. They have a similar look and feel to native mobile apps.&lt;/p&gt;

&lt;p&gt;Each framework has access to premium templates and pre-made applications, though Angular and React have more premium options than Vue.&lt;/p&gt;

&lt;h3&gt;
  
  
  Performance
&lt;/h3&gt;

&lt;p&gt;When choosing a framework or library, you need to think about performance as well.&lt;/p&gt;

&lt;p&gt;In many cases, you won’t have to worry about performance, especially if you’re building a small project. However, the more a project grows in scope and complexity, performance can (and will) become a concern.&lt;/p&gt;

&lt;p&gt;It’s important to note that the quality of development and following best practices when it comes to web performance are more important than the choice of framework.&lt;/p&gt;

&lt;p&gt;But since there are some performance metrics and differences, I’ll look into them and explain how each could affect your development efforts.&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;JS Framework Benchmark:&lt;br&gt;
*&lt;/em&gt;&lt;br&gt;
According to the results of the JS Framework Benchmark, Vue.js is generally the fastest framework. Despite this, there isn’t much of a difference.&lt;/p&gt;

&lt;p&gt;There are three relevant actions here: selecting a row where React is a bit slower than the others; swapping rows where both Angular and React are much slower than Vue.js; and clearing rows where Angular is slowest.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkyksbruubf42wjsgxhf2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkyksbruubf42wjsgxhf2.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Perf Track:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Hundreds of thousands of websites are measured by Perf Track, but here we will focus on just a few of them (you can view the full results here: Angular, React, Vue.js).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzi9top7algw15ws8gwie.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzi9top7algw15ws8gwie.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Both React and Vue.js are noticeably faster than Angular when loading and presenting the first content (FCP) and the largest one (LCP).&lt;/p&gt;

&lt;p&gt;In terms of Cumulative Layout Shift (CLS), React has the most sites with a CSL below 0.1. Nevertheless, the results for Angular and Vue.js are worse, but not significantly.&lt;/p&gt;

&lt;p&gt;Regarding the time taken from a user’s first interaction with a site (FID), all frameworks bring good results.&lt;/p&gt;

&lt;p&gt;Finally, the time between the browser requests a page and the first byte of information from the server it is received (TTFB) is lower in Angular than in React and Vue.js, with React being the slowest framework.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;There are many factors to take into consideration when picking a front-end framework. The popularity of a certain framework is one of the key indicators, but not the only one.&lt;/p&gt;

&lt;p&gt;If you have vast quantities of dynamic data to display, Vue.js should be taken into strong consideration. If you aspire to create a rich user interface, React is a good choice. If you need to build a complex application, Angular would be your best bet. With that being said, it is important to choose the right tool for the given job.&lt;/p&gt;

&lt;p&gt;By taking into account the factors we have discussed in this article, you should be able to hand-pick the best framework for your needs.&lt;/p&gt;

&lt;p&gt;Originally published at &lt;a href="https://adroitgroup.io/blog/angular-vs-react-vs-vue" rel="noopener noreferrer"&gt;adroitgroup.io&lt;/a&gt; and written by &lt;a href="https://medium.com/@balazs.szabo.adroit" rel="noopener noreferrer"&gt;Balázs Szabó&lt;/a&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>vue</category>
      <category>react</category>
      <category>beginners</category>
    </item>
    <item>
      <title>What’s the Best OS for Developers: Mac vs Windows vs Linux</title>
      <dc:creator>Eduard Tar</dc:creator>
      <pubDate>Thu, 11 May 2023 12:35:46 +0000</pubDate>
      <link>https://dev.to/adroitgroup/whats-the-best-os-for-developers-mac-vs-windows-vs-linux-52kl</link>
      <guid>https://dev.to/adroitgroup/whats-the-best-os-for-developers-mac-vs-windows-vs-linux-52kl</guid>
      <description>&lt;p&gt;Whether you plan on developing mobile or web apps, games, or software, the right OS can be the difference between success and failure. In this guide, we’ll explore how developers can benefit from Mac, Windows, and Linux — each of which has unique advantages depending on your individual needs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2VcKIM7w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mjnccyforxl58awxch68.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2VcKIM7w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mjnccyforxl58awxch68.png" alt="Image description" width="800" height="305"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s the Best OS for Developers: Mac vs Windows vs Linux
&lt;/h2&gt;

&lt;p&gt;Whether you plan on developing mobile or web apps, games, or software, the right OS can be the difference between success and failure. In this guide, we’ll explore how developers can benefit from Mac, Windows, and Linux — each of which has unique advantages depending on your individual needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start by Identifying Your Needs.
&lt;/h2&gt;

&lt;p&gt;In order to decide which OS is the best for your development needs, you must first identify exactly what those needs are. Are you focusing on development for mobile apps? Do you want to create games or software? Maybe hardware development is more interesting to you. Different operating systems specialize in different aspects of development, so it’s important to be aware of all the possibilities before making a decision. Once you know exactly what type of development tasks you will be taking on, then it’s time to choose an OS.&lt;/p&gt;

&lt;p&gt;Here are the three main OS options available to developers: Linux, Mac OS, and Windows. Each has its own benefits and drawbacks. Linux is known for its customization capabilities, offering developers a more open-source platform than either Mac or Windows. However, Mac has its advantages when it comes to creating mobile apps as it includes features like Xcode which allows you to easily compile iOS and Android applications. Finally, Windows is the most widely used operating system for running games and software — though it does lack some of the customizability options offered by the other two platforms.&lt;/p&gt;

&lt;p&gt;So which is the best option for you? It really depends on your development needs and preferences. Take some time to consider what type of development tasks you want to take on and which features are most important to you. From there, you can make an informed decision that works best for your specific needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dive into the Different OS Features and Their Versions.
&lt;/h2&gt;

&lt;p&gt;When narrowing down your OS options you should be sure to take a look at the different features and version updates of each OS. For example, if you’re looking to use Mac OS, consider the differences between macOS Catalina and Big Sur. Alternatively, when considering Windows OS, become familiar with the benefits of Windows 10 and its various versions, such as Windows 10 Pro or Home Edition. Lastly, when it comes to Linux distributions like Ubuntu or Fedora, research their available versions for the latest developments and new features that will give you an advantage in your development tasks.&lt;/p&gt;

&lt;p&gt;Each OS comes with its set of tools and capabilities that can help simplify your development tasks. As a developer, you’ll want to be sure to pay attention to the more advanced options and commands because they will often be the most useful when developing applications. Consider things like using Git for version control, using SSH key-based authentication, or allowing access via Remote Desktop Protocol to speed up remote code testing and deployment. Each of these features can be used differently depending on the OS so it’s important to research what every platform has to offer before deciding which one is best for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Consider Platforms Compatibility and Development Tools.
&lt;/h2&gt;

&lt;p&gt;As you research the best OS for your development tasks, consider how well each platform works with different technologies and tools. For example, Mac OS and Linux are better suited to certain programming languages than Windows, whereas Windows would have better compatibility with .NET technology. Additionally, if your project requires cloud-based solutions and services, then look into which platforms are most integrated with cloud service providers’ tools. Making sure you select an OS that is compatible with the type of development work you need it for can not only make your workflow easier but also allow you to effectively use all of its features.&lt;/p&gt;

&lt;p&gt;In addition to compatibility, you should also consider the development tools that come with each OS. For example, Mac OS comes pre-installed with an integrated development environment (IDE) called Xcode which allows developers to create a wide range of applications and software. Similarly, Linux provides a suite of command line utilities and programming languages including Python, Ruby on Rails, and Perl allowing developers to quickly code from the shell. Windows also has a supportive developer community with plenty of IDE options such as Visual Studio for those involved in .NET Framework Development. Ultimately, whichever platform you choose may have more or fewer features depending on what type of development you need it for so do your research before selecting one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Analyze System Requirements and Cost Limits.
&lt;/h2&gt;

&lt;p&gt;Consider the hardware requirements to run and manage each system, such as the RAM and processor capabilities, before making a decision. Also, Macs have traditionally been expensive, so you will have to factor potential costs associated with different systems into your decision-making process. Be sure to research different options that lie within your cost limits but still offer the necessary features for what you need. With the wide variety of options available, there should be an OS solution fitting into your budget.&lt;/p&gt;

&lt;p&gt;Moreover, keep the system’s appropriateness in mind. Some systems are more capable of handling specific tasks than others. Often, developers use Macs for their work as they provide superior framework support. Windows machines offer reliable and effortless integration with numerous popular development tools while Linux offers open-source flexibility and customization options with a fraction of the burden on resources. Weigh each system’s pros and cons against your project’s needs to make an informed decision.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don’t Forget About Third-Party Applications Support Options.
&lt;/h2&gt;

&lt;p&gt;The OS you choose should provide the necessary components and capabilities to run and manage the third-party applications you plan to utilize. Not all applications are supported by every platform, so it’s essential to research if your programs of choice will work on the desired operating system. It is recommended that you check which options have received good ratings from users in third-party software testing reviews, as this method can help determine if an OS is a good fit for your development needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The goal is to ensure that you get the resources necessary for all development activities and have the option of utilizing multiple desktop environments with an OS that supports it. You should also ask yourself if the OS can be upscaled if the project grows bigger than initially expected. If you’re moving from Windows to Linux, consider working on a virtual machine to experience all of Linux’s goodness first-hand before committing fully. Ultimately, a careful review of features and services is required for making an informed decision about whether Mac, Windows, or Linux is best for your development project.&lt;/p&gt;

&lt;p&gt;Originally published at &lt;a href="https://adroitgroup.io/blog/whats-the-best-os-for-developers-mac-vs-windows-vs-linux"&gt;adroigroup.io&lt;/a&gt;&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>codenewbie</category>
      <category>webdev</category>
      <category>discuss</category>
    </item>
    <item>
      <title>The Web Application Development Process Explained</title>
      <dc:creator>Eduard Tar</dc:creator>
      <pubDate>Thu, 11 May 2023 12:26:16 +0000</pubDate>
      <link>https://dev.to/adroitgroup/the-web-application-development-process-explained-28ec</link>
      <guid>https://dev.to/adroitgroup/the-web-application-development-process-explained-28ec</guid>
      <description>&lt;p&gt;In the early days of the internet, companies could effortlessly make their online presence by creating a simple website. But today, with countless websites and web applications in the market, it has become hard for every company to meet the high demands.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ST_3Ys8H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p4zwq5ubsjkepltbuwil.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ST_3Ys8H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p4zwq5ubsjkepltbuwil.png" alt="Image description" width="720" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Developing a web application step by step
&lt;/h2&gt;

&lt;p&gt;Web application development in today’s age is a process, just like making a cake can be. You can’t bake a cake in 15 minutes, and you have to have the right ingredients as well. The same goes for web applications. You need to plan out how you want it to look, what your app will do, and how you’ll set up everything before actually doing the development.&lt;/p&gt;

&lt;p&gt;Imagine that you have some idea in your mind of a web app that could go up fast in the market. Without turning your idea into a working product, it remains just an idea. In today’s age, it is much more difficult to test and implement an idea than it was 20 years ago.&lt;/p&gt;

&lt;p&gt;We’ve come up with this web application development process flow guide for those of you who want to learn about the best practices for creating successful web applications.&lt;/p&gt;

&lt;p&gt;But before moving forward, first, let’s clarify what a web application really is.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a Web Application?
&lt;/h2&gt;

&lt;p&gt;To answer this question we need to roll back to the early 90s again when the web was invented.&lt;/p&gt;

&lt;p&gt;Almost all of the online content was static. They were just files and people would edit the files, put them on their servers, and they all linked to one another.&lt;/p&gt;

&lt;p&gt;These days, almost every website including Reddit, LinkedIn, and Facebook is built dynamically on the fly by programs called web applications. So, in simple words: a web application is a program that generates content for the website that a browser requests.&lt;/p&gt;

&lt;h2&gt;
  
  
  Advantages of a Web App
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Web apps can be accessed through various platforms such as a desktop, laptop, or mobile device.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Since web apps run in a web browser and aren’t downloaded from an app store, like Google Play or Apple store, users always see the most up-to-date version when they open a web application in their browser.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Because web apps are platform-agnostic, they are easy to maintain. They don’t need to be written in a specific language. Web apps usually use coding languages that are common across multiple platforms — typically a combination of a server-side script (PHP) and a client-side script(JavaScript).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Because the web application runs in a web browser, it can be discovered by search engines, like Google, and displayed in search engine results.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So now you know the history of web application and what it is. Now you need to decide how you want to build your web application.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do you want to build your web app?
&lt;/h2&gt;

&lt;p&gt;The first thing you can think about when you want to create a web app is assembling a team. But if you don’t have a ready-to-go group of programmers, designers, testers, and project managers, you need to choose between building a new team or partnering up with an external company.&lt;/p&gt;

&lt;p&gt;Let’s investigate these options and which one is best for developing your web application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build an in-house team
&lt;/h2&gt;

&lt;p&gt;If you decide to build your web application by hiring new team members, it has both advantages and disadvantages.&lt;/p&gt;

&lt;p&gt;You can hand-pick people who 100% fit your company’s culture and share your values.&lt;/p&gt;

&lt;p&gt;At the same time hiring, well-skilled people could be a considerable investment, in terms of time and money.&lt;/p&gt;

&lt;p&gt;In the meantime, as a company owner, you often do not have enough technical expertise to hire the right candidates for your project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Work with an external partner
&lt;/h2&gt;

&lt;p&gt;This could be a short phase because working with an external company that specializes in web app development is always much quicker than building your own team.&lt;/p&gt;

&lt;p&gt;This can be risky because the selected team may not meet your company’s needs.&lt;/p&gt;

&lt;p&gt;You can prevent this by looking at reviews of the company before choosing the right partner, checking their references, and asking for an introductory call or calls before accepting their offer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A good piece of advice: Try to choose an external development company that acts as a partner with you, not just a customer, and helps you to make your product even more valuable.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KqsclD4V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hz9prn1nfe0qniiw2ryw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KqsclD4V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hz9prn1nfe0qniiw2ryw.png" alt="Image description" width="720" height="481"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  IT Staff augmentation
&lt;/h2&gt;

&lt;p&gt;You may not have known about this possibility until now, but there is a service that allows you to integrate as many quality developers, testers, and project managers into your team as you need to complete your web application. This is called the IT Staff Augmentation Service. This is actually a golden middle ground between building your team or working with an external company.&lt;/p&gt;

&lt;p&gt;If you want to build your web application in this way, you first need to find a suitable team where this form of collaboration is available, who knows the latest technology to turn your idea into a working web application.&lt;/p&gt;

&lt;p&gt;You usually save money by working with such a team because you only pay one bill per month and don’t have to spend on HR, hiring, other labour costs, and so on.&lt;/p&gt;

&lt;p&gt;In this collaborative form adding more resources to the project is easier and much faster than hiring new members to your team.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are the key steps in web app development?
&lt;/h2&gt;

&lt;p&gt;Once you’ve decided how you want to build your product, whether you want to hire new team members or with an outsourced web application development team, it’s time to start product development.&lt;/p&gt;

&lt;p&gt;The basic process starts with laying the foundations: defining the business objective and outlining the key deliverables.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Discovery and planning
&lt;/h3&gt;

&lt;p&gt;This stage of discovering and researching determines what the subsequent steps will look like. Our project manager will work with you to gather all the requirements and define the scope of your web application, to get a clear understanding of your purpose, and the target audience you want to reach.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Wireframes &amp;amp; Designs
&lt;/h3&gt;

&lt;p&gt;Based on the provided information, we create a mind map, which describes the relationship between the main areas of your application. Before we start working on the design or coding of the web app, we create a wireframe that visually represents the user interface we want to develop.&lt;/p&gt;

&lt;p&gt;The success of your website will depend on how well users benefit from its features. Our goal is to create excellent user experiences, making your web app interactive, intuitive, and user-friendly. In this phase, we take your app into shape, all the visual content, such as images, photos, or videos are created at this step. We create a team for you and develop a UI prototype of your site.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Development
&lt;/h3&gt;

&lt;p&gt;The development team starts working on your website, using the Agile framework which is perfect for building web apps. Sprint in agile is normally 1 week to 1 month.&lt;/p&gt;

&lt;p&gt;We assess what features make sense to deploy first from the perspective of customer value, organizational value, and risk. We involve you, by inviting you to our progress presentations meetings.&lt;/p&gt;

&lt;p&gt;One of the greatest advantages of the agile approach is that we can deliver value continuously and if you have a change of requirements we can put it in the next sprint.&lt;/p&gt;

&lt;h4&gt;
  
  
  Quality assurance
&lt;/h4&gt;

&lt;p&gt;Performing quality assurance testing during website development makes the site stable and usable. That’s why your project goes through a detailed manual testing process by the most precise tester in the world who works with us. :) Our testing process contains user experience testing, functional testing, performance testing, security testing, and lastly device &amp;amp; platform testing.&lt;/p&gt;

&lt;h4&gt;
  
  
  Release Preparation
&lt;/h4&gt;

&lt;p&gt;— Of course, we want to launch your product smoothly and plan for a positive reception from users. Before deploying your web application, we ensure that the product is working as intended and run load tests on the environments to test how it reacts to traffic.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4
&lt;/h3&gt;

&lt;p&gt;: Delivery and post-launch support&lt;br&gt;
After the big launch, the development process is not over. The development of a web application cannot stop at the release of version 1.0, because the bugs that arise must be fixed, changes must be implemented based on customer needs, performance must be optimized continuously, and new functions must be added.&lt;/p&gt;

&lt;p&gt;We will continue to be available to you as a partner for further development, updates, and DevOps/Maintenance.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is the cost of a web app development?
&lt;/h2&gt;

&lt;p&gt;The basic factors that determine cost are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The desired functions&lt;/li&gt;
&lt;li&gt;Time&lt;/li&gt;
&lt;li&gt;and the resources you devote to turning your idea into a real web application.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s dive into a little more detail:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Development team size&lt;/strong&gt;: Whether you are building your own team or working with an external development company, development costs gradually increase with the number of people involved. Of course, if the project starts with 2 developers from your own team, the cost may seem less, but the implementation time will probably be longer, so the costs may end up being higher than if you work with a larger external team who can deliver faster.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Technologies&lt;/strong&gt;: Depending on the idea may require different frameworks, which may differ from the knowledge of your developers. In this case, you have to allocate extra time to education for your team or need to hire or work with an external company that has the specific knowledge.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Time frame&lt;/strong&gt;: Everything is based on the accuracy of the planning. A too-short and too-long time frame can increase the cost of development in both cases. The explanation is simple if it takes more time, more resources are needed, which increases the cost of the project. On the other hand, planning within a small time frame will definitely be a critical factor in increasing the price quote of the hired team, however, the delivery and results will come sooner.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Application type and specificity&lt;/strong&gt;: It is important to note that most applications must meet certain requirements. Whatever the application, if its operation falls within the GDPR zone, compliance is an additional cost that is mandatory and cannot be omitted. It just has to be accepted with dignity. If your web application idea is innovative, it means reading about innovative technologies and involving innovative resources. In this case, you should expect that it will cost a lot more to develop your web application in the end.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion:
&lt;/h2&gt;

&lt;p&gt;If you are planning to develop a web application, consider if an in-house team will be sufficient for your needs or not. It is not that easy for every company to have its own web application development team, as it will involve multiple hiring and knowledge-seeking processes. This may distract from the main business activity of a company. Another option is to work with an external development partner, which can be an outside company that has an expert team or has worked on similar projects before.&lt;/p&gt;

&lt;p&gt;Originally published at &lt;a href="https://adroitgroup.io/blog/how-to-start-a-web-application-development"&gt;adroitgroup.io&lt;/a&gt; and &lt;a href="https://medium.com/adroit-group/the-web-application-development-process-explained-f81430fd7159"&gt;medium.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>programming</category>
      <category>development</category>
    </item>
    <item>
      <title>The most useful free resources for Frontend developers in 2023 - HTML + CSS (beginner to advanced)</title>
      <dc:creator>Eduard Tar</dc:creator>
      <pubDate>Thu, 11 May 2023 12:16:09 +0000</pubDate>
      <link>https://dev.to/adroitgroup/the-most-useful-free-resources-for-frontend-developers-in-2022-html-css-beginner-to-advanced-32l5</link>
      <guid>https://dev.to/adroitgroup/the-most-useful-free-resources-for-frontend-developers-in-2022-html-css-beginner-to-advanced-32l5</guid>
      <description>&lt;p&gt;Well-chosen resources and tools greatly influence our results in all areas of life. Web development is no exception. Most of the beginners don’t know where to start learning, which is understandable given the ever-expanding nature of the Internet. During the past years I managed to filter down the best resources out there, to learn, and develop myself in many aspects related to programming. Now, I’m going to share the result with you, and you are going to get an answer for questions like:&lt;/p&gt;

&lt;p&gt;Where do you start learning?&lt;br&gt;
What should you start learning?&lt;br&gt;
What tools should you use?&lt;br&gt;
How to improve your way of learning/working?&lt;/p&gt;

&lt;p&gt;In most cases front-end developers' careers start with HTML and CSS. It’s not a coincidence. Every webpage on the internet eventually compiles to plain HTML, which gives us the skeleton (main structure) and CSS that adds the cosmetics to it. It’s a solid and reliable starting point, since you get an easily comprehensible visible representation of your work. Let us begin from this starting point too. By the end of this article you will be enriched with a solid set of tools that will be essential in your daily routine :)&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Learning/Tutorials
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.w3schools.com/"&gt;W3 school&lt;/a&gt;: The most essential place to start your web developer journey. If you are a total newbie, w3 schools can give you a solid understanding of the basic pillars of the web. Mostly I visit the site, if I need a HTML or CSS snippet, or I want to see some properties and their possible values.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8YQjWreE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zbln7tevkoj6vzwlrxgj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8YQjWreE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zbln7tevkoj6vzwlrxgj.png" alt="Image description" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/lancejpollard/1978404"&gt;All meta tags&lt;/a&gt;: A comprehensive collection of html meta tags. &lt;/p&gt;

&lt;p&gt;Get a better understanding of how html meta data works and what they can offer.&lt;/p&gt;

&lt;p&gt;Meta tags are very important to know, because they can affect your pages appearance and highly affect your SEO (search engine optimization) scores. The most important tags are the ones which affect your SEO score (title, description, keywords, canonical, robots), and the social media related ones (OG meta). Here you can find all the meta tags in one place separated by usage.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rmmsxzn6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0ao0628omgp6ucgoy8so.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rmmsxzn6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0ao0628omgp6ucgoy8so.png" alt="Image description" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.pluralsight.com/guides/semantic-html"&gt;Semantic tags - Accessibility&lt;/a&gt;: Why is it important to use semantic tags? Get a better understanding of accessibility.&lt;/p&gt;

&lt;p&gt;Accessibility is mainly an SEO concept. It helps the crawlers/robots/web-spiders to scan and evaluate your page’s content. With semantic tags you can tell the robots what kind of content they will find in a specific container, but in a human readable way.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WTBH4mbf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gks7qyni0pelx5n0ljzg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WTBH4mbf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gks7qyni0pelx5n0ljzg.png" alt="Image description" width="800" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://css-tricks.com/"&gt;Css tricks&lt;/a&gt;: Css tricks is your holy grail to learn css best practices, and expand your knowledge overall in css. &lt;/p&gt;

&lt;p&gt;Somehow I always end up here, when I want to deepen my knowledge in css. They have a high quality blog, which they update on a daily basis. Big names in the developer world have published articles here. They have video tutorials, code snippets, guides, and at last but not least the CSS Alamanac, where you can find all the css properties in one place.&lt;/p&gt;

&lt;p&gt;When you are stuck with a css problem I highly recommend you to include “css tricks” in your search terms at first.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--R8G4K5Lm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/erthwoyouojkinax2pz9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--R8G4K5Lm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/erthwoyouojkinax2pz9.png" alt="Image description" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://flexboxfroggy.com/"&gt;Flexbox froggy game&lt;/a&gt;: The css flexbox is a must-have skill to start your site-builder career. &lt;/p&gt;

&lt;p&gt;You can build basic and intermediate layout skeletons with it. This game absolutely amazingly presents what flexbox can do, and it helps you to understand in a practical way.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sNtdjznI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vcc7ydilnk0ndwqn19lh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sNtdjznI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vcc7ydilnk0ndwqn19lh.png" alt="Image description" width="800" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://codingfantasy.com/games/css-grid-attack"&gt;CSS Grid game&lt;/a&gt;: The css grid is also a must-have skill to be a professional site-builder. &lt;/p&gt;

&lt;p&gt;You can build advanced layout skeletons with it. Codingfantasy teaches you this in the form of a demanding and easy-to-digest intuitive game, completely free of charge.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sQKlyndh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cy5zzkrc4irgl8k9dfru.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sQKlyndh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cy5zzkrc4irgl8k9dfru.png" alt="Image description" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://meyerweb.com/eric/tools/css/reset/"&gt;CSS reset&lt;/a&gt;: With resetting CSS, you give all different browsers a common starting point to deal with your project.&lt;/p&gt;

&lt;p&gt;The goal of a reset stylesheet is to reduce browser inconsistencies in things like default line heights, margins and font sizes of headings, and so on. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BDfYmLOt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bqrycv90z02p6h3vo2a9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BDfYmLOt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bqrycv90z02p6h3vo2a9.png" alt="Image description" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://kinsta.com/blog/responsive-web-design/"&gt;Responsivity&lt;/a&gt;: Learn fluid layouts, breakpoints, media queries and other important aspects of responsive web design.&lt;/p&gt;

&lt;p&gt;A very overall and up-to-date study about responsive web design in 2022. It’s beginner's level, but I‘ve found it very valuable, since it tells you all the main aspects of responsibility, and gives you easy and nice examples on how to implement the concept.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CqQfiIzq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e3w36r54duhbewh68dds.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CqQfiIzq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e3w36r54duhbewh68dds.png" alt="Image description" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Youtube Channels﻿
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/kepowob"&gt;Kevin Powell - The css king&lt;/a&gt;: This guy is making so good and comprehensive content, so that he was crowned royalty by the people of the internet. Definitely worth checking out.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rgb2B1my--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sae7vb15nz6qevt1fl8n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rgb2B1my--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sae7vb15nz6qevt1fl8n.png" alt="Image description" width="800" height="370"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/c/OnlineTutorials4Designers"&gt;Online tutorials&lt;/a&gt;: Quick, simple, versatile, and innovative HTML+CSS templates with best practices in mind. The most compact and spectacular way to expand your css knowledge via video tutorials.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--s-ZLe5D---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/libxebz4f30k2n1a1ugk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--s-ZLe5D---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/libxebz4f30k2n1a1ugk.png" alt="Image description" width="800" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Generators
&lt;/h2&gt;

&lt;p&gt;All in one generators: Create any css code on the web quickly. &lt;/p&gt;

&lt;p&gt;Spare time, and get a grasp on best practices.&lt;/p&gt;

&lt;p&gt;It’s not too realistic to use these tools to do your everyday’s css, but it is a very nice tool to understand things, and deepen your best practices. In most cases you would probably use one or two of these tools, but still, it’s just a good thing to have this kind of reinforcement, if you are in need of it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://css-generator.netlify.app/"&gt;Generator 1&lt;br&gt;
&lt;/a&gt;&lt;br&gt;
&lt;a href="https://webcode.tools/generators/css"&gt;Generator 2&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--o6ZX8n8f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7bwm7swo98rv0oxog5vg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--o6ZX8n8f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7bwm7swo98rv0oxog5vg.png" alt="Image description" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://shadows.brumm.af/"&gt;Box shadow generator&lt;/a&gt;: Pretty box shadows can be tricky to make. This tool helps you visualize the process of making your desired box shadows in a handy and spectacular way.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GyfUTm11--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l8x2dq9cvgz2v3a51tz5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GyfUTm11--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l8x2dq9cvgz2v3a51tz5.png" alt="Image description" width="800" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://cssgradient.io/"&gt;Gradient generator&lt;/a&gt;: Spare effort and time with this beautiful gradient generator.&lt;/p&gt;

&lt;p&gt;I often find myself using this gradient generator. Really easy to use, and capable of making complex gradients, which spares tons of time. I don’t even need to say that it gives you multi-browes compatible code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dAjSVw6P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o7n67c8guzzqlrhsfl6r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dAjSVw6P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o7n67c8guzzqlrhsfl6r.png" alt="Image description" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.lipsum.com/"&gt;Lorem ipsum generator&lt;/a&gt;: Using mock data, has never been this easy. &lt;/p&gt;

&lt;p&gt;Generate custom lorem ipsum texts to fill the void in your project’s template. &lt;/p&gt;

&lt;p&gt;Although I usually use Lorem Ipsum generator as a VS code plugin, it may still come in handy in some cases. For example when you need really long placeholder text, it may be more ideal to use this one.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gnACeXho--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x3q73fajiwgp93n8kolt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gnACeXho--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x3q73fajiwgp93n8kolt.png" alt="Image description" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://realfavicongenerator.net/"&gt;Favicon generator&lt;/a&gt;: A good website must have a good favicon too. It helps you stand out in the world of browser tabs.&lt;/p&gt;

&lt;p&gt;You spent hours on design, colors, graphics... How much time left for the favicon? Probably not much. This professional free tool can do it for you in 2 minutes. It also gives you the opportunity to set an apple touch icon, PWA icon, and you can set your theme color as well.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VdBPhzUu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4y6fi82nrfyb9zzyx4q4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VdBPhzUu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4y6fi82nrfyb9zzyx4q4.png" alt="Image description" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://10015.io/tools/css-loader-generator"&gt;Animated loader generator&lt;/a&gt;: Make a custom loader in no time.&lt;/p&gt;

&lt;p&gt;When I’m in a hurry, and don't have much time to be creative about loaders, I usually come here, pick a loader, and it’s done :)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://adroitgroup-io-storage.s3.eu-central-1.amazonaws.com/text-editor/2022-11-14_1fdN7HzFtp_6-loader-generator.png"&gt;https://adroitgroup-io-storage.s3.eu-central-1.amazonaws.com/text-editor/2022-11-14_1fdN7HzFtp_6-loader-generator.png&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://uiverse.io/"&gt;Free UI elements&lt;/a&gt;: Get high quality free UI elements to you project.&lt;/p&gt;

&lt;p&gt;This place can be a total hit, if you want to be inspired. I would recommend it mostly for input elements.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5ffd-zXR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kouyfj7flnsgflnper1j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5ffd-zXR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kouyfj7flnsgflnper1j.png" alt="Image description" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gradihunt.com/"&gt;Premade gradients&lt;/a&gt;: Choose from hundreds of premade gradients.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rvAHWGwA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uzf8b9lxnvcuaktuh1c9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rvAHWGwA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uzf8b9lxnvcuaktuh1c9.png" alt="Image description" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.magicpattern.design/tools/css-backgrounds"&gt;Background pattern generator&lt;/a&gt;: Make your own qualitative background pattern.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2RqExGZC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jc3gia5htemv5ptcg2np.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2RqExGZC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jc3gia5htemv5ptcg2np.png" alt="Image description" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Others
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://autoprefixer.github.io/"&gt;Css auto prefixer&lt;/a&gt;: However modern css frameworks and tools will probably do it in the background, in some cases it is highly recommended to check the multi-broweser compatibility manually. Auto prefixer helps to convert your css to multi-browser compatible code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5Va9b5pK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cs41csr2sgofw3dy883t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5Va9b5pK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cs41csr2sgofw3dy883t.png" alt="Image description" width="800" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://caniuse.com/"&gt;Can I use - CSS property compatibility check&lt;/a&gt;:  If you’re not sure you can use a specific css property with full multi-browser compatibility, check it on this website. I often come here, when I use some newly released or experimental css property.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--U-0TXNjx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tsuu439k8damu8xxs0f4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--U-0TXNjx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tsuu439k8damu8xxs0f4.png" alt="Image description" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.svgator.com/"&gt;SVGator svg animations&lt;/a&gt;: Make outstanding svg animations (even without any animation experience) almost for free.&lt;/p&gt;

&lt;p&gt;SVG animations are difficult to make. But it was only difficult until now. SVGator isn’t completely free of charge (12$/month), but it has a free version where you can state the fact that it’s totally worth the money. The platform is impressively easy to understand and use. After 2 hours of practice you can technically animate whatever you’d like to.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eaUgPBET--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7bnlq2sprwslx4fgz2xe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eaUgPBET--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7bnlq2sprwslx4fgz2xe.png" alt="Image description" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://codepen.io/joeyred/pen/pEagLQ"&gt;Fixed background on Mobile&lt;/a&gt;: Fixed backgrounds can be tricky to implement on phones and tablets. Since there’s still not any native support to achieve this function, this code snippet can save your day.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Lw0Q1Vqu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7r2sxd0n23021r13mow6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Lw0Q1Vqu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7r2sxd0n23021r13mow6.png" alt="Image description" width="700" height="325"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://usefonts.netlify.app/"&gt;Find the best fonts&lt;/a&gt;: Find fonts that match your idea/brand/design the best.&lt;/p&gt;

&lt;p&gt;Figuring out how to pick the best font for your brand can be overwhelming. Learning more about different typefaces and font combinations can make things simple. When it comes to choosing the right typeface for your brand or design project, there are a number of different factors to consider. 1. Understand your brand identity, 2. Take note of the brand fonts you admire, 3. Research typography, 4. Choose a few fonts to start, 5. Consider the typographic hierarchy, 6. Ask for feedback.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OLSMJC5V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/shts34m3tixqv2bmwc80.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OLSMJC5V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/shts34m3tixqv2bmwc80.png" alt="Image description" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Find and download fonts and webfonts:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.fontsquirrel.com/"&gt;Fontsquirrel&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dafont.com/"&gt;Dafont&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://fonts.google.com/"&gt;Google fonts&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Color palettes:
&lt;/h3&gt;

&lt;p&gt;Make your colors consistent! Find predefined color palettes, or make your own palette.&lt;/p&gt;

&lt;p&gt;If we were not born as a designer prodigy, developing a sense of beauty may be difficult. This website is intended to fill a part of this gap. We can choose from more than 1,000 pre-made color palettes, which will surely provide a result with a consistent color scheme.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://colorhunt.co/"&gt;Colorhunt &lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://colorpalettes.net/"&gt;Colorpalettes &lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JnsyM238--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s3wjjn7c5e6sti5prsvi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JnsyM238--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s3wjjn7c5e6sti5prsvi.png" alt="Image description" width="800" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://beefree.io/templates"&gt;Email templates&lt;/a&gt;: Making HTML Email templates can be really a pain in the ass. &lt;/p&gt;

&lt;p&gt;Different email clients (gmail, outlook, etc.) might interpret your email template differently. Therefore there’s only one way to make a stable template. HTML table layout, with inline css. Unfortunately it’s very unintuitive, and it’s probably always wiser to use a premade template.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7BAPcK9H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d5b5z7gvwyzm36zcsn0v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7BAPcK9H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d5b5z7gvwyzm36zcsn0v.png" alt="Image description" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.free-css.com/free-css-templates"&gt;Free HTML+CSS templates&lt;/a&gt;: If you want to be inspired or practice with altering other’s code, then free-css.com is a good place to start.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0zt49Ofh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ebp9xijuvi5dnfd1hz9e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0zt49Ofh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ebp9xijuvi5dnfd1hz9e.png" alt="Image description" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.toptal.com/designers/htmlarrows/symbols/"&gt;HTML symbols&lt;/a&gt;: Usually we don’t use symbols on a daily basis, but it’s definitely essential to know the basics of HTML symbols and entities.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6mcVzMAg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zu082lr2sl6b3s9ggx7x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6mcVzMAg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zu082lr2sl6b3s9ggx7x.png" alt="Image description" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://m3.material.io/"&gt;Material design&lt;/a&gt;: Use and master the predefined tools developed by google. Find themes, icons, fonts, and get open source projects.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tAE0Pqg5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6i5pj48wu1l89led2k73.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tAE0Pqg5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6i5pj48wu1l89led2k73.png" alt="Image description" width="800" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Must-read articles
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.browserstack.com/guide/how-to-implement-mobile-first-design"&gt;Mobile first principle&lt;/a&gt;: Understand the importance of phone optimization. In 2022 60% of people browsing the internet from their phone. In web development it means, you have a higher priority on developing on mobile devices firstly, then for desktop and other devices.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2R7iTgDD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i13g5gx1ttqhv7o5ul54.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2R7iTgDD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i13g5gx1ttqhv7o5ul54.png" alt="Image description" width="800" height="523"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://css-tricks.com/equal-columns-with-flexbox-its-more-complicated-than-you-might-think/"&gt;Flexbox equal height&lt;/a&gt;: Making equal height columns might be tricky even with flexbox. Check the golden standard to make it work.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WUr1CgY0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t56mod1digk0a6crm150.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WUr1CgY0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t56mod1digk0a6crm150.png" alt="Image description" width="800" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.digitalocean.com/community/tutorials/css-css-units-explained"&gt;Css units explained&lt;/a&gt;: Deciding when to use which css unit might be hard to comprehend. Read this article, to dispel the gloom.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lu0RfQ9U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jm3kjsye6b1b3upt53kt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lu0RfQ9U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jm3kjsye6b1b3upt53kt.png" alt="Image description" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://getbem.com/naming/"&gt;BEM naming convention&lt;/a&gt;: The BEM approach ensures that everyone who participates in the development of a website works with a single codebase and speaks the same language. Using proper naming will prepare you for the changes in design of the website.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0ZLLGIxA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qk10oytp1c76mwyeq6e8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0ZLLGIxA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qk10oytp1c76mwyeq6e8.png" alt="Image description" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freecodecamp.org/news/what-is-tailwind-css-a-beginners-guide/"&gt;Tailwind css: &lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JrC8_Hqz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ht72it3nehlqp5xnmhzx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JrC8_Hqz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ht72it3nehlqp5xnmhzx.png" alt="Image description" width="800" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Did you like this article?&lt;/p&gt;

&lt;p&gt;More is on the way. I’m going to gather useful resources in different topics like javascript, php, seo, vs code and so on.&lt;/p&gt;

&lt;p&gt;Let’s continue with javascript, and all the relevant js frameworks next time.&lt;/p&gt;

&lt;p&gt;========&lt;br&gt;
Originally published at &lt;a href="https://adroitgroup.io/blog/the-most-useful-free-resources-for-frontend-developers-in-2022-html--css"&gt;adroitgroup.io&lt;/a&gt; and written by &lt;a href="https://medium.com/@mate.sera"&gt;Máté Séra&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>learning</category>
      <category>html</category>
      <category>css</category>
    </item>
  </channel>
</rss>
