developing and publishing multiple packages

{
  "name": "currency-input",
  "version": "1.0.0",
  "dependencies": {
    "react": "16.x",
    "lodash": "3.x",
    "meow": "2.x"
  }
}
{
  "name": "currency-input",
  "version": "1.0.0",
  "dependencies": {
    "react": "16.x",
    "lodash": "3.x",
    "meow": "2.x"
  }
}
{
  "name": "address-input",
  "version": "1.0.0",
  "dependencies": {
    "react": "16.x",
    "lodash": "3.x",
    "meow": "2.x"
  }
}
{
  "name": "awesome-input",
  "version": "1.0.0",
  "dependencies": {
    "react": "16.x",
    "material-ui": "1.x"
  }
}

npm publish awesome-input

npm install awesome-input

{
  "name": "currency-input",
  "version": "1.1.0",
  "dependencies": {
    "react": "16.x",
    "lodash": "3.x",
    "meow": "2.x",
    "awesome-input": "1.0.0"
  }
}
{
  "name": "address-input",
  "version": "1.1.0",
  "dependencies": {
    "react": "16.x",
    "lodash": "3.x",
    "meow": "2.x",
    "awesome-input": "1.0.0"
  }
}

npm publish currency-input address-input

{
  "name": "currency-input",
  "version": "1.1.0",
  "dependencies": {
    "react": "16.x",
    "lodash": "3.x",
    "meow": "2.x",
    "awesome-input": "1.0.0"
  }
}
{
  "name": "address-input",
  "version": "1.1.0",
  "dependencies": {
    "react": "16.x",
    "lodash": "3.x",
    "meow": "2.x",
    "awesome-input": "1.0.0"
  }
}
{
  "name": "awesome-input",
  "version": "1.0.0",
  "dependencies": {
    "react": "16.x",
    "material-ui": "1.x"
  }
}

awesome-input not awesome anymore

awesome-input

1. Fix Bug

2. Unit Test

3. npm publish awesome-input@1.0.1

 

address-input

1. npm install awesome-input@1.0.1

2. Verify Fix

3. npm publish address-input@1.1.1

 

currency-input

1. npm install awesome-input@1.0.1

2. Verify Fix

3. npm publish currency-input@1.1.1

{
  "name": "email-input",
  "version": "1.0.0",
  "dependencies": {
    "react": "16.x",
    "lodash": "3.x",
    "email-validator": "4.x",
    "awesome-input": "1.1.0"
  }
}
{
  "name": "awesome-input",
  "version": "1.1.0",
  "dependencies": {
    "react": "16.x",
    "material-ui": "1.x"
  }
}

awesome-input

1. Add new feature

2. Unit Test

3. npm publish awesome-input@1.1.0

 

email-input

1. npm install awesome-input@1.1.0

2. Integrate awesome-input

3. Unit Test

4. npm publish email-input@1.0.0

 

address-input

1. npm install awesome-input@1.1.0

2. Integrate awesome-input

3. Unit Test

4. npm publish address-input@1.2.0

 

currency-input

1. npm install awesome-input@1.0.1

2. Integrate awesome-input

3. Unit Test AND FOUND A BUG, SHIT!

awesome-input

1. Fix Bug

2. Unit Test

3. npm publish awesome-input@1.1.1

 

email-input

1. npm install awesome-input@1.1.1

2. Unit Test

3. npm publish email-input@1.0.1

 

address-input

1. npm install awesome-input@1.1.1

2. Unit Test

3. npm publish address-input@1.2.1

 

currency-input

1. npm install awesome-input@1.1.1

2. Integrate awesome-input

3. Unit Test AND GREAT, NO BUG!

4. npm publish currency-input@1.2.1

npm link

node_modules

email-input

awesome-input

node_modules

address-input

awesome-input

node_modules

currency-input

awesome-input

awesome-input

symlink

{
  "name": "awesome-design",
  "version": "1.0.0",
  "dependencies": {
    "email-input": "1.0.1",
    "address-input": "1.2.1",
    "currency-input": "1.2.1"
  }
}
import EmailInput from 'email-input';
import AddressInput from 'address-input';
import CurrencyInput from 'currency-input';

export { EmailInput, AddressInput, CurrencyInput };
import { EmailInput } from 'awesome-design';

awesome-design/index.js

user-feature/index.js

MANAGING MULTIPLE PACKAGES IS HARD

FIXING 1 PACKAGE HAS CHAIN EFFECT ON MULTIPLE PACKAGES

{
  "name": "email-input",
  "version": "1.0.0",
  "dependencies": {
    "react": "16.x",
    "lodash": "3.x",
    "email-validator": "4.x",
    "awesome-input": "^1.1.0"
  }
}

SEQUENCE IS IMPORTANT

GIT

MORE GIT REPOS MAKE YOUR GITHUB PROFILE LOOK MORE IMPRESSIVE

​shawn / awesome-input

git submodule

email-input

address-input

currency-input

awesome-design

email-input

address-input

currency-input

awesome-design

import EmailInput from './email-input/src/index.js';
import AddressInput from './address-input/src/index.js';
import CurrencyInput from './currency-input/src/index.js';

class AwesomeDesignDemo extends React.Component {
  render() {
    return (
      <Demo>
         <EmailInput />
         <AddressInput />
         <CurrencyInput />
      </Demo>
    );
  }
}

awesome-design/demo.js

monorepo

QUESTIONS?

101

lerna.json

{
  "packages": [
    "widgets/*",
    "utils/*"
  ],
  "npmClient": "yarn"
}

https://en.wikipedia.org/wiki/Glob_(programming)

email-input

widgets

lerna.json

address-input

awesome-design

package.json

package.json

currency-util

utils

test

package.json

docs

__mocks__

email-input

widgets

lerna.json

address-input

awesome-design

package.json

package.json

currency-util

utils

test

package.json

docs

__mocks__

@shawn/email-input

@shawn/address-input

@shawn/currency-util

...

lerna list

lerna bootstrap

if dependency not in lerna project:

      npm install

 

else if dependency version satisfy the local version in lerna project:

      symlink local copy to node_modules

 

else:

      npm install

lerna bootstrap

email-input

widgets

lerna.json

awesome-input

awesome-design

package.json

package.json

email-util

utils

package.json

node_modules

{
  "name": "@shawn/email-input",
  "dependencies": {
    "awesome-input": "^0.5.0",
    "email-util": "^0.6.0",
    "react": "16.3.0"
  }
}
  
widgets/email-input/package.json
{
  "name": "@shawn/awesome-input",
  "version": "0.5.5"
}
  
widgets/awesome-input/package.json
{
  "name": "@shawn/email-input",
  "version": "0.9.1"
}
  
widgets/email-util/package.json

awesome-input

email-input

react

email-input

widgets

lerna.json

awesome-input

awesome-design

package.json

package.json

email-util

utils

package.json

node_modules

{
  "name": "@shawn/email-input",
  "dependencies": {
    "awesome-input": "^0.5.0",
    "email-util": "^0.6.0",
    "react": "16.3.0"
  }
}
  
widgets/email-input/package.json
{
  "name": "@shawn/awesome-input",
  "version": "0.5.5"
}
  
widgets/awesome-input/package.json
{
  "name": "@shawn/email-input",
  "version": "0.9.1"
}
  
widgets/email-util/package.json

awesome-input

email-input   (from npm)

react              (from npm)

lerna link

if dependency not in lerna project:

      npm install

 

else:

      symlink local copy to node_modules

 

lerna link

email-input

widgets

lerna.json

awesome-input

awesome-design

package.json

package.json

email-util

utils

package.json

node_modules

{
  "name": "@shawn/email-input",
  "dependencies": {
    "awesome-input": "^0.5.0",
    "email-util": "^0.6.0",
    "react": "16.3.0"
  }
}
  
widgets/email-input/package.json
{
  "name": "@shawn/awesome-input",
  "version": "0.5.5"
}
  
widgets/awesome-input/package.json
{
  "name": "@shawn/email-input",
  "version": "0.9.1"
}
  
widgets/email-util/package.json

awesome-input

email-input

react              (from npm)

scope

--scope=email-autocomplete

--scope=email-*

--ignore=email-autocomplete

--scope=email-autocomplete

--include-filtered-dependencies

--scope=email-autocomplete

--include-filtered-dependents

--since=[git-ref]

QUESTIONS?

102

lerna publish

lerna diff

lerna changed

lerna version

lerna publish

git tag

lerna diff

= git diff v1.0.0

lerna diff @shawn/email-input

git diff v1.0.0 ./widgets/email-input

lerna changed

lerna version

lerna publish

lerna

changed

show changes since last git tag

lerna

version

lerna

publish

update version,

git commit, git tag,

git push

npm publish

lerna info Looking for changed packages since v1.0.0


@shawn/awesome-input

@shawn/currency-input

@shawn/email-input

@shawn/address-input

@shawn/awesome-design


lerna success found 5 package ready to publish

lerna changed

lerna info Looking for changed packages since v1.0.0

...

? Select a new version for @shawn/awesome-input (currently 1.0.0) Minor (1.1.0)

...

Changes:
 - @shawn/awesome-input: 1.0.0 => 1.1.0

 - @shawn/currency-input: 1.0.0 => 1.1.0

 - @shawn/email-input: 1.0.0 => 1.1.0

 - @shawn/address-input: 1.0.0 => 1.1.0

 - @shawn/awesome-design: 1.0.0 => 1.1.0

? Are you sure you want to create these versions? (ynH)

lerna version

...

- @shawn/awesome-design: 1.0.0 => 1.1.0

? Are you sure you want to create these versions? Yes

 

lerna info publish Publishing packages to npm...
 

Successfully published:

- @shawn/awesome-input@1.1.0

- @shawn/currency-input@1.1.0

- @shawn/email-input@1.1.0

- @shawn/address-input@1.1.0

- @shawn/awesome-design@1.1.0

lerna publish

103

lerna run

lerna exec

lerna run test

npm run test

in every package that has "test" npm script

lerna exec -- rm -rf src/

rm -rf src/

in every package

lerna run --stream

@shawn/awesome-input: yarn run v1.0.2
@shawn/awesomeness: yarn run v1.0.2
@shawn/happiness: yarn run v1.0.2
@shawn/debounce-utils: yarn run v1.0.2
@shawn/debounce-utils: jest
@shawn/happiness: jest

@shawn/awesomeness: yarn run v1.0.2

lerna run --parallel

lerna run --no-bail

lerna add

lerna-extras

https://confluence.garenanow.com/display/SPCFE/Lerna+Extras

lerna-extras bootstrap-here

lerna-extras

add-here

lerna-extras

diff-package-since <git-ref>

lerna-extras search

lerna-extras bootstrap-changed

lerna

By Li Hau Tan