Frontend Development 24 min read

Monorepo Practices and Migration for Large Frontend Projects

The article explains monorepo concepts, compares monolithic, multirepo, and monorepo approaches, presents a Tianmao Campus case study, and recommends a pnpm + lerna‑lite + TurboRepo toolchain with detailed setup, configuration, local development scripts, and a unified build‑release workflow to streamline large frontend projects.

DaTaobao Tech
DaTaobao Tech
DaTaobao Tech
Monorepo Practices and Migration for Large Frontend Projects

This article explains what a monorepo is, why it is needed, and how to adopt it in large front‑end projects. It first compares three project management modes – Monolithic (single repository), Multirepo (multiple repositories) and Monorepo (single repository with many packages) – and lists their advantages and disadvantages.

It then presents a real‑world case study of the Tianmao Campus "Ruyi POS" business, describing the current pain points such as slow builds, duplicated dependencies, and fragmented code review processes.

The optimization goals are summarized: reduce build and deployment cost, improve CR (code review) control, link changes to requirements, and unify the whole development‑release workflow.

Next, the article reviews the monorepo ecosystem for front‑end development, covering package managers (npm, Yarn, pnpm), versioning tools (Lerna, lerna‑lite, Changesets), and build tools (Turborepo, Nx, others). It recommends the toolchain pnpm + lerna‑lite + turborepo and explains why each was chosen.

Setup steps include installing pnpm globally, initializing a mono repository, and configuring the workspace:

$ tnpm i -g pnpm

Example project structure:

your-mono-project
├── packages
│   ├── bundles
│   │   └── bundle-a
│   │       └── package.json
│   └── components
│       └── util-a
│           └── package.json
├── .gitignore
├── .npmrc
├── lerna.json
├── package.json
├── pnpm-workspace.yaml
├── turbo.json

Key configuration files:

lerna.json

{
  "packages": ["packages/*/*"],
  "command": {
    "publish": {"conventionalCommits": true},
    "version": {"conventionalCommits": true, "syncWorkspaceLock": true}
  },
  "version": "independent",
  "npmClient": "pnpm"
}

pnpm-workspace.yaml

packages:
  - packages/*/*

turbo.json

{
  "$schema": "https://turborepo.org/schema.json",
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "inputs": ["src/**/*"],
      "outputs": ["es/**", "lib/**", "build/**"]
    }
  }
}

For local development, the article introduces a custom script that discovers mono packages and generates a local-links.js file used by webpack aliasing:

// relateLocalMonoLinks.js
module.exports = async function relateLocalMonoLinks(def) {
  try {
    const localLinks = await getAppDepsLocalMainJsPath();
    const cacheLinks = await getCacheLinks();
    const chosenLinks = await getChosenLinks(localLinks, cacheLinks);
    await updateChosenLinks(chosenLinks);
  } catch (e) {}
};

Webpack configuration then merges these links when IS_LOCAL_DEV is set:

// webpack.config.js
const baseConfig = {
  resolve: { alias: getAliasMap() }
};

function getAliasMap() {
  let aliasMap = { '@': path.resolve(cwd, './src') };
  const pjson = require(path.resolve(cwd, 'package.json'));
  Object.keys(pjson.dependencies || {})
    .map(pkg => ({ key: pkg, value: path.resolve(cwd, 'node_modules', pkg) }))
    .forEach(({ key, value }) => (aliasMap[key] = value));
  if (process.env.IS_LOCAL_DEV) {
    try {
      const links = require(path.resolve(cwd, 'local-links')) || {};
      aliasMap = Object.assign({}, aliasMap, links);
    } catch (e) { console.log('invalid local links'); }
  }
  return aliasMap;
}

The workflow for adding a new component to the mono repo is described step‑by‑step, including removing its own .git folder, adjusting its package.json build script, and running pnpm i to link it.

Finally, the article outlines the build and release process: commit changes in the mono repo, run the unified build tool (TurboRepo) which caches unchanged work, and publish packages using lerna-lite (which supports pnpm workspace protocol). The released packages can then be referenced by the application with the new version.

The conclusion emphasizes that monorepo is a strategy, not a framework, and the chosen tools should bring tangible benefits such as faster builds, easier dependency management, and unified CI/CD.

frontendproject managementMonorepoBuild ToolspnpmTurborepo
DaTaobao Tech
Written by

DaTaobao Tech

Official account of DaTaobao Technology

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.