Organizing a Vue Component Library with Mono‑repo, Scripts, and Lerna
This article explains how to structure a Vue component library using a mono‑repo approach, set up the project with @vue/cli, manage component creation, demo examples, build and publish scripts, enforce code formatting with ESLint, and handle versioning and changelogs with Lerna.
Componentization is the most popular way to reuse code in modern front‑end development, and as a project grows the number of components increases, making efficient organization essential.
We compared the two mainstream repository strategies—mono‑repo and multi‑repo. Multi‑repo with tools like rollup leads to issues such as chaotic issue management, cumbersome version updates, and duplicated changelog maintenance. Mono‑repo with a single JavaScript build tool (e.g., babel ) avoids these problems but requires a larger repository and a build tool capable of handling all packages.
After evaluation we chose a mono‑repo because our components have frequent inter‑dependencies and we standardize on vue as the development framework.
Project creation uses @vue/cli , which scaffolds the project, hides the complexity of webpack and loaders, and provides a hot‑reload development server. The CLI also offers multiple build targets (app, library, web component) suitable for a component library.
Component storage follows the mono‑repo layout: a packages folder contains a sub‑folder for each component, each with its own package.json , README.md , CHANGELOG.md , src , dist , and node_modules . Example directory tree:
1 ├── packages
2 │ ├── error-page-vue
3 │ │ └── ...
4 │ ├── feed
5 │ │ ├── CHANGELOG.md
6 │ │ ├── README.md
7 │ │ ├── dist
8 │ │ ├── node_modules
9 │ │ ├── package-lock.json
10 │ │ ├── package.json
11 │ │ └── src
12 │ ├── feed-edit
13 │ │ └── ...
14 │ └── ...
15 └── ...Demo / debugging components are placed in an examples folder, with a components.js configuration that generates routes and navigation for each demo.
import Navigation from "./Navigation";
let routes = components.map(component => ({
path: `/${component.name}`,
component: () => import(`../examples/${component.name}`)
}));
routes.unshift({ path: "", component: Navigation });
export default routes;Script automation includes three main scripts under a scripts directory:
new.js – creates component directories, updates components.js , and generates initial files.
build.js – uses @vue/cli-service to build each component programmatically.
delete.js – removes component artifacts.
Example snippet from new.js :
function updateConfig(path, components) {
// update components.js file
...
}
function createPackages(componentName) {
// create package folder with package.json, src/index.js, README.md, etc.
...
}To keep initial file content consistent we run eslint programmatically:
const CLIEngine = eslint.CLIEngine;
const cli = new CLIEngine({ ...require("../.eslintrc.js"), fix: true });
CLIEngine.outputFixes(cli.executeOnFiles([filePath]));Build script leverages the Node API of @vue/cli-service to invoke the build command for each package, allowing custom configuration per package when a local vue.config.js exists.
const vueCliService = require("@vue/cli-service");
const buildService = new vueCliService();
async function build() {
for (let i = 0, len = components.length; i < len; i++) {
const name = components[i].name;
await buildService.run("build", {
_: ["build", `${root}/packages/${name}/src/index.js`],
target: "lib",
name: `hy-${name}`,
dest: `${root}/packages/${name}/dist`,
formats: "commonjs,umd-min"
});
}
}Version management is handled by lerna , which manages multiple packages in a mono‑repo, installs dependencies across packages, and automates version bumping, changelog generation, and publishing to npm.
Changelog follows a simple convention with sections Added , Changed , Removed , and Fixed in CHANGELOG.md files.
Summary steps :
Run npm run pkg-new <package name> to create a component.
Develop the component under packages/<package name> .
Add demo data in examples/<package name>/index.vue and run the dev server.
Build the component with npm run pkg-build [package name] .
Publish using npm run pkg-publish , selecting the appropriate version via Lerna.
These practices provide a reproducible workflow for maintaining a large Vue component library.
Sohu Tech Products
A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.
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.