Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
July 24, 2021 02:15 pm GMT

Lerna Workspaces - Managing Projects With Multiple Packages

Lerna workspace allows to create/manage various packages, like app (react application), web (react.js application), common (common business logic/code) needs to be implemented both in react native and react.js.

Lerna workspace manages versioning so you can create a package for some of your functionality and want to share with other applications then you can easily integrate in other packages by adding that dependency in package.json like you do for other NPM/YARN packages.

Please download full source code from our GitHub.

Related Article - Share Code Between React Native & React.js

Learn more about Yarn Workspaces - Monorepo Approach

Step by Step Lerna Integration -

If you are using Lerna for the first time, you need to install Lerna Globally.

npm install --global lerna

Let's start by creating Lerna Project,

npx lerna init // initialize lerna workspace

After finish initialization you will get following folder/files directory,

lerna-workspace  /packages  lerna.json  package.json

packages - You can put your web (Web App), app (Mobile App), common (Common Components) inside this directory

lerna.json - Contain configuration for packages

package.json - Contain dependency and lerna workspace settings

Initially in package.json you will get package name "name": "root", we will change it to "name": "@workspace/root", make sure "private": true to share packages under the workspaceSettings.

package.json

{  - "name": "root",  + "name": "@workspace/root",} 

Now, Go to lerna.json change it to following,

{  "packages": [    "packages/*"  ],  + "version": "independent",  + "npmClient": "yarn",  + "useWorkspaces": true } 

Let's change workspace settings in package.json, Change it to following

{  "name": "@workspace/root",  "private": true,  "devDependencies": {      "lerna": "^4.0.0"  },  + "workspaces": {      + "packages": [      + "packages/**"      + ]  + }}

We have setup everything in lerna.json and package.json, now lets create React.js application and common component directory

cd packagesnpx create-react-app components --template typescript // common componentnpx create-react-app app --template typescript // react.js web application

Monorepo hoist package to root, so dependency you have installed, actually installed on root node_modules instead of node_modules on each app component package.

If you see the folder structure, it will looks like,

lerna-workspace /node_modules /packages   /app      package.json      ...   /components      package.json      ... lerna.json package.json yarn.lock

Now, think you have two application using same components, instead of design & develop components separately, you can add it to /components packages and use that package wherever your want, let's see,

create-react-app-config - CRACO - help us to modify web package configuration, so let's install it,

yarn add --dev craco -W

Now, Let's change the package name for the app and components.

/packages/app/package.json

/packages/app/package.json{  - "name": "app",  + "name": "@workspace/app",}

/packages/components/package.json

{  - "name": "components",  - "name": "@workspace/components",}

Let's add components dependency into app/package.json

{  "dependencies": {    + "@workspace/components": "0.1.0",      ...  }}

We are using craco, so we need to change few settings in app/package.json scripts to following,

{  "scripts": {    + "start": "craco start",    + "build": "craco build",    + "test": "craco test",    + "eject": "craco eject"  }} 

Now, let's switch to root package.json and add scripts, Lerna has powerful scripts commands if you type build here in root package.json it will build for all child packages at the same instance.

/package.json{  + "scripts": {    + "start": "lerna exec --scope @workspace/app -- yarn start"  + }}

Now, let's execute it, execute - yarn start, it will give errors and you can't find the modules craco.config.js which we don't have yet.

For instance let's change scripts in /app/package.json to following,

{  "scripts": {    + "start": "react-scripts start"  }} 

And try to execute yarn start it will load your react app successfully. So our web app runs perfectly using lerna workspace.

Now, let's add a button in the web app and perform increment operation and save count value into state.

app/src/App.js

function App() {  const [count, setCount] = useState(0);  return (    <button      onClick={() => setCount((prev) => ++prev)}      >      Increment    </button>  )} 

Run the web app, counter increment works perfectly.

Now, let's pull button component in components, go to components directory,

cd componentscd srcmkdir components

Create new file Button.tsx inside packages/components/src/components, add following code,

import * as React from "react";interface Props { onClick: () => void;}const Button: React.FC<Props> = (props) => { return <button {...props}>Increment</button>;};export default Button;

Now, go to packages/components/src/index.tsx and change to following,

import Button from "./components/Button";export  { Button };Let's add to packages/app/src/App.js+ import { Button } from "@workspace/components";function App() {  const [count, setCount] = useState(0);  console.log(Button);  return (    <div className="App">      <header className="App-header">        <img src={logo} className="App-logo" alt="logo" />        + Your count is {count}        + <Button onClick={() => setCount((prev) => ++prev)} />     </header>   </div> );}export default App;

If you faced any compile error for App.tsx not found then, go to

packages/components/package.json and add

{  + "main": "./src/index.tsx"} 

We need to hoist our packages so execute,

yarn lerna bootstrap // this will bootstrap application and make shared components/links componentsyarn start

After yarn start you will faced error for loaders, because create-react-app webpack contain loaders, so we need to setup following,

cd packages/app/touch craco.config.js

And add the following code in craco.config.js

const path = require("path");const { getLoader, loaderByName } = require("@craco/craco");const packages = [];packages.push(path.join(__dirname, "../components"));module.exports = { webpack: {   configure: (webpackConfig, arg) => {     const { isFound, match } = getLoader(       webpackConfig,       loaderByName("babel-loader")     );     if (isFound) {       const include = Array.isArray(match.loader.include)         ? match.loader.include         : [match.loader.include];       match.loader.include = include.concat(packages);     }     return webpackConfig;   }, },};

As we have added craco.config.js so let's change scripts settings in /packages/app/package.json

{  "scripts": {    + "start": "craco start",  }} 

And finally yarn starts, web app works fine with using Button (reusable code) from components package.

Lerna Scripts -

test scripts

Lerna allows you to run scripts and execute wherever you want to do in scripts. Lets add some test scripts in root /package.json

// package.json{  + "scripts": {    + "test": "lerna run test"  + }}

Also, add scripts in packages,

// packages/app/package.json{  + "scripts": {    + "test": "echo app packages test scripts"  + }}
// packages/components/package.json{  + "scripts": {    + "test": "echo component packages test scripts"  + }}  

Now, if you run test script, lerna run test it will log run test scripts in two packages (app, components) and you will get log following,

lerna info Executing command in 2 packages: "yarn run test"lerna info run Ran npm script 'test' in '@workspace/components' in 0.5s:$ echo component packages test scriptscomponent packages test scriptslerna info run Ran npm script 'test' in '@workspace/app' in 0.4s:$ echo app packages test scriptsapp packages test scriptslerna success run Ran npm script 'test' in 2 packages in 0.9s:lerna success - @workspace/applerna success - @workspace/components

scope scripts

So, you see, lerna runs test scripts in two packages. If you want to test script of specific packages you can do it by giving scope, Change root package.json,

// package.json{  + "scripts": {    + "test": "lerna run test --scope=@workspace/app"  + }}  

Now, lets run the script npx run test, It will log following,

lerna notice filter including "@workspace/app"lerna info filter [ '@workspace/app' ]lerna info Executing command in 1 package: "yarn run test"lerna info run Ran npm script 'test' in '@workspace/app' in 0.7s:$ echo app packages test scriptsapp packages test scriptslerna success run Ran npm script 'test' in 1 package in 0.7s:lerna success - @workspace/app

You see this time script executed in @workspace/component because we have specified scope.

You can can apply multiple packages in scope by specifying like,

scope with multiple packages

// package.json{  + "scripts": {    + "test": "lerna run test --scope={@workspace/app,@workspace/components}"  + }}

It will log following -

lerna notice filter including ["@workspace/app","@workspace/components"]lerna info filter [ '@workspace/app', '@workspace/components' ]lerna info Executing command in 2 packages: "yarn run test"lerna info run Ran npm script 'test' in '@workspace/components' in 0.6s:$ echo component packages test scriptscomponent packages test scriptslerna info run Ran npm script 'test' in '@workspace/app' in 0.3s:$ echo app packages test scriptsapp packages test scriptslerna success run Ran npm script 'test' in 2 packages in 0.9s:lerna success - @workspace/applerna success - @workspace/components

Lerna Versioning

Lerna contains packages, everytime you build/commit something, it allows you to increment the package version automatically using the following versioning script.

{  + "scripts": {    + "new-version": "lerna version --conventional-commits --yes",  + }}

Learn more about conventional commit and commitzen.

Conventional commit create Git Tag and ChangeLog and Increment package version for you so you can know what you changed in each release/commit. Lets run a script, but before that commit your code and run the following.

Execute npm run new-version you will get following logs,

> [email protected] new-version /Users/kpiteng/lerna> lerna version --conventional-commits --yeslerna notice cli v4.0.0lerna info current version 1.0.0lerna info Looking for changed packages since v1.0.0lerna info getChangelogConfig Successfully resolved preset "conventional-changelog-angular"Changes: - @workspace/app: 1.0.0 => 1.0.1 - @workspace/components: 1.0.0 => 1.0.1lerna info auto-confirmed lerna info execute Skipping releaseslerna info git Pushing tags...lerna success version finished

This will create CHANGELOG.md file for you in both packages, Lets look it, Go to /packages/common/CHANGELOG.md you will find following,

/packages/common/CHANGELOG.md,

If you see packages/app/package.json you will see version incremented,

// packages/app/package.json{  "name": "@workspace/app"  "version": "1.0.1"}// packages/components/package.json{  "name": "@workspace/components",  "version": "1.0.1"}

diff scripts

Lerna diff script allows the user to check a screenshot of what exactly changed since the last commit, it is more like Git, Bitbucket - its showing what you have changed before the commit. So to do that, lets add script in root package.json

// package.json  {    "scripts": {      + "test": "lerna run test --since"      + "diff": "lerna diff"  }}

Also, lets change something in code, go to /packages/app/src/App.js,

// packages/app/src/App.jsfunction App() {  + const [counter, setCounter] = useState(0);}

Now, lets run the script npx run diff you will get log following

> [email protected] diff /Users/kpiteng/lerna> lerna difflerna notice cli v4.0.0diff --git a/packages/app/src/App.js module.exports = () => {   const [count, setCount] = useState(0);+  const [counter, setCounter] = useState(0); }

Please download full source code from our GitHub.

Thanks for reading Blog!

KPITENG | DIGITAL TRANSFORMATION
www.kpiteng.com/blogs | [email protected]
Connect | Follow Us On - Linkedin | Facebook | Instagram


Original Link: https://dev.to/kpiteng/lerna-workspaces-managing-projects-with-multiple-packages-4bf1

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To