Web App in Mono repo

In here I am going to add an application project, which will be using some of the libraries we have in our mono repository. In this case, I will be creating a Single Page Application, using React, as an example.

Create React SPA #

cd packages
npx create-react-app spa

Lets update packages/spa/package.json name:

"name": "@mr/spa",

At our root package.json at scripts add:

  "scripts": {
    "start:spa": "cd packages/spa && yarn start"
  },

Lets add our internal libraries using Lerna:

yarn lerna add @mr/types @mr/utils --scope=@mr/spa

I was expecting it to work, however it fails. For what I see, it is only possible to add a library as dependency at a time, using lerna. I read more about it here

Experiment with

yarn lerna add @mr/utils --scope=@mr/spa

Followed by

yarn lerna add @mr/types --scope=@mr/spa

In this case, we have created our react-app with javascript, so @mr/types will not be very useful.

Lets start using our books in our React Application. Go to packages/spa/src/App.js and update it to:

import { allBooks } from "@mr/utils";

function App() {
  return (
    <div>
      <h1>List of Books</h1>
      <ul>
        {allBooks().map(function renderBook(book) {
          return (
            <li key={book.id}>
              {book.title} from {book.author}
            </li>
          );
        })}
      </ul>
    </div>
  );
}

export default App;

Now lets do a change on @mr/utils and check if we get it. Lets add a tag property to our books. We will need to change @mr/types as well.

On @mr/types I have updated src/Book.ts to:

export interface IBook {
  id: string;
  title: string;
  author: string;
  tag?: string;
}

export function bookToString(book: IBook): string {
  return `${book.title}`;
}

tag was added as an optional property to IBook interface, representing our books.

Now, lets go to @mr/utils. I update books array at src/booksService.ts with a tag for each book:

const books: IBook[] = [
  {
    id: "1",
    title: "Clean Code",
    author: "Uncle Bob",
    tag: "Software",
  },
  {
    id: "2",
    title: "The Pragmatic Programmer",
    author: "Andy Hunt and Dave Thomas",
    tag: "Software",
  },
];

However we see VSCode is warning us with an error. I am going to execute lint:

yarn lerna run lint

No error was found, because it is a typescript error, and eslint is not configured to check those types.

Ok. We are going to link all of our dependencies:

yarn lerna bootstrap

Already up-to-date.

We changed @mr/types and @mr/utils, so we need to rebuild it:

yarn lerna run build

And now errors disappeared. We will want to automate this process to improve the Developer Experience. It would be good to have packagesrebuild automatically when a change happens. I will do it later.

For now, lets go back to our Single Page Application in React and show tag for each book. Our packages/spa/src/App.js:

import { allBooks } from "@mr/utils";

function App() {
  return (
    <div>
      <h1>List of Books</h1>
      <ul>
        {allBooks().map(function renderBook(book) {
          return (
            <li key={book.id}>
              {book.title} from {book.author} about {book.tag || ""}
            </li>
          );
        })}
      </ul>
    </div>
  );
}

export default App;

And it was updated on http://localhost:3000.

Next, I will try the same for a react-native application.

Published