📜 ⬆️ ⬇️

Behind the closed door of the front of the EFS

In this article we will talk about the library of components of the Unified Frontal System (EFS) and how the front-end platform is built in general.



One of the main tasks of the ESF program is the transformation of all frontal systems to a single technological stack. The frontal system in our context is an interface through which any user interacts with the bank. This can be an online bank - many of them know Sberbank Online and Sberbank Online for business applications, such as ATMs, terminals, interfaces of operators in branches and call-centers and other systems used by many thousands of customers and bank employees in Russia.

The main problem that we solve is the replacement of outdated code: there are many frontal systems in the bank, each has its own architecture, its own design.
')
Obviously, this is inconvenient for everyone: for customers, employees and the bank as a whole.
Therefore, the main mission of the ESF frontend is to replace the existing hodgepodge and bring everything to a single code base, to a single technological stack with a convenient and understandable user scenario.

What are the challenges facing development?



Before the ESF era, the time to launch a new technical product on the market could be up to 1 year. With EFS, we set ourselves the task of reducing the time-to-market to 1 month.
And this is just the beginning!

How is the frontend arranged at ESF?


We have a team of developers of the ESF platform, as well as application developers, whose task is to implement the business logic.

The platform team is developing a library of UI components for internal use. There are quite a few examples of such development - companies such as Google, Yandex, Avito, Mail.ru, etc. also have component libraries. The teams of applied projects use this library to implement their projects, providing feedback in case of problems.
The platform team now has 8 people. We work in two-week sprints, at the end of each of them we release a new version of the library, which contains fixes and, possibly, new components. We, of course, have code review, our own code style - we have taken the best programming practices and adapted them for ourselves.

As a toolkit, we use a set of tools from Atlassian: JIRA for setting tasks, BitBucket for git repositories, and Confluence for documentation.

What does the library consist of?



Browser support


Target browsers are IE8 +. Now IE8, if someone remembers, it was IE6 in its time: terrible API and terrible debugging. Of course, the time spent in debugging in IE8 is priceless. There were cases when the developers spent several days trying to find where the error occurred, because in IE8 there was a very poor debug toolkit and it sometimes shows that the error occurred in a completely different place.

IE support is not random, we have to work with hardware from the browser: RFID tablets, various printers, scanners, etc. The Web does not have a single standard for working with hardware: in the distant past, ActiveX was selected as the technology for working with it. The amount of software written using ActiveX is tremendous, and this does not allow us to give up the support of IE overnight and move towards modern browsers. The plans include converting outdated ActiveX to Java applets and abandoning IE8.



Technology stack


We are a kind of startup inside a large organization and our frontend technology stack is not very different from most global startups: react, redux and PostCSS. All these technologies have proven themselves at their best, and they also allow us to support IE8. However, we cannot drastically change the technology stack, since around it, a specific application architecture is tied, for example, it was React that allowed us to break one huge application into hundreds of small ones and load them on demand using SystemJS.

React


This is the first technology we have chosen for the following reasons:

  1. Allows you to break the application into components, thereby organizing a component approach to development.

  2. Easy to learn - we do not require a new colleague to know React, we just give him a couple of days to figure out the project.

  3. IE8 support. From this, in fact, it was possible to begin, because, if you look at which frameworks and libraries support IE8, it turns out that there are very few. The most popular - Angular, Ember, Vue.js - do not support him, so we were lucky with React.

Also in the development process, we began experimenting with React Native, which allowed us to release a cross-platform library of UI components. You can read about it in our first article .

How do we make friends with React and IE8?


First, we are not updating the version of React, because at some point they also refused to support IE8. Secondly, we use es3ify - this is a webpack loader, which takes our ES5 code and surpasses it in ES3. It simply replaces some things that don't work in IE8.

TypeScript


The second technology we chose was TypeScript, which is why:

  1. Strong typing
    By our standards, the any type is prohibited, however, there are exceptions to the rules, because far from everything can be covered with generics.

  2. Foolproof
    We are all human and sometimes use the wrong types, transfer the wrong data, and the compiler produces simple and understandable errors.

  3. Convenience of working with application developers
    As described above, we transfer our library to application developers. Many of them also use TypeScript, and at the compilation stage they understand how to work with components correctly.

Now in the library about 70 components. When we first started developing, we had all the components “smart”, that is, they contained a state and all the logic was inside. We had no particular problems. But, as soon as the components became more difficult, they began to invest in each other, there were a lot of them, we realized that we still had performance problems, we’ll tell you how we solved them.

Performance


First, we made the components "stupid", that is, we got rid of the state, bringing it to the application level. Now, application developers decide how to change the state, and the necessary props are only forwarded to our components.

Take an example:

export default class Input extends React.Component<Props, State> {    static defaultProps: Props = {        value: ''    }    state: State = {        value: this.props.value    }    handleChange = event => {        const value = event.nativeEvent.target.value;        this.setState(prevState => ({value}))        this.props.onChange(value);    };    render() {        return <input onChange={this.handleChange}                      value={this.state.value} />;    } } 

There is a library component Input, it has a value stored in state, it returns input in render, and it changes state in onChange. Is there a lot of code for such a component? Definitely a lot, let's refactor this example:

 export default class Input extends React.Component<Props, {}> {   static defaultProps: Props = {       value: ''   }   handleChange = event =>       this.props.onChange(event.nativeEvent.target.value);   render() {       return <input onChange={this.handleChange}                     value={this.props.value} />;   } } 

The component code has become shorter, and at the level above there is the Form component, which itself decides how to manage the state of the component: via redux or through the simplest setState. Input has become easier, and, accordingly, more productive.

Second, we adhere to the pure components architecture (PureComponent), i.e. all external properties, internal state and context are checked for compliance with the previous state. If the state has not changed, then there is no point in calling render once more. We perform this check in the method shouldComponentUpdate, which we added to all our components.

And third, we got rid of memory leaks in callbacks.

 export default class Button extends React.Component<Props, {}> {   render() {       return (           <button onClick={event => this.props.onClick(event)}>               {this.props.children}           </button>       );   } } 

In this example, the component has an onClick callback and a switch function is passed to it.
If you set it this way, then a leak occurs. In IE8, it is especially visible because every time you call render, this function is created, it accumulates, and brakes occur in the component. Let's slightly change our example:

 export default class Button extends React.Component<Props, {}> {   handleClick = event => this.props.onClick(event);   render() {       return (           <button onClick={this.handleClick}>               {this.props.children}           </button>       );   } } 

The code itself has become more concise, and besides, we got rid of the leak, since the callback function is no longer created with each call to render.

Future plans include ending support for IE8, which will allow the use of more advanced frontend technologies. In addition, we have already begun work on a large-scale project for integrating with the EFS mobile platform, have begun to develop a hybrid library that allows using the same code for both the web and mobile devices using React Native.

In the next article about the frontend of the ESF program, we will tell about how we use Redux and how it became the heart of our architecture, subscribe to our blog, so as not to miss!

Ideas, suggestions and wishes - write, we will be happy to talk with you in the comments to the article.

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


All Articles