DEV Community

ynwd
ynwd

Posted on • Edited on

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)