Cyber-enhanced Web Applications

The modern frontend has gone a long way since jQuery and conventional HTML pages. We now have assemblers, package managers, a component approach, SPA, SSR and much more.







It seems that we have everything that is needed for happiness. But the industry is moving forward. I want to tell you about the compiled Svelte framework, and what advantages it has over analogues.









Image by Andrew Walpole









To understand the current situation in the front-end, I analyzed the popularity of queries in Google Trends for the keywords React, jQuery, Vue, Angular in Russia over the past 5 years.









Google trends







Over the past 5 years, the number of queries related to jQuery has dropped significantly, giving way to component frameworks. Although jQuery has lost ground, it is still a popular development tool.







From this graph it can be concluded that component libraries won the front end, and React is the leader in Russia.







Labor market



We write the code not only for ourselves, but also for money. Mostly for the money. Therefore, it is foolish to consider the popularity of frameworks in isolation from the labor market.







By the number of vacancies on hh, React is in first place, followed by jQuery and other component libraries. If we look at the number of applicants who indicated the libraries in question in their key skills, then jQuery knows 5 times more applicants than React. And 15 times bigger than Angular.









Labor market







The following conclusions can be drawn from this graph:









So, component frameworks won. Frontend solved the problems that developers faced during jQuery. But new approaches give rise to new troubles. What problems do I see?







  1. Performance.

    In January of this year, Google announced the possibility of publishing PWA applications on google play, paving the way for javascript in the native application store. This imposes a certain responsibility on developers, because users expect the performance of native applications, there should be no difference for the consumer.

    Javascript also conquers low powered devices. This is a smart TV, watch, IoT. Such devices have a limited budget of memory and processor, so developers can not afford to waste their resources on the user.

    At work, we have experience running React applications on an Internet hub. It turned out so-so.
  2. High entry threshold.

    As we saw above, most job seekers point to jQuery skills, not react. Mastering the concepts of React is much more difficult than connecting to a jQuery page and starting to create.
  3. Dependence on the framework.

    If you have a component library written in React, you are unlikely to be able to reuse it in a Vue or Angular project. You become a hostage to the ecosystem.


Svelte. Vanilla flavored.



In April of this year, the third version of the compiled Svelte framework was released.

Svelte offers developers the ability to write high-level declarative code that, after compilation, turns into low-level imperative code. This also makes it possible to do effective tree shaking, and as a result allows sending a minimal bundle to the client.

Let's see what solutions Svelte offers for the sounded problems.







Since React is the most popular library in Russia, further examples will be on React.







1. Performance



If you are starting to get acquainted with the new library, then most likely you will start the tour with a ToDo list. This is a fairly simple task, which is often easier to write in vanilla. If you want to delve deeper into the framework, then a review of Real World Application is a great choice. This is a blog that is essentially a clone of Medium. There is registration, authorization, creating posts, commenting, likes. The framework experts write the implementation of the functionality and add it to the Real World Application collection.

An article on comparing Real World Application written in different frameworks was published on FreeCodeCamp.

If we look at the size of the final bundle, then Svelte outperforms its competitors. Only 9.7kb of code is sent to the client. As a result, it takes less time to transfer data, parsing and processing your code.









Real World Application bundle size comparison







And the best code is not written code.

If we look at the number of lines of code needed to write the application’s functionality, then Svelte will need about 1,000 lines, and React about 2,000 lines. The less code in your application, the less bugs and easier support.









Real World Application Code Size Comparison







Let's take a look at performance. js-framework-benchmark offers a comparison of rendering performance among front-end frameworks. The test is to draw a table with a large number of rows. Further manipulations with this table are made: partial or full update, creation, cleaning, deleting of lines.







By time of update, Svelte shows the best or comparable time. Svelte is very balanced, there are no distortions when performing different types of operations.









Comparison of update execution time, ms







If we look at the amount of memory consumed, then Svelte is the least voracious among the considered libraries.









Comparison of the amount of consumed memory, mb







I was not used to taking a word and decided to check everything myself. I found an implementation of the DBMonster benchmark for the front end and rewrote the implementation on React 16.8 and Svelte 3. The test consists in rendering the table and then updating the rows.









What does the DBMonster test look like?







During the test, Svelte consumed 10 MB less memory and updated 10 ms faster than React.









Svelte / react







The above tests are synthetic, but from them it can be concluded that when developing on Svelte out of the box you get:









2. High entry threshold



If we look at the simplest component on React, then you need to import React itself, write a function that will return the markup and export your component. Total 3 lines of code.







import React from 'react'; const Component = () => (<div>Hello</div>); export default Component;
      
      





If we look at the simplest example of a component on svelte, then you just write the markup. Total 1 line of code.







 <div>Hello</div>
      
      





Strictly speaking, the simplest Svelte component is an empty file. This makes it possible to create a template for your application from empty files, and then begin development. In this case, nothing will break.







You can also take the layout received from the typesetter and immediately use it as a Svelte component without additional transformations. Valid html is a Svelte component.







I want to share an example from an interview on the position of middle react developer.







 setFilter() { this.switchFlag = !this.switchFlag } ... <button onClick={setFilter}>Filter</button>
      
      





The candidate tried to save the state of the filter button directly into the class property. React, despite its name, is not reactive enough to respond to such changes. This suggests that even middle developers find it difficult to get the state update patterns that React uses.







Let's look at an example of a button that increases the counter by a click.













On React, you need a variable to hold state and a function that can update state. Next, you need to assign a handler for the update to the button itself. In total, I got 8 lines of code.







 import React from 'react'; const Component = () => { const [count, setCount] = React.useState(0) return <button onClick={() => setCount(count + 1)}> Clicked {count} </button> } export default Component;
      
      





To solve a similar problem on Svelte, you need a variable to store state. Further in the handler, you simply change the value of this variable. Total 6 lines of code.







 <script> let count = 0; </script> <button on:click={()=>count+=1}> Clicked {count} </button>
      
      





Let's complicate the example a bit. Suppose we need an input field that displays its state next to it.













On React, we still need a variable and function to update the state. Then, in the input field, you need to transfer the current value and assign a handler to the changes. I ended up with 11 lines of code.







 import React from 'react'; const App = () => { const [value, setValue] = React.useState(''); return ( <React.Fragment> <input value={value} onChange={e => setValue(e.target.value)} /> {value} </React.Fragment> ); } export default App;
      
      





To solve this problem on Svelte, you need a variable that stores state, and then just do two-way binding in the input field. Total 5 lines of code.







 <script> let value = ''; </script> <input bind:value={value}/> {value}
      
      





If you have ever animated the removal of an element from the DOM on React, then I sympathize with you. React will require either a wrapper who will delay the removal of the element from the DOM and make the animation, or the element will remain in the DOM, but the animation will require control of the display property or other manipulations so that the element does not take up space.













I tried to find the simplest implementation on React, in the end I got 35 lines of code. If you have a simpler solution, share in the comments.







Fadein fadeout react
 import React from "react"; import "./style.css"; const App = () => { const [visible, setVisible] = React.useState(true); return ( <React.Fragment> <button onClick={() => setVisible(!visible)}>toggle</button> <div className={visible ? "visible" : "invisible"}>Hello</div> </React.Fragment> ); }; export default App;
      
      





 .visible { animation: fadeIn 0.5s linear forwards; } .invisible { animation: fadeOut 0.5s linear forwards; } @keyframes fadeOut { 0% { opacity: 1; } 100% { opacity: 0; display: none; } } @keyframes fadeIn { 0% { opacity: 0; } 100% { opacity: 1; } }
      
      





On Svelte, a similar component requires only 8 lines of code. Svelte has a built-in module for managing animations. You import the desired kind of animation, and then say how to animate your component when adding and removing.







 <script> import { fade } from 'svelte/transition'; let visible = true; </script> <button on:click={()=>visible=!visible}>toggle</button> {#if visible} <div transition:fade>Hello</div> {/if}
      
      





Compilability allows Svelte to provide cool abstractions to the developer. And if you do not use them, they will not fall into the final bundle.







For example, the transition module has a cool crossfade functionality that allows you to animate a component when moving from one DOM node to another. Using it, you can make such a task transition in the ToDo list.













Another example of cool abstractions is the use: directive. It allows you to assign a custom handler to a DOM element. The example below handles the events of pressing and moving, as well as touch events using just one function.













After getting to know Svelte, my friends usually say that they have not experienced such a lot of fun with front-end development since jQuery.







3. Dependence on the framework



When React arrived, there were a lot of jQuery widgets on the web. Finding the right component on React was difficult. Then wrappers for jQuery widgets began to appear, which were able to synchronize React and jQuery. After that, components written on React itself have already begun to appear.

Now a similar situation with React itself. There are a bunch of ready-made solutions and libraries that do not allow you to transfer to another framework without pain.







What does Svelte offer? After compilation, your code turns into regular JS, which does not require runtime. This makes it possible to use the Svelte component in other frameworks. You just need one universal wrapper. For example, an adapter for React and Vue svelte-adapter . By wrapping the component in the adapter, you can use the element as a regular component.







 import React from "react"; import SvelteSpinner from "svelte-spinner"; import toReact from "svelte-adapter/react"; const Spinner = toReact(SvelteSpinner, {}, "div"); const App = () => <Spinner size={50} />
      
      











Svelte supports compilation in the custom element, which further expands the scope of application of components. You can see custom element support with various frameworks at custom-elements-everywhere .







Personal experience



I can’t write at Svelte at work yet, because we are sitting tight on the React ecosystem, but I have personal projects.

I previously wrote how I published my Metalz app on Google Play.













According to my feelings, Svelte allows you to write more concise and understandable code, while providing a wide range of tools to simplify implementation.







Minuses



Like any young framework, Svelte has a small ecosystem of ready-made solutions and few articles where you can find best practices. Therefore, I would not recommend immediately taking Svelte for large projects, since you can end up in an architectural dead end.







Try Svelte on small projects, I'm sure you will like it.








All Articles