loading...

What do you call the style of monorepo that Babel and Material-UI use?

dwjohnston profile image David Johnston ・2 min read

Both Babel and Material-UI are lerna monorepos.

They both have something in common where they install a lot of common dev dependencies at the project root - jest, babel, eslint etc.

Material-UI does a thing, where a given package's build scripts reference build scripts and configs at the project root:

    "build": "yarn build:cjs && yarn build:esm && yarn build:es && yarn build:umd && yarn build:copy-files",
    "build:cjs": "cross-env NODE_ENV=production BABEL_ENV=cjs babel --config-file ../../babel.config.js ./src --out-dir ./build --ignore \"**/*.test.js\"",
    "build:esm": "cross-env NODE_ENV=production BABEL_ENV=esm babel --config-file ../../babel.config.js ./src --out-dir ./build/esm --ignore \"**/*.test.js\"",
    "build:es": "cross-env NODE_ENV=production BABEL_ENV=es babel --config-file ../../babel.config.js ./src --out-dir ./build/es --ignore \"**/*.test.js\"",
    "build:umd": "cross-env BABEL_ENV=production-umd rollup -c scripts/rollup.config.js",
    "build:copy-files": "node ../../scripts/copy-files.js",
    "prebuild": "rimraf build",
    "release": "yarn build && npm publish build --tag latest",
    "test": "cd ../../ && cross-env NODE_ENV=test mocha 'packages/material-ui/**/*.test.js' --exclude '**/node_modules/**'",

Babel's packages don't even have build scripts, instead they are built via make files at the project root.

Additionally, both are using yarn, which has its own concept of workspaces.

What I'm wondering is how this fits in with monorepo design in general.

For example it makes sense that you would want a consistent code style across all of your monorepo, so eslint defined in the root makes sense.

However, in the case that your monorepo is a 'frontend/backend/common' type project - there are going to be linting rules (eg. React specific) that only apply to frontend, so this isn't necessarily always going to work. (I suppose you could have two different eslint configs in the root).

I think I've had a fundamental misunderstanding about monorepos - I had thought that basically each package in a monorepo should stand in its own right - that is, you should be able to checkout the project and build and test just the one package.

The idea being, that a project may have different teams, different ways of working, and so working on one package shouldn't require knowledge about how the other package works. However, the packages to have dependencies on each other, and you want that to 'just work' in development, which is where I've found lerna helpful.

This certainly isn't really the case with Babel - there are no build scripts in the packages, and at the project root just a single 'build' script. You would have to be diving into the make files to be building an individual package.

Can someone outline some of the key concepts people use to think about monorepos?

eg.

  • Common tooling at project root
  • What a standard 'getting started' flow looks like for a developer freshly checking out the project is.
  • What a standard build pipeline flow looks like. (My understanding for example just force publishes all packages, regardless of changes, and keeps all their versions in sync like that).

Discussion

pic
Editor guide