Korolev. Medicine for the web

    About a year ago, Nikita Prokopov’s manifest article on disappointment in software was released. Judging by the positive feedback, developers are not indifferent to the quality of their products. Maybe it's time to start acting?


    In this article I want to talk about my development, which, in my opinion, can cure the main performance problems of the modern web and make the user a little happier. The problems are: heavy JS code, high time to start working with the page (TTI) , high memory and processor consumption.


    Before reading further, follow the link . Try playing a couple of games. Play preferably from the desktop.


    A bit of history


    From the very beginning, the web browser was conceived as a thin client for web servers. The browser displayed the hypertext pages it received from the server. Simple and elegant. As it often happens, a beautiful idea is faced with reality, and after a few years, browser manufacturers have added support for the scripting language. At first, it served only as a decoration, and right up to the mid-2000s, it was considered good form to make web pages work without JS support.


    A modern approach to website development is the result of the development of user interface interactivity requirements. Tasks to improve interactivity fell on the shoulders of coders. Those often did not have the competencies and authority to develop an “end-to-end” solution. Layout designers learned to write JS and became front-end. Logic gradually began to flow from the server to the client. It is convenient for the front-runner to write for the browser, and the back-end is convenient not to think about the user (give my JSON to you, and then at least the grass does not grow). Just two years ago, there was a surge of interest in serverless architecture, where it was suggested that JS applications would work directly with the database and event buses.


    Currently, a “spherical website in a vacuum” is a complex JS application and a simple API server with which it communicates. The main logic runs on a thick client, the server side degenerates to a simple layer to the database.


    The need to keep logic on the client creates problems. If the service “took off” and began to earn money, then further, in terms of productivity, it will only get worse. Requirements will change. The development team will change. There will be more and more new code, and the old code will not be cleaned. The page will swell from dependencies, it will load JSON about the purpose of which no one remembers, but it's scary to delete, suddenly something breaks. Background tasks will appear setInterval, each of which is performed for several milliseconds every second, which after some time will lead to brakes and warming up the unfortunate user's iPad to the point that he can fry fried eggs on it. It ends up being burnt outfront-end vendors will come to the manager with a proposal to rewrite everything from scratch on a new framework. The manager will refuse, and front-end will begin to use two frameworks together.


    How Korolev works


    So, what if we return to the point of the report? The moment when someone came up with the idea of ​​updating content without reloading the page, and the historical inevitability gave rise to AJAX? What if you leave everything on the server and make a thin client? The best sites do server page pre-rendering (SSR) so that the user sees the interface before JS loads and starts. You can go further and leave on the client only the code that is responsible for processing I / O, given the current requirements for interactivity. Thoughts about this spilled over into the Korolev project .


    How does it work on the client side? The user comes to the page. The server gives the generated HTML and a small script (~ 6 Kbytes without compression) that connects to the server via a web socket. When a user fires an event (for example, a click), the script sends it to the server. After processing the event, the server generates a list of commands like "add new

    "," add a class to such an element, "" delete such and such an element. "The client applies the list of commands to the DOM. As such, HTML does not work - the script works directly with the DOM, so do not worry that the contents the shape or scroll position will be reset.


    What is happening on the server? When a request for a page comes from the browser, Korolev creates a new session. For the session, the initial state is made, which is stored in the cache. HTML is generated from this state, which is given to the client as a response to the request. In addition, the server saves the "virtual DOM" in the session. After requesting the page, the server accepts the request to open the web socket. Korolev associates an open web socket with a session. Each event coming from the client can change the state associated with the session. Each state change leads to a function call render, which forms a new "virtual DOM", which is compared with the old version. The comparison results in a list of commands to send to the client.


    What happens in the code and head of the developer? The above could remind you of React, with the difference that everything runs on the server. In terms of development approach, we also have something similar. Therefore, if you worked with React or another "virtual DOM", then the Queen's approach will be familiar to you. If you are not familiar with React, then imagine that you have data that you insert into the template. Imagine that according to the template, event handlers are scattered that can change data (but not the DOM). You change the data, the page changes itself. Korolev himself comes up with how to change the DOM.


    Performance


    There are two popular questions about Korolev: “what if the delays are high” and “will this not load my server”. Both questions are very reasonable. The front-end programmer is used to having his program run on the user's local machine. This means that the changes made to it will be applied as soon as the JS machine finishes executing the code and the browser starts rendering. I specifically showed an example of using "at maximum speed" at the very beginning. You could observe the delay only if you came from the other side of the globe (the servers are located in Moscow) or you sat on the Internet via GPRS. Well, or my pathetic virtual server with one core and 1 GB of RAM could not stand the habr effect.


    The question about server load is usually asked by beckenders. The change output engine works very quickly: ~ 10 thousand conclusions per second for two arbitrary trees of 500 nodes on the junior macbook of 2013. Static rendering also gives a pretty good result: up to 1 million pages per second. Each "virtual DOM" is stored and processed in a special serialized form and takes 128 KB for an average web page. The output process is specially optimized and does not have an overhead for memory and GC.


    As for the speed of development, here Korolev gives great advantages. No need to write an additional layer between the database and the server. No need to negotiate a protocol between client and server. No need to worry about the modularity of the front-end - the JS weight on the client will always remain the same. No need to do additional logic for server events: just accept the message from the queue and change the state of the session, Korolev will render and deliver.


    Price


    You have to pay for the benefits. Some habits will have to be abandoned, and some new ones to acquire. For example, you have to abandon JS animations and be satisfied with CSS animations. You will have to learn how to make the infrastructure initially geo-distributed if you want to serve users from different countries with high quality. Have to abandon JS and go to Scala.


    I am a little ashamed (actually not) that I misled the reader and did not immediately say that Korolev was written in Scala. Would you read up to this point if I immediately spoke about this? Talking about the Queen, I have to overcome two stereotypes. The first is due to the fact that server rendering is perceived as something slow, not interactive. The second is related to the fact that Scala is something complicated. And the first and second stereotype have nothing to do with reality. Moreover, programming in React style on Scala is more convenient than on JS. Modern JS gravitates towards functional programming, Scala takes it out of the box. For example, any object in Scala has a method copy()that allows you to copy an object by changing some fields. Immutable collections are built into the Scala standard library.


    Conclusion


    Korolev has been developed for three years by several developers and many "children's" problems are resolved in it. The project is well documented, all functionality is covered with examples. I propose to begin the implementation of the Queen with small independent services. I hope Korolev helps make the programs less disappointing.


    Link to the project on github


    Also popular now: