📜 ⬆️ ⬇️

Reservoir Dogs: Angular 2 vs React

Meet, the confrontation of two frameworks: Angular and React in the format of the fight on the example of a specific simple application. Yevgeny Gusev ( @bunopus ) speaks for Angular, Ilya Taratukhin ( @ilfa ) stands for React. To make honest conclusions, they first exchanged technologies and tried to deploy a basic project. Start on React gave rise to many problems, but with Angular, the situation was much simpler, because this is an ideal application for a person who did not particularly work with the front-end. But, of course, it was only the beginning, the real dispute went further, all stages of which are under the cut



About speakers:

Evgeny Gusev has more than ten years of experience as a developer, the last few years working in the company Wrike . He first developed in C ++ / C #, and then decided that all the movement and money were on the front end and moved there. Now in Wrike do not use JavaScript, and use Dart.
')
Ilya Taratukhin has been involved in commercial development for about seven years and they are all in the front end. Worked in 2GIS, wrote on native JS and already, it seems, the dying Knockout . In parallel with his work at Wrike, Illya is developing his project, in which he actively plunged into React. For more than a year, Ilya has been using a bunch of Dart + Angular 2 . The experience is really interesting

That is, Evgeny has a lot of experience with Angular, and Ilya has a great experience with React. For everything to be honest, they exchanged technologies and tried to create a fairly simple project on these frameworks.


Disclamer: Further decoding of the report of Evgeny Gusev and Ilya Taratukhin at RHS ++ 2017, everything that is being discussed is true at the time of the preparation of the report, when Angular was in version 4.2.0, and React - 15.5.0. However, the comparison covers the most significant aspects, for which no significant changes have occurred, despite the fact that Angular 6.0.0-rc.3 has already been released.

Part 1. Introduction




The essence of the project is as follows: there is an input field into which the name of the city is driven in, according to http requests on the weather server, the weather in the selected city is found out - it is cloudy again in St. Petersburg, and you have to go and drink beer. Nothing complicated.

React


Eugene: I started to get acquainted with React, of course, with the choice of the ideal Starterpack - I don’t understand anything in React.

Suppose a customer came to me and asked me to make a weather widget. To solve this problem, I began to look for what would help me to make a project, and found an excellent site that I recommend to everyone. I go there and see this picture: 108 Starterpacks (now there are already 189), with 20 of them labeled as minimal.



I had a problem choosing a framework., And it became 108 problems. But I managed and chose Starterpack from Facebook .



I must now in every way vilify React and say that everything is bad, but in fact everything was normal, and even works well. I started by saying that “ how to send an HTTP request to React ” and got a link to stackoverflow, where I was told that you can fetch, axios, something else.

Imagine I had 1 problem, 108 problems were added to it, and then 3 more.

Ilya: Let me explain, Evgeny is a little bit away from JavaScript for about two years now, and forgot how an HTTP request is made in JS and that you can take a fetch , because It should be in all browsers. But if that, polyfill to fasten and it will be fine.

Eugene: I chose axios, of course. The next thing you need for a simple “Hello world!” Application is to write a simple application.



There is a render function, and in it is a simple input, that is, everything is simple - you drive something in, and onChange does setState.



I had to use bind ! Okay, this is probably not a problem. React is my problem. Another simple “Hello world!” Application needs tests.

Briefly about tests - everything is bad


I didn’t manage to run them the first time, I gave up and decided that Illya is smarter, although I didn’t even ask him.

Margin notes


Eugene: After my vast experience in React, I want to clarify the following: how to combine the names of the components and the names of the classes on the styleguide? Ilya, what do you call your components in React?

Ilya: Since the component is a certain class, I call it CamelCase with a capital letter.

Yevgeny: I turn everything inside, because the markup must be in small letters and hyphens. When in the JSX markup, classes are written with a capital letter - CamelCase, it just becomes bad for me.

Secondly, I want Dependency Injection. Is there a DI in React?

Ilya: There is no React itself, but there are various tools that implement DI in full or in some truncated version.

Evgeny: There are probably 100 of them? But nonetheless:


Think for what it would become if I had screwed in another Redux, Flux and other “Aksy”.

Total : 4 of 5.



Why 4, not 5? Yes, in Starterpack, in principle, everything is clear, but I imagine that I need to make a normal large working application out of this Starterpack sooner or later. I think, then I will have to read not 4 articles, but probably 104, and make my perfect Starterpack.



Ilya: Let's go to my experience. When you deal with Angular, everything is simpler, because there is such a colossus as Google, which dictates what to do, and I very quickly came across Angular's CLI QuickStart .

As a result, I executed 4 commands in the console.



I'm a frontend developer — I have Node.js and NPM, there is no such problem. As a result, in 10 minutes I received a working application with hot-reload and bolted tests. Everything is cool, a lot of things were added - I didn’t even immediately understand what I now have.

The next task is the same: make an HTTP request, and before that you need to make a component that will display the result. I found that Scaffolding from Angular allows you to do this in one line , called this command and received 4 files:




Eugene: I would like to say that React in Starterpack from Facebook also has testiki, but for some reason they did not work for me.

Ilya The next step is to make an HTTP request. I somehow broke through the Angular documentation, found an example, copied it almost completely, and called the getWeather function.



And got nothing, looked from console.log, the network tab - nothing, emptiness!

Evgeny: For those who write little or no Angular, Observable on RxJS is very lazy. Until you subscribe to them, they will not work.

Ilya: I guessed that something was wrong, but I was not ready to insert the given template somewhere. I just wanted to check that my HTTP request through the HTTP library provided by Angular works in general. So I rummaged through the documentation and found how to do it at Promise .



So, did, caused - it all worked. Overall I was pleased .

Next problem. I hang the handler, I write in TypeScript in 2017, and I still have to bind the context, it was a bit shocking to me, because I was used to the joys of Dart.



This is where my problems are over. I got a working application, but I have a couple of questions left.

Open questions



Weather application is very simple to do, it is gathered almost out of the box. But when we start doing a serious project, we need control over the assembly. Now the whole assembly is hidden inside the cli-starter-kit.

Eugene: Inside the Angular CLI, there is the ng eject command, which removes all unnecessary Starter dependencies and allows you to make everything you need from a starter application.


Ilya: The next item. As you saw, starter-kit nageneril CSS files for me, but I already want to use less, sass, stylus, postcss. I turned to Eugene: “How so? I want less! ”, And he advised to just rename the file, and indeed, the assembly automatically picked up the less file. I was once again horrified - how much all Angular pulls with itself, but it works.

Total:


My conclusion is that Angular is just the perfect application for a person who didn’t work particularly with the front-end , for someone who, for example, came from .net. He is accustomed to DI, all sorts of complex abstractions, in Angular 4 you can inherit components from each other.

But you need to be ready to learn the tools of the framework - you will have to read a lot. These are really huge volumes of documentation. If Eugene fears that in order to work with React he will have to seriously search on the Internet, then everything is gathered in one place, you just need to read and understand.

Part 2. The dispute


Total - we met with 2 frameworks. What is our argument?

$$$ $$$ Super Project


We made the site shawarma (or shawarma). We have a small landing page with several tabs. One of them is comments, by them we can understand how state works, how something is saved, etc. The last tab is a block of contacts with a map (map as an external JS library). We will return to the map a little later - this is a pain point.

We made a simple application for which you can get 10 000 rubles or 5 free portions of shavarma.

Let's take a look at Data-Flow - how the threads move in our frameworks. Let's start with Angular



Angular (left)


It all starts with the state. In our case, this is just an ordinary array of comments, from which we take comments, somehow we render or add them.

We put this state into our components through @ - all Angulars love dogs and square brackets. Through the square brackets in the markup write that in this comments-widget state will be put (comments).

If I want to add something from the widget, and if I’m not afraid to harm, I’ll just do an Object Change. But it is better not to do so.

It is better to write @output and parentheses - these are not events, these are streams from RxJS - so they do not pop up, but work a little differently.

React (right)


React also has a state. In general, React recommends using the Flux architecture, for which there are many different tools. We pass pieces of the state to the component through the so-called props. I have not found the correct way to translate this word into Russian.

Eugene: Maybe you can translate props, like the pieces - “you are this.”.

In props, we throw data — comments will be available in the component through the comments property. When we want to handle some event, such as a click or add, we also send it to the props component, but this will be just a callback.

Angular


When we have not just comments that need to be rendered, but something huge, big, and a bunch of components, of course, it's pretty silly to do input-output. But when these are small components, for example, there is an avatar or something else inside a large comments-widget, you can also get data back and forth through input-output and square brackets.

React


In general, nothing new, everything is exactly the same - we pass props to the child components, somewhere inside CommentsWidget we have sorted out the comments, and inside the comment component we are passing the specific comment already. Also with CommentForm, we can listen to the add event and somehow handle it.

Evgeny: Of course, if we have a really big app, then it’s stupid to do that. You will have a huge tree of these input-output. But we in Angular have Dependency Injection! Is there a React DI?



Ilya: If someone doesn’t know, I didn’t know before working with Angular either - you can set up connections between your services and components in a very unobvious way, so confuse everything, and just shoot yourself in the foot at each refactoring.

Eugene: Angular - not for stupid.

We take the service - it is essentially just a class with a certain annotation. We shove him wherever possible - but I did not tell you that! In general, you shove it only where it is needed - in this case in our comments-widget.

And where it is not needed, we use the same input-output. That is, it is a kind of hybrid system. In the comments-widget, we use service calls, object retrieval is all as usual.

Ilya: In React, there are some trimmed versions of DI, which allow, for example, to throw some data from top to bottom.

I will tell on the example of Redux simply because it is the most popular library. The rest of the tools work in a similar way.

We have a certain store. Using the connect magic function, we connect the store with our top-level component. The top-level component knows that there is a store, where the data comes from in a certain format, and according to a certain format of communication through action it can notify the store that something has happened.



Thus, we have 2 types of components:

  1. Some smart components that are aware of the existence of a state receive information about its update and notify the state that they need to be updated.
  2. Context-independent components that we can use, in general, where we want to - just proxy them with the necessary props.

Eugene: And in Angular, all components are smart.

Component Definition


Let's now look at the code and how we create the components in our two frameworks.



Angular


In Angular, a component is a simple regular JSX, TypeScript or Dart class - but this is a class with some small annotation in @. It is possible to write through selector: “Angular, look, if you see such-or-such a class, property or tag in the markup, then this is a component, respectively, treat it as a component”.

Ilya: Let me remind you that we have a dispute. Therefore, I will be the most oppositional.

React


So, in React we describe the so-called functional setState component. We just have a function that takes a props object as input and returns a JSX template.



Eugene: Templates in Angular are simple, plain, clear HTML.

Ilya: Very clear! See: ngFor, brackets, comments, parentheses, onADD - plain HTML!

Eugene: Yes, of course, you need to learn something - stars, brackets, dogs. But they say that Angular is like this, because it was written by javists, it has a lot of keywords, but on the whole it is plain HTML.

React


Ilya: I will be honest and say that React is not quite normal HTML. Here in JSX is some kind of cross between HTML and JS code, or TypeScript code - depending on what you write. Yes, there is such a nuance, but it is enough to take care of yourself, to write in the component file only the code that concerns the display of the component. And all the heavy logic needs to be pulled out in the reducer, in the store, in the helper away from the components, and then everything will be clean and transparent.

If you share JS developers and layout designers in your company, then layout designers will quickly become accustomed to such a description of the components and will not experience problems with it.



Angular


Eugene: How does DI work in Angular? In fact, you just use magic and say:

- Look, I have such a service in the constructor (commentsService in this case).

And that's all, Angular will implement it for you when you have a component created. Then you simply use the instance during lifecycle hooks, as in this case, ngOnInit. You can talk about DI before the end of the day - it's just magic.

React


Ilya: I’ll show you some React magic. To connect the component with the store, take the component and the connect function from Redux and pass the connect rule to the rule. One rule will talk about how to break a Redux tree into subtrees and pass it to the component with props, and the second, on the contrary, will talk about how to wrap the Redux action into a callback and pass it into the component's props - that's all.

Evgeny: You will forgive me, of course, but if in the case of Angular this is magic, then this export default connect is some kind of black magic.

Ilya: You know, for 2 years JS has changed a bit and now the export default is normal.

User interaction


Evgeniy: In general, this is the most interesting part - how everything is rendered and where it breaks when the user does something.



Angular


We have an application, inside it there is a comments-widget, inside it there is a small comment-form. These are all components. What happens when a user clicks submit somewhere in the bottom component?

All Angular lovers adore zones. Zones are such a tricky thing that came out, oddly enough, from Dart. Zones implement monkey patch for all asynchronous functions of your browser: setTimeout, setInterval, as well as all user interactions, such as clicks.

When something happens, zones jerk and pull some code - this is a ChangeDetection. ChangeDetection runs from the root across all components, determines that something has changed, and renders everything. If, for example, there were 5 comments and the 6th one was added, then all 5 comments would be rebranded. So, but very quickly.

React


Ilya: Let's make the same React application. As we found out, it's not a problem to make applications with plus or minus the same architecture, but the matter is in the details.



We catch the submit event of the form, notify the component above, throw the action in the store, process the action. Store throw emit change. Emit change will arrive to all components that are associated with the store, and components will begin to check the props on the topic, the links to the store trees have changed or have not changed.



If they have changed, the component will call the rerender function, completely re-render the Virtual DOM, then Virtual DOM will compare its previous state with the current one, with the new one, and make a point change in the DOM tree.

Eugene: Wait. We have a Virtual DOM, and in principle, potentially I have 2 instances of the entire DOM tree in my memory.

Ilya: Is this a problem?

Evgeny: And if I have a gigabyte of memory on a laptop?

Ilya: Laptop from 2007? But if essentially, then we have a very unpleasant limitation of a real DOM. It does not allow to hold more than 5-10 thousand DOM nodes and begins to behave inadequately, to slow down. Therefore, we will not be able to create too many Virtual DOM nodes.

Eugene: Especially in IE.


Part 3. Pain


It usually hurts after an argument.



Angular


What is the pain in angular? I just did not tell you this, but it is a little slow, but only if you do not know how to cook it.



For example, I have a textarea. I want to do something on mousmove, for example, hang a class or highlight something. Then I just subscribe to mousmove and do it. It's simple.

I paint the components in acidic colors when a ChangeDetection happens, and I see something like this.



In general, it is claimed that ChangeDetection is very fast. But if you have a lot of DOM nodes and components, then everything is not very fast.

Fix it is very simple - subscribe to mousmove outside the zone, so that Angular does not touch you. Then, when you need something, you can go back to the zone.



Ilya: We create a zone so that everything works fine for us automatically, and then we try to bypass it !?

Eugene: So it is necessary! I said that Angular is not for stupid.

It would be all fair, if not Angular-4. The guys tried, did everything well. In general, now Angular is really fast, beautiful and works fine.



React


Ilya: A little about the pain of React. At one time, when I started to dive into React, I decided that I would now write applications on a framework that works through state. It seems to be simple, yes? And then you think: “I would have hung a classic on the DOM node, I would have worked some kind of animation, and then I would have removed this classic!” But no, such things in React do not work.



When you write an application on React, for the first couple of months you learn to rebuild your thinking and write an application on React - to change the state and to understand how your application will change after changing it. Anyway, everyone who is completely immersed in React learn and understand how to work with it.

In the sample application, there was a block with a map. If you need to insert a third-party card, there may be two options.

Good outcome. Some guys, for example, from 2GIS have written their React-wrapper over the library. A map is some kind of third-party JS application that builds a DOM tree, it can be a simple component. You use it and that's it.



Another option . But sometimes you want to connect the JS library, which nobody before you connected or connected to React, but did not put the solution in open source, how to wrap the JS library in the React component. And the adventure begins.



You will find out that React has a lot of lifecycle hooks, some of which you will have to use. First you need to use componentDidMount, wait until your React component is rendered and inserted into the DOM. Then you can initialize this third-party JS library, pass the DOM to it, and it will deploy its belongings there.

You need to remember lifecycle hooks in componentWillReceiveProps, and every time you have props updated at the component input, you need to write with your hands a huge logic that, when changing this property, will understand what needs to be done in the function call language of this library.

In my example, quite simply, but I suspect that there will be a huge footcloth.

You will need to recall lifecycle hooks shouldComponentUpdate. Here we simply return false and say: “React, we transferred a gifchik to you in the render, consider it empty, and don’t get into it at all”

One more thing


Eugene: Let's talk a little bit about the tools.

Angular


Angular naturally has it all. You do not need anything, thank you all.

React


Ilya: React can be loved at least for excellent DevTools.



There is React DevTools, which helps to present the application not as a DOM tree, but as React components; see which component is nested; see the magic wrapper components that Redux creates, for example, and which props came to the input of the component; understand where and what was done wrong.

It seems to me that many people started using React after seeing its DevTools. These tools allow you to travel through time and see the history of a change in state by winding the state of the application a few steps back.

Evgeny: Back to 2007?

Ilya: If the tab lived for a very long time, then why not?



Also there are useful buns: diff between the nearest states, full state and the test tab, in which moki for testing are generated. You can take mocks based on the current state of the application, cram it into state and tests that will check something. There will be no need to take steps that will transfer the application to the desired state, the state will simply create the application, and then you will check if everything is fine when the application is in this state.

Part 4. End


After a dispute, there is pain, and after pain - the end. Let's sum up some results of the battle of Angular against React.



Angular



React





At the conference, Eugene and Ilya voted Angular vs React right in the course of the report, but, unfortunately, bots got involved in the game. Therefore, let's repeat in the survey to this article.

We promise that this year you will not be bored at the RIT ++ festival - the pool of reports on the frontend is very serious. Here are some examples:

Andrei Solodovnikov (N1.RU) promises to help you figure out whether Vue.js is suitable for creating a large web application , tell you what makes the development on Vue.js really convenient and how things are with performance.

Vitaly Glibin from Huntflow does not claim that it will be easy to explain to business why you need half a year to rewrite everything from scratch in this modern and modern framework. But
It offers you to share your personal experience of migrating a large and complex application from Backbone to Vue , and tell you why you managed to do this without harm to the business (and even vice versa).

Yuri Yurin proposes to save you more than 100 hours , which Skyeng spent on discussions, experiments and code, trying to learn from the mistakes of others. The report "The technical side of creating a UI-kit on Angular 4/5 " will be devoted to the process of making the common code to the library .

The report by Mikhail Bashurov from Luxoft will deal with the event loop , consider what it is and what it is eaten with. Let's talk about how to use asynchronous J ava S cript , which has one stream at the same time, and not shoot yourself in the foot.

In total, about 60 applications have been submitted to Frontend Conf , but less than half will be selected. Follow the news, and you can book tickets without waiting for the exact program.

Source: https://habr.com/ru/post/353618/


All Articles