
While working on complicated software solutions, many times we need to create multiple projects which may have some common building blocks, or some other sharing code.
Monorepos are basically the architectural pattern which sets all these multiple projects together. All the dependencies are stored in one single big repo.And makes it easy to share the code. You can know more about monorepos here.
As the title says, we are going to setup a react typescript monorepo by using the tool Lerna.
Lerna is a tool that optimizes the workflow around managing multi-package repositories with git and npm.
Also first things first, if you like my content and would love to know more about my future posts. Please follow me from the sidebar on this page. Also you can join the newsletter.
Goal
We will create two packages.
One as Application (react app container) and other as ComponentLibrary (where we can store some common components).
Our goal is to successfully set up both repo. And use code from ComponentLibrary into the Application.
If you want to skip and just download the repository, click here.
Lets start with setting up the project.
Create the base repository and setup Lerna
Let’s start by creating a folder by the name lerna-monorepo
. And install lerna as a global package
npm i lerna -g
cd lerna-monorepo
Initialize the project as a monorepo by lerna inside the lerna-monorepo
folder
lerna init
You must be able to see some folder structure like this.

Here we have the package.json
for obvious reasons. And we also have the lerna.json
to configure lerna in it.
Inside packages
we can keep the dependent modules.
Setup the react typescript webapp
For setting up the react repo, we are going to set it up from scratch. I am going to follow the official typescript react setup docs. The link is here. You can reference it for more details.
We are going to install it inside the packages folder. Let’s create a folder named as Application
.
And make two folders inside, src
& dist
.
TypeScript files will start out in your src
folder, run through the TypeScript compiler, then webpack, and end up in a main.js
file in dist
.
cd packages
mkdir Application
cd Application
mkdir src dist
Initialize project
Let’s make this repo in a npm repo. This will also add package.json
to it
npm init --y
Folder structure must be looking like this now.

Install dependencies
Webpack will be useful to convert the .ts file into a single big .js file.
That @types/ prefix means that we also want to get the declaration files for React and React-DOM.
Let’s run below commands to install these.
npm i react react-dom --save
npm i @types/react @types/react-dom webpack webpack-cli --save-dev
Now let’s install typescript and other dependencies which will help us to convert the code from .ts to .js.
npm i typescript ts-loader source-map-loader --save-dev
Add Typescript config file
Create a file called as tsconfig.json
in the Application
folder and paste the following content inside.
{
"compilerOptions": {
"outDir": "./dist/",
"sourceMap": true,
"noImplicitAny": true,
"module": "commonjs",
"target": "es6",
"jsx": "react"
}
}
Add index.tsx file
Create index.tsx
file in the Application/src
folder
import * as React from "react";
import * as ReactDOM from "react-dom";
export interface HelloProps { name: string; }
class Hello extends React.Component<HelloProps, {}> {
render() {
return <h1>Hello from {this.props.name}!</h1>;
}
}
ReactDOM.render(
<Hello name="Application" />,
document.getElementById("example")
);
Add index.html
Create index.html
file in the Application
folder
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello React!</title>
</head>
<body>
<div id="example"></div>
</body>
</html>
Create webpack configuration file
Install html-webpack-plugin, so that the index.html
file can have the js inserted by itself.
npm i html-webpack-plugin --save-dev
Add file webpack.config.js
to the src/Application
folder.
const path = require("path");
const HWP = require("html-webpack-plugin");
module.exports = {
mode: "production",
// Enable sourcemaps for debugging webpack's output.
devtool: "source-map",
resolve: {
extensions: [".ts", ".tsx", '.js'],
},
module: {
rules: [
{
test: /\.ts(x?)$/,
exclude: /node_modules/,
use: [
{
loader: "ts-loader"
}
]
},
// All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
{
enforce: "pre",
test: /\.js$/,
loader: "source-map-loader"
}
]
},
plugins: [
new HWP({
template: path.resolve(__dirname, "index.html"),
filename: "index.html",
inject: "body"
})
]
};
Now webpack is all setup. If you run the below command from folder pakcages/Application
, You will be able to run index.html
in the browser and will be seeing “Hello from Application”
npx webpack

Obviously, we won’t be running npx webpack after every single line of code change. We want the page to refresh as the code is changed. For that we will use webpack-dev-server.
Let’s install it
npm i webpack-dev-server --save-dev
Also lets make an entry of webpack-dev-server command into the package.json. Add this to the package.json.
"scripts": {
"start": "webpack-dev-server"
},
If we run npm run start
now, we will be able to access the localhost link where we can view the same result.
Setup the shared folder
So far so good, we have created the monorepo setup, we have installed the react typescript app. Now we need to create another package, which we can use inside of our Application.
Let’s call it ComponentLibrary
, where we can keep all our common components to reuse in different applications
cd packages
mkdir ComponentLibrary
Folder structure looks something like this now.

Let’s initialize npm inside ComponentLibrary
npm init --y
Installing Dependencies in ComponentLibrary
We are going to need react and @types/react packages for now.
npm i react --save
npm i @types/react --save-dev
Create index.tsx
file in the ComponentLibrary
folder and put the following code inside.
import * as React from 'react';
const ComponentLibrary = () => {
return (
<h1>Hello from ComponentLibrary!</h1>
)
}
export default ComponentLibrary;
Connect everthing
We made the Application and the ComponentLibrary packages.
Now it’s time to connect these together.
Let’s add ComponentLibrary as npm package into Application. And also whenever something is changed in ComponentLibarry, the application should update.
Add following code in Application/package.json
"dependencies": {
"html-webpack-plugin": "^4.3.0",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"ComponentLibrary": "1.0.0"
..
We have added it as dependency, but npm would not be able to find ComponentLibrary anywhere.
Now to actually get this package from the neighbour, we need to run one more tiny step.
Go to the root directory i.e lerna-monorepo
and run
lerna bootstrap
This command will link the dependencies together in the repo.
Let’s add the ComponentLibrary into Application/src/index.tsx
. Edit the file as below.
...
class Hello extends React.Component<HelloProps, {}> {
render(): JSX.Element {
return (<>
<h1>Hello from {this.props.name}!</h1>
<ComponentLibrary />
</>);
}
}
...
Now if we go to packages/Application
and run
npm run start
We are going to see something like below.

Extra Tip: You can also call run the project from base directory i.e. lerna-monorepo
, you just have to add the below script in the root level package.json
{
"name": "root",
"private": true,
"devDependencies": {
"lerna": "^3.22.1"
},
"scripts": {
"start": "npm start --prefix packages/Application"
}
}
Using this boilerplate code, you can expand your monorepo furthur.
Thanks for reading!
Application can’t find Component Library.
I get this error: TS2304: Cannot find name ‘ComponentLibrary’.
sorry, may bad. forgot to import it on the Application index.tsx.
my bee you can add the import into Application/src/index.tsx code example.
great tutorial by the way.
thanks, and you can remove my comments.
Hope u found it. Thanks Haniel. 🙂