My experience with an unconventional approach to building a group of React apps

Introduction

Before starting, I want to notify that I have no desire to somehow offend or promote my point of view as true. All systems, applications, modules and functionality, one way or another, were made for some reason, this is the way and this is normal! I am writing this article in order to improve similar systems in our cozy community:

In this article I will try to talk about one of the systems built on React and TS with which I managed to work, subjectively describe its pros and cons, and also touch on the topic of what could be improved within the system.

If you have any comments (or find the article stuffy), additions, or you can somehow write an article better, then please write about it in the comments, it will be very interesting for me to read 🙂


A bit of pain from the project:

  • Full copy of the entire source directory => Paste the directory and manually delete unnecessary parts

  • Virtually no reusable components

  • Global styled files without modularity or CSS-in-JS

  • Writing Styles With Ids And Tags

  • We need new features, and this will not bring money to the business (c)

Perhaps we have a general experience of working with similar projects and you understand all the discomfort, if yes then welcome to the cat 🙂 otherwise, go through anyway, because I will try to write about useful things.


About the system

In order to add meaning to the text below, I will describe a little what the system was made for:

  1. Preparing small snippets of code for insertion into a mobile application via WebView

  2. Conducting AB testing to increase product conversion (that is, if people do not buy services anymore, the directory with features is deleted or goes to the deprecated folder)

This system has 2 types of applications Screens and Widgets, their main difference is where WebView will later insert them into the mobile application, and probably that’s all 🙂

Screens and Widgets this is a set of directories where each Webpack is built as a separate React application, the application also has its own config and config in fixtures directory

This architecture was made with the goal that each subsequent application (hereinafter I will call it a screen) could be very different from the previous one and make it possible to visually customize it as much as possible.

The key structure of the application root looks like this:

{
  .storybook: "Конфиги для общей настройки сторибука",
  node_modules: "Куда же без них",
  scripts: "Общие скрипты с функциями",
  
  src: {
  	js: {
  		fuxtures: "Конфиги для тестирования",
			components: "Буквально пару переиспользуемых компонентов",
  		screens: "Директория с приложениями",
  		widgets: "Другая директория с приложениями"
		},
		img: "Общие стили",
		styles: "Директория с общими стилями",	
		index.html: "Корневой html шаблон для приложений"
	}

	// И некие стандартные вещи вроде
	tsconfig.json,
	package.json,
	jest.config.js,
	postcss.config.js,
	webpack.common.js
	...
}

The structure of the screen or widget is as follows:

{
	components: "Компоненты под текущий экран или виджет",
  colorThemeStylesheet.tsx: `
  	Файл в котором через react-helmet устанавливаются css переменные,
    значение которых берется из конфига или конфига фикстуры если 
    он имеется.
  `,
  config.ts: "Локальный конфиг экрана",
  id999.pcss: "Стили для экрана или виджета, где 999 это id текущего экрана",
  id999.stories.ts: "Конфиг для storybook",
  index.ts: "Входной файл для сборки вебпака",
  Screen.tsx: `
  	JSX код в основном в нем содержится весь код, 
    который в редких моментах вынесен в локальные компоненты
  `
}

The principle of creating a new screen

We take a directory with similar functionality, do CTR + C => CTR + V, add a pinch of magic fixture config and voila! It seems like our promo is ready, but we need to make not a 100% copy of another screen, but with differences, we make them for experiments and then a dull mechanical hell begins.

Suppose we have in the screen that we copied there is the following functionality:

And according to the TK you need:


We start walking in circles of routine

DFirst, we have to manually delete from Screen.tsx all JSX slider markup and “stock description” markup =>

NSGo to the styles of this screen, look for all the places where you need to delete (which by the way we can completely skip to ourselves due to the fact that they can be stylized in completely different ways, which will lead to a snowball when this screen is copied) =>

NSgo to ColorThemeStylesheet.tsx and remove the places of the sv-va config that are not used =>

Havewe take extra parameters and interfaces with types from our config.ts =>

ANDdem in fixtures, repeat the process =>

NSRename the directory to new screen =>

NSrenaming the stylesheet and storybook =>

V we wrap the stylesheet in our screen id to encapsulate the styles for the storybook (because all screens and widgets are displayed in the storybook, and if you do not do the above, then the storybook can float) =>

ANDdem in 100 screen we are looking for JSX markup of animation “blinking eyes”, insert it, insert styles to it, insert ColorThemeStylesheet some sv-va config and fixtures (having previously added the types in the config and the values ​​themselves), insert and understand that in 100 it was implemented crookedly or with very different functionality =>

Lwash the keyboard against the wall => get a new one out of the drawer

NSrepeating the process of removing animation =>

Berem from 102, repeat the insertion process with your hands

ANDwe create “shares” or typeset this block ourselves (so that later it can be deleted in the child screen)

V in the best case, after all this, the end (in a frequent review it will not be approved, because something is left in the config, in the fixed config, in styles, in markup, in logic, in pictures, in the ColorThemeStylesheet file, etc.) and as soon as the long-awaited approval passes, you must repeat the cycle with the next blot and so on until the weekend.


Advantages and disadvantages

pros

Minuses

Maximum customization of screens and widgets.

Time-consuming screen creation and errors due to the human factor of inattention, even with minimal differences in functionality

View all screens and widgets from the storybook, the ability to transfer to the storybook parameters of the sv-va for visual testing

There is no way to quickly find out which screen has this or that functionality

There is no way to quickly reuse any functionality

A snowball of potential bugs

There is no way to fix this or that part of a group of screens due to a missed error

When copying an ancient screen, the revuter will require the removal of an adjacent coma from mistakes that were made earlier and do not apply to the task

As we copy and paste our screens, git thinks that these are new files, which means that there will be a lot of things in the review.


Possible improvements

  1. Moving most of the functionality into reusable components to avoid a snowball, make it easier to understand how the screen works and speed up development when using default interface elements

    PS since our system must be as flexible as possible, we must use the composition of elements and if there is a need to change the component use Themebut don’t change our component Modalas it may affect other screens.

    Item # 1
    Item # 1
  2. Creation of a certain template that will assemble into an empty screen or widget (and use import of components from 1 point in it)

Item number 2
Item number 2

Conclusion

Tk I have a certain context of knowledge about the system, I could have missed something in the article that would have led to its misunderstanding, but I really hope that everything was clear and interesting 🙂

It seems to me that the improvements described above would help cleanse the system of the above-described disadvantages. What do you think can be done in this system to simplify the process of creating new screens and widgets?

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *