Share code between a React Frontend and Node.js Backend Application in Nx

Share this video with your friends

Send Tweet
Published a year ago
Updated 10 months ago

As we have seen, an Nx workspace isn't only for frontend applications, but it can also host backend applications as well. By having the corresponding backend layer within the same monorepo, we can benefit from the code-sharing capabilities in an even greater way. In this lesson, we're going to define a TypeScript interface that describes the data exposed by our backend API. We host that interface in an Nx workspace library, s.t. we can use it from within our Node.js backend application as well as our React frontend app.

Instructor: [0:00] Besides the order benefits, which we already mentioned, one big plus is obviously the code sharing capabilities. In fact, if we use our dep-graph again, we can see that right now we already share some of the code and functionality among our libraries.

[0:14] For instance, right now, we have the store util formatters down here, which is a library that contains some general-purpose functions in our very specific example for formatting ratings.

[0:25] We use that rating formatting functionality here in our store application, more specifically within that app TSX component and also in the future game detail component, which lives here inside that future game detail library.

[0:38] Of course, code sharing is not only among frontend applications as it is here in this case, but we also have that backend API application. The API exposes games while also the frontend application consumes games. Basically, the same structure gets exposed by the API.

[0:57] As a result, what we can do is we can define some interfaces, especially because we're using TypeScript here to share those interfaces between the API side as well as our store application.

[1:08] For that purpose, let's go back and generate a new library and this will be a simple workspace library, which means it will just be a normal TypeScript library. We call it util interfaces and we will generate it inside a directory API.

[1:24] We can use the dry run to see what gets generated and we can see here that we got a new library inside an API folder called util interface, which is exactly what we want. Let's remove the dry run and directly generate the library.

[1:37] We now see in the libs folder, we have besides the store folder with the more store-oriented frontend libraries, also that API folder with that util interfaces library, which we just generated.

[1:48] We didn't use our interfaces, let's here use that file and create a new game interface. Let's also rename that file to game.ts. That game interface here represents basically the structure of a game. It gets exposed by our API as well as being consumed on our frontend side.

[2:08] Let's also export that here properly and then we can go on our API side and use that game TypeScript interface. In our API side, we go to our games repository and start typing this games array here.

[2:24] We can import this from nx/egghead/api-util/interfaces and here we get our game imported. Similarly, we can now go to our actual frontend application into our app.tsx file and here we get the data, which right now is typed as any, but now that we know it's of type game, we can import this here as well and that according import statement at the very top here.

[2:50] We can repeat the same procedure also in our actual library here in our store future game detail, which is the last place right now where we have to use our game. Again, we can here import the actual game interface and we can go here and type this as a game.

[3:10] Now that we have typed this, we also need to change here this initializer to null to match our types of definition. Let's restart our application. If we go back here and refresh, we see it still works as expected.

[3:25] Also, if we now inspect our actual dependency graph, we can see that much more reuse takes place. Now, we have that store application, which uses that API user interfaces as well as our store future game detail as well as our API application that exposes that game on the API side.

[3:46] As can be seen obviously, having the backhand also in the same monorepo can bring a lot of advantages because, in this way, we cannot even share just simple types as we did in our very simple example here, but maybe even some business logic that needs to be repeated on the frontend side as well as on the backend side once the data arrives.