1 + 1 + 1 + 1 doesn’t equal to 4

Man from IT Space
Roonyx BNPL platform
5 min readMay 5, 2021

Or how to develop 4 business apps for the price of 3 using Nx?

If in advance you decide what applications you will need in the future and develop them as a single system now, you will save money and time on at least testing a couple of dozen hypotheses in marketing. And perhaps launch one more business.

However, many customers do not know about this feature, because very few developers can implement it with Nx, and thus they do not offer it.

We know how and we practice it. Let me give you an example.

About the business and money

A client with a restaurant business reached out, tormented by excel. Right on the threshold of opening in a new location. They wanted to update their website and create an app for online deliveries. For the immediate, but still, future, he postponed the creation of solutions for staff management and accounting of goods in the warehouse.

Conclusion. Implementation plan:

-A website with an online delivery function
-Delivery App
-Inventory Management App
-Staff Management App

If we first create the site and the app, in six months we would start accounting for the goods, and in a year we would be involved with staff management, then that would be costly to our client:

$15k (site upgrade) + $40k (delivery app) + $30k (inventory management app) + $25k (staff management app) = $110k.

Now imagine. We build a website, for example, using Angular. We create a UI and backend for the layout of products on the site. We waste your time and money on thinking, drawing, and implementing. Then we start making the delivery app, and we need to re-create the UI and backend for the product layout. The business is the same, the brand and the design are the same. But money is spent again. And then more money will be spent when we will develop an application for accounting for goods.

And you can develop and design most of the similar application components at once, using them in all 4. The frontends and backends of the 4 applications will be combined into one system. While they can look like 4 completely different ones, each has its own admin panel and input.

Then you get this picture:

site upgrade + delivery app + inventory management app + staff management app = $75k.

Pleasant? The client also liked this option so we started developing a single system of 4 applications using a common component base.

We created applications using different Frameworks and approaches. But with Nx, this was not a hindrance. It helped us:

- combine 4 applications with a frontend on Angular and React, a backend on Nest using common component libraries;
- reduce the amount of code and increase its quality;
- develop fast and uniformly.

The customer was happy. For clarity, here are some similar components in the applications that we managed to save money on:

About Nx and the development process

Well, now about the technical side. Let’s reproduce the process.

To get started, we need to prepare a place for this, we will create a new Nx workspace. Let’s use npx.

npx --ignore-existing create-nx-workspace nxws --preset=empty

This is the preparatory stage. It would be nice to add some applications to our project. To do this, we will add the ability to create applications, starting with Angular.

npm i @nrwl/angular

Still, nothing works, now we can finally create an application. Nx creates a structure slightly different from the standard one for an Angular application. Applications and libraries will be located separately. We’ll soon see how useful this will be.

nx g @nrwl/angular:app angularapp

The first application is created.

Now we need to repeat similar actions several times. Let’s create an application with React. For this, we will first add a diagram.

npm i @nrwl/react

And create it.

nx g @nrwl/react:app reactapp

All our preparatory stages are now completed, and we can immediately move on to the pleasant part; the ability to use common code for our applications. Let’s build it.

nx g @nrwl/workspace:lib ui

We create a web component that will be common between our applications.

export class GreetingElement extends HTMLElement {
public static observedAttributes = [‘title’];
attributeChangedCallback() {
this.innerHTML = `<h1>Welcome to ${this.title}!</h1>`;
}
}
customElements.define(‘nxws-greeting’, GreetingElement);

And of course, we export it to index.ts

export * from './lib/greeting.element';

Our element is ready for use. All it remains is to prepare our applications.

First, the application is on Angular. We import our library into it

import '@nxws/ui'; // <-- the new libraryimport { enableProdMode } from '@angular/core';import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';if (environment.production) {
enableProdMode();
}
platformBrowserDynamic()
.bootstrapModule(AppModule)
.catch((err) => console.error(err));

In order not to have any issues with Angular, we register CUSTOM_ELEMENTS_SCHEMA.

@NgModule({
declarations: [AppComponent],
imports: [BrowserModule],
providers: [],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
bootstrap: [AppComponent],
})
export class AppModule {}

Now we can use our component in app.component.html

<div style="text-align:center">
<nxws-greeting [title]="title"></nxws-greeting>
<img
width="300"
src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-logo.png"
/>
</div>
<p>This is an Angular app built with <a href="https://nx.dev">Nx</a>.</p>

To use our component in the React application, we will perform similar actions

Import the library to main.ts

import '@nxws/ui';import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { App } from './app/app';ReactDOM.render(<App />, document.querySelector('nxws-root'));

Here we need the file intrinsic.d.ts so that we can use the web components in React

declare namespace JSX {
interface IntrinsicElements {
[elemName: string]: any;
}
}

That’s it, now we can use our web component.

import * as React from 'react';
import { Component } from 'react';
import './app.css';export class App extends Component {
render() {
const title = 'reactapp';
return (
<div>
<div style={{ textAlign: 'center' }}>
<nxws-greeting title={title} />
<img
width="300"
src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-logo.png"
/>
</div>
<p>
This is a React app built with <a href="https://nx.dev">Nx</a>.
</p>
</div>
);
}
}

Now we can celebrate. Our applications on different frameworks use common web components. But we are not going to stop there. You can’t get very far on just the front-end. We need some kind of backend. To do this, we will take the application on Nest. We can use it as an API Gateway or BFF, or as a real backend. And once again, common libraries will help us. But this time we use them to create common interfaces for our applications, without any contracts between the backend and the frontend because we have real common interfaces now.

With an already familiar sequence of actions, we can create an application on Nest.

Add the schema.

npm i @nrwl/nest

And create it.

nx g @nrwl/nest:application nestapp

We need a library for interfaces. We could use the existing one, but let’s not be lazy and create another one.

nx g @nrwl/workspace:lib share

We create an interface in it and export it.

export interface Interface {
message: string
}

All is left is to use it in our applications

import { Interface } from '@nxws/share';
import { Injectable } from '@nestjs/common';
@Injectable()
export class AppService{
getData(): Interface{
return { message: 'Welcome to nestapp!' };
}
}
import { HttpClient } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';
import { Interface } from '@nxws/share';
@Component({
selector: 'nxws-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent implements OnInit{
constructor(private readonly http: HttpClient) {
}
title = 'angularapp';
ngOnInit() {
this.http.get<Interface>('/api ').subscribe(result => this.title = result.message);
}
}

And voila! We have created a common schema for the API and a framework that allows you to use common elements for different applications.

Any other questions? Always happy to answer! Ask away!

--

--

Man from IT Space
Roonyx BNPL platform

An inspired Angular & RoR virtuoso who tells about technologies and achievements of IT progress that are useful for developers and business.