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)