Practical Frontend Engineering: Building a Vue3 Component Library with pnpm Monorepo
This article explains how to set up a Vue3 component library using a pnpm‑based monorepo, covering project structure, workspace configuration, TypeScript project references, build scripts, and best practices for frontend engineering and collaborative development.
Introduction
Frontend engineering is a collection of techniques that streamline development, build, and iteration processes. While definitions vary by experience, the core idea is to combine tools that enable smooth project delivery. Modern frontend projects increasingly adopt a monorepo layout, as seen in Vue3 and Element Plus.
What is a Monorepo?
A monorepo stores all related packages in a single repository, offering shared configuration, easy inter‑package debugging, and simplified third‑party version management. This article focuses on implementing a monorepo with pnpm , the tool used by Vue3 and Element Plus.
Understanding Vue3's Monorepo Structure
Vue3's source is organized under a packages directory, where each sub‑folder (e.g., compiler-core , runtime-dom , reactivity ) contains its own package.json , API, type definitions, tests, and README. This fine‑grained modularization clarifies dependencies and improves maintainability.
The dependency graph shows clear relationships between modules, making it easy for developers to locate and modify code.
Workspace Protocol for Inter‑Package Dependencies
Using the workspace: protocol, packages reference each other locally without pulling from the npm registry. For example, adding "@vue/reactivity": "workspace:*" in a root package.json tells pnpm to resolve the dependency from the workspace.
Setting Up the Monorepo with pnpm
1. Install pnpm globally: npm install pnpm -g
2. Initialize the root package.json and mark the repository as private:
{
"private": true,
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": { "test": "echo \"Error: no test specified\" && exit 1" },
"keywords": [],
"author": "",
"license": "ISC"
}3. Create pnpm-workspace.yaml to declare workspaces:
packages:
- play # component playground
- docs # documentation
- packages/* # all component packages4. Initialize each package (e.g., @cobyte-ui/components , @cobyte-ui/theme-chalk , @cobyte-ui/utils ) with its own package.json and add them as workspace dependencies in the root:
{
"dependencies": {
"@cobyte-ui/components": "workspace:*",
"@cobyte-ui/theme-chalk": "workspace:*",
"@cobyte-ui/utils": "workspace:*"
}
}TypeScript Configuration and Project References
To improve compilation speed, the repository uses TypeScript project references. The root tsconfig.json lists three sub‑configs: tsconfig.web.json (component packages), tsconfig.play.json (playground), and tsconfig.vitest.json (tests).
{
"files": [],
"references": [
{ "path": "./tsconfig.web.json" },
{ "path": "./tsconfig.play.json" },
{ "path": "./tsconfig.vitest.json" }
]
}The shared base config ( tsconfig.base.json ) defines compiler options such as target: es2018 , module: esnext , strict mode, path aliases ( "@cobyte-ui/*": ["packages/*"] ), and other sensible defaults.
Each sub‑config extends the base and adds specific settings, e.g., tsconfig.web.json enables composite: true for incremental builds, while tsconfig.play.json allows JavaScript files and includes the playground source.
Type Checking Workflow
Because the build uses rollup-plugin-esbuild , which skips type checking, the project runs separate scripts:
tsc --noEmit for pure TypeScript packages.
vue-tsc --noEmit for packages containing Vue SFCs.
Scripts are defined in package.json :
{
"scripts": {
"typecheck:web": "vue-tsc -p tsconfig.web.json --composite false --noEmit",
"typecheck:play": "vue-tsc -p tsconfig.play.json --composite false --noEmit",
"typecheck:node": "tsc -p tsconfig.node.json --noEmit",
"runall": "pnpm run typecheck:web && pnpm run typecheck:play && pnpm run typecheck:node && pnpm run typecheck:vitest"
}
}For parallel execution, the project can use npm-run-all :
{
"scripts": {
"typecheck": "run-p typecheck:web typecheck:play typecheck:node typecheck:vitest"
}
}Running the Playground
Create a Vite Vue‑TS playground with:
pnpm create vite play --template vue-tsInstall dependencies and add a root script to launch it from the repository root:
{
"scripts": {
"dev": "pnpm -C play dev"
}
}Conclusion
The guide demonstrates a complete frontend engineering setup: a pnpm‑powered monorepo, workspace protocol for local dependencies, TypeScript project references for fast incremental builds, and coordinated scripts for type checking and development. This illustrates that engineering is not just tooling but a disciplined workflow that improves collaboration and code maintainability.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.