Forem

ynwd
ynwd

Posted on • Edited on

7 2

How to create react monorepo with npm workspace, webpack, and create-react-app

Workspaces is a generic term that refers to the set of features in the npm cli that provides support to managing multiple packages from your local files system from within a singular top-level, root package. (npm workspaces)

.
├── package.json
│
└── web
    │
    ├── components
    │   └── package.json
    │
    └── modules
        │
        ├── home
        │   └── package.json
        │
        └── root
            └── package.json
Enter fullscreen mode Exit fullscreen mode

repository: https://github.com/ynwd/monorepo/tree/init

Create and enter app directory

mkdir mono && cd mono
Enter fullscreen mode Exit fullscreen mode

Create components and modules dir

mkdir -p web/components web/modules
Enter fullscreen mode Exit fullscreen mode

Create shared components

cd web/components
Enter fullscreen mode Exit fullscreen mode

init a package

npm init -y
Enter fullscreen mode Exit fullscreen mode

install webpack

npm i webpack webpack-cli -D
Enter fullscreen mode Exit fullscreen mode

install react

npm i react react-dom
Enter fullscreen mode Exit fullscreen mode

install babel and webpack loader

npm i @babel/core @babel/preset-env @babel/preset-react babel-loader -D
Enter fullscreen mode Exit fullscreen mode

create a first component

// src/index.js
import React from "react"

const Header = ({ text = "" }) => {
    return (
        <h1>Shared header library {text}</h1>
    )
}

export {
    Header
}
Enter fullscreen mode Exit fullscreen mode

create webpack config

// webpack.config.js
const path = require("path")

module.exports = {
    mode: "production",
    entry: {
        index: { import: "./src/index.js" }
    },
    module: {
        rules: [
            {
                test: /\.jsx?$/,
                exclude: /node_modules/,
                loader: "babel-loader",
            },
        ],
    },
    output: {
        filename: "components.bundle.min.js",
        library: 'fstrComponents',
        libraryTarget: 'umd',
        clean: true
    },
}
Enter fullscreen mode Exit fullscreen mode

create babel config

// babel.config.js
module.exports = {
    presets: [
        [
            "@babel/preset-react",
            {
                targets: {
                    node: "current",
                },
            },
        ],
    ],
};
Enter fullscreen mode Exit fullscreen mode

update package name, module, and script:

// package.json
{
  "name": "@fstr/components",
  "version": "1.0.0",
  "description": "",
  "module": "dist/components.bundle.min.js",
  "scripts": {
    "build": "webpack",
    "build-watch": "webpack --watch",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.15.8",
    "@babel/preset-env": "^7.15.8",
    "@babel/preset-react": "^7.14.5",
    "babel-loader": "^8.2.2",
    "webpack": "^5.58.1",
    "webpack-cli": "^4.9.0"
  },
  "dependencies": {
    "react": "^17.0.2",
    "react-dom": "^17.0.2"
  }
}
Enter fullscreen mode Exit fullscreen mode

build

npm run build
Enter fullscreen mode Exit fullscreen mode

Create react app

back to app root dir

cd ../../ 
Enter fullscreen mode Exit fullscreen mode

create root module

npx create-react-app web/modules/root
Enter fullscreen mode Exit fullscreen mode

create home module

npx create-react-app web/modules/home
Enter fullscreen mode Exit fullscreen mode

update all packages name

{
  "name": "@fstr/home"
}
Enter fullscreen mode Exit fullscreen mode
{
  "name": "@fstr/root"
}
Enter fullscreen mode Exit fullscreen mode

Link all modules and components together

still in the app root folder, create npm workspace

// package.json
{
    "name": "@fstr/monorepo",
    "private": true,
    "version": "1.0.0",
    "workspaces": [
        "./web/*",
        "./web/modules/*"
    ]
}
Enter fullscreen mode Exit fullscreen mode

Link all modules and components together.

npm install
Enter fullscreen mode Exit fullscreen mode

This will create symlink on node_modules.

Now you can run all modules from app root dir.

npm run build -w @fstr/components
Enter fullscreen mode Exit fullscreen mode

Run root module

npm start -w @fstr/root
Enter fullscreen mode Exit fullscreen mode

Run home module

npm start -w @fstr/home
Enter fullscreen mode Exit fullscreen mode

Import shared component from modules

Now you can import shared component from all modules

// web/modules/root/src/App.js
import logo from './logo.svg'
import './App.css'
import { Header } from "@fstr/components"

function App() {
  return (
    <div className="App">
      <Header text="from root" />
    </div>
  )
}

export default App

Enter fullscreen mode Exit fullscreen mode

Run the root module to see the changes

npm start -w @fstr/root
Enter fullscreen mode Exit fullscreen mode

Top comments (0)

Postmark Image

Speedy emails, satisfied customers

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up