Slide 1

Slide 1 text

JSConf Korea 2020 Developing in a Large Monorepo

Slide 2

Slide 2 text

Jai Santhosh Engineering Manager @jaisanth

Slide 3

Slide 3 text

Microsoft Search

Slide 4

Slide 4 text

Re-using Components They are the user’s most important, cross-app and cross-platform interactions in the Office Suite. High-Value Experiences These experiences must feel familiar across apps and platforms, but also look and feel consistent within a platform and within an app. Coherence

Slide 5

Slide 5 text

People Card

Slide 6

Slide 6 text

People Card

Slide 7

Slide 7 text

People Card Card Conversations Documents Events Organization Analytics Contact

Slide 8

Slide 8 text

Write new code Test locally Create a PR Receive Peer Review Verify build and test reports Merge PR with main Checkin new code Deploy through rings to production Listen and measure for feedback Propose next steps Write new code Agility Inner Loop Outer Loop

Slide 9

Slide 9 text

Web Win32 UWP iOS Mac Android src src src src src src Agility

Slide 10

Slide 10 text

Web Win32 UWP iOS Mac Android src Agility

Slide 11

Slide 11 text

Agility & Coherence

Slide 12

Slide 12 text

Monorepo

Slide 13

Slide 13 text

What is a Monorepo? A repository with multiple packages or projects • Other repositories can re-use small parts of our code • Better code re-use unit (better tooling) Singularity across multiple packages • Developer agility • Code consistency as conventions are shared • Unified processes, versioned centrally • Code discoverability • ... Why in one repository? • Various projects or packages can co-exist. • Micro platform with an entire application stack in one place. Not necessarily a monolith

Slide 14

Slide 14 text

Using separate packages Re-using can be made easier with singular responsibility packages. Can be published easily. Enables cross-team usage of required packages. Can manage releases easily.

Slide 15

Slide 15 text

You need reliable tooling! Package Management Linters Build system / Infrastructure Testing Tools Cross-package orchestrators and more… Package Management Cross-package orchestrators

Slide 16

Slide 16 text

Package Management

Slide 17

Slide 17 text

JavaScript package JavaScript Repo Repo’s external dependencies

Slide 18

Slide 18 text

package.json NPM Yarn Files on disk NodeJS require() is read by which writes is resolved by which finds

Slide 19

Slide 19 text

require("react") • /User/../git/Monorepo/packages/people-core/node_modules/react • /User/../git/Monorepo/packages/node_modules/react • /User/../git/Monorepo/node_modules/react • /User/../git/node_modules/react • /User/../node_modules/react • /node_modules/react Node Module Resolution

Slide 20

Slide 20 text

package-1 package-2 Repository 1 Repository 2

Slide 21

Slide 21 text

package-1 package-2 Repository mono monorepo

Slide 22

Slide 22 text

package-1 package-2 Repository mono monorepo A (1.0) C (1.0) B (1.0) B (2.0) B (1.0)

Slide 23

Slide 23 text

package-1 package-2 monorepo A (1.0) C (1.0) B (1.0) B (2.0) node_modules packages package-1 package-2 node_modules symlinks https://yarnpkg.com/blog/2018/02/15/nohoist/ Package Hoisting

Slide 24

Slide 24 text

rush yarn workspaces pnpm workspaces Lerna Package Management - Tools Multiple popular tools for package management, let’s check how yarn workspaces works.

Slide 25

Slide 25 text

• Set "private": true • Add workspace packages • Optionally, you can add a nohoist list of packages as well • Run yarn from the root of the monorepo. • Package installation time for about 150+ packages came down from ~20mins to ~6mins. monorepo/package.json Yarn Workspaces

Slide 26

Slide 26 text

Cross-package Orchestration

Slide 27

Slide 27 text

rush Lerna Shell scripts Gulp Cross-package Orchestration - Tools Perform operations on files across multiple packages, usually from the root folder

Slide 28

Slide 28 text

monorepo/lerna.json • Add "packages": [<>] • Specify npmClient • Set useWorkspaces value. • lerna run [script] - Run the script across packages Lerna

Slide 29

Slide 29 text

Lerna - Example

Slide 30

Slide 30 text

Lerna - Example

Slide 31

Slide 31 text

• We use test dev apps for each of the experiences for quick dev validation. • lerna run --scope [] [script] Lerna - Scoping

Slide 32

Slide 32 text

• lerna publish - create new release versions of packages that have been updated. • lerna diff [package?] - Diff package(s) since the last release. • lerna changed – Check which packages have been changed since last release. • lerna version – Bump version of packages changed since the last release. Lerna - Versioning

Slide 33

Slide 33 text

• Brought down our build times by more than 5x. • Good community adoption • babeljs • create-react-app • react-router • jest • and many more... Lerna - Wins

Slide 34

Slide 34 text

Summing it up… • Pick the right tools for your monorepo, based on the complexity of the packages, to improve the developer experience. • For linting, unit/functional/perf testing you can combine it with tools like lerna to easily run these commands across packages. • If you are using TypeScript, you will have to handle TS compilation and for a better developer experience, manage typings for better Intellisense.

Slide 35

Slide 35 text

References https://medium.com/@vincentbailly/evolving-a-large-typescript-repository-4a32c61e94fd https://rushjs.io/ https://lerna.js.org/ https://yarnpkg.com/lang/en/docs/workspaces/ Image courtesy: @redbadgerteam, Adobe Stock images

Slide 36

Slide 36 text

Thank you! Jai Santhosh Engineering Manager @jaisanth