Package management and dependency rules
npm / pnpm workspaces
The monorepo uses pnpm with workspaces defined in pnpm-workspace.yaml:
themes/*plugins/*packages/*tools/*
Root package.json also lists workspaces for compatibility with tools that read it.
Hoisting
pnpm installs dependencies into:
- A root
node_moduleswith symlinks into workspace packages - Per-package
node_moduleswhere needed for peer dependencies or isolation
Expectation: Hoisting reduces duplication, but you must not rely on implicit hoisting — a package must declare every dependency it imports in its own package.json. CI and fresh installs must succeed without “it worked because another package pulled it in.”
Rules
- Declare own dependencies — If
plugins/my-plugin/src/index.jsimports a package, that package must appear inplugins/my-plugin/package.json(dependenciesordevDependenciesas appropriate). - Workspace protocol — Internal packages use
workspace:*when published through the workspace (for example shared npm packages underpackages/). - Single install — Run
pnpm installonce at the monorepo root; do not ask contributors topnpm installinside each plugin unless troubleshooting. - Composer — Run root
composer installfor monorepo PHP tooling; runpnpm composer-install(ornx run <project>:composer-install) for per-project vendors as needed.
Composer path repositories
Plugins and themes often reference monorepo libraries via a path repository in composer.json:
json
"repositories": [
{
"type": "path",
"url": "../../packages/phpunit-config",
"options": { "symlink": false }
}
]Keep relative paths correct for the package’s depth under plugins/ or themes/.
Troubleshooting
| Symptom | Things to check |
|---|---|
| Module not found after adding an import | Add the dependency to that package’s package.json and run pnpm install from root. |
| Wrong version of a transitive dep | Add a direct devDependency or use pnpm overrides at root (sparingly, with team agreement). |
| Peer dependency warnings | Install the peer into the package that consumes it or align versions with @wordpress/* packages. |
| Duplicate React or block editor issues | Ensure a single version of @wordpress/* across the workspace; check root and package package.json alignment. |
| Composer path not found | Verify url in composer.json relative to the package directory. |
Lockfiles
pnpm-lock.yamlis committed at the root — keep it authoritative for JS.- Per-package
composer.lock— follow team policy; many migrations remove per-package locks in favor of reproducible installs fromcomposer.jsonconstraints. Confirm with maintainers before deleting.