paint-brush
Enlarge your DRY :  How to Share Values Between Web App Backend and Frontendby@lebedevsergey
1,212 reads
1,212 reads

Enlarge your DRY :  How to Share Values Between Web App Backend and Frontend

by Sergey LebedevFebruary 6th, 2021
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

REST API endpoints paths list which backend uses to route API requests and frontend uses to make backend API requests.

Company Mentioned

Mention Thumbnail
featured image - Enlarge your DRY :  How to Share Values Between Web App Backend and Frontend
Sergey Lebedev HackerNoon profile picture

In almost any web application there is some set of values that are used on both backend and frontend parts. The typical case is REST API endpoints paths list which backend uses to route API requests and frontend uses to make backend API requests. Sometimes there are some user input validation values that are used at the same time in frontend and backend input validation. Or some other values like numerical ids, localization strings or even your Web-application name.

The vast majority of modern Web-applications are made from frontend and backend parts. The first one is usually written in JavaScript or transpiled to it. Backend however might be written in a whole range of programming languages, from PHP to Haskell. It can also consist of several parts in different programming languages — as trendy microservice architecture suggests. And sometimes it is written in JavaScript — the same programming language as frontend uses. But even then the backend and the frontend are still two different parts of the application.

Of course it would be nice to set all double-used constants in one place only as it follows DRY principle and helps to avoid inconsistencies — for example when some of these values are changed only in one part of Web-application and do not meet the same value in its another part.

How can we share values between application parts? Well, there are different approaches. Shared values might be:

  • Declared in one piece of code that is included in backend and frontend parts
  • Placed in a shared configuration file
  • Provided to frontend by a special backend API that returns shared value
  • Defined in backend-generated JavaScript code that declares shared values added it to coming from backend HTML

Let’s review each of listed approaches in more detail.

Declaring constants in one piece of code for both parts

It is simple and implements the DRY principle literally. It would be an ideal solution but unfortunately it works only when both backend and frontend are written in JavaScript, which is not always true.

Sharing configuration file with constants values

It seems to be very similar to the previous approach but there are additional peculiarities here. Firstly, both parts of the application should be able to read configuration file format, for example, YAML. Secondly, the configuration file should be accessible for both application parts.

This requires placing the configuration file at some publicly accessible resource like application public assets folder. But it isn’t very clear architecture — why a YAML file is placed in assets with? It also increases potential attack area and requires additional code to parse configuration file

Backend constants API

Here constants are set in backend code and a special backend API method is created which the frontend part uses to get shared constants. This complicates application code because it requires additional backend code implementing constants API method and additional frontend code that reads and injects constants values into Javascript code scope.

Code generation approach

In this approach generated code defining shared values is injected in the frontend. As the typical Web-application frontend part is very likely written in JavaScript shared values will be put in a generated chunk of JavaScript code with several constants definitions which then will be included in the frontend code — with simple include JavaScript statement or as a JavaScript module.

The injection of shared values in the frontend code variables scope can be done in a couple of ways:

  • global shared values definitions — not the most elegant solution as those shared values constants will pollute the frontend global namespace
  • put shared constants definitions into a global class — which is more elegant
  • put shared constants definitions into a class and injecting it into the frontend with some kind of Dependency Injection technique — a bit overengineered implementation for my taste
  • put some shared constants into a state management pattern stuff like Redux —  seems to be the same idea as putting in a global class

In my opinion, of all solutions discussed above the code generation approach is the best one. Code generation can be done on Web-request when the backend gives site page code or during frontend code pre-processing and building phase. The latter is better as it allows you to generate code only once during bundling the frontend code and avoid overhead of doing code generation each time on Web-request. But I do not know tools doing that for JavaScript bundlers like Webpack or Parcel. A plugin like this should be able to parse shared constants values definitions from backend part code which requires creating plugins for the most used backend programming languages.

On the other hand, code generation on Web-request is easier to implement as it is enough to have reflection mechanism in the programming languages used by backend in order to get shared constants values defined in some part of backend code. For example, I use this approach in my phpconst2js library and it works perfectly.

So we discussed different approaches to sharing constants between Web-application backend and frontend. And as often happens in engineering there is no ideal solution — each of those approaches has its pros and cons.