Mobile Development 24 min read

Building a React Native Component Library with Lerna, Yarn Workspaces, and Automated Tooling

This tutorial walks through creating a production‑ready React Native UI component library named vant‑react‑native, covering monorepo setup with Lerna, package naming, Yarn workspaces, commit and code standards, icon generation, on‑demand loading, debugging, documentation with Dumi, CI/CD deployment, and unit testing.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Building a React Native Component Library with Lerna, Yarn Workspaces, and Automated Tooling

Standing on Vant Design's shoulders

After evaluating vant, antd‑mobile and fishd‑mobile, the author chooses vant as the UI design reference and names the package vant-react-native with a descriptive description field in package.json .

Multi‑package management with Lerna

Lerna creates a monorepo where each component lives in its own package (e.g., @vant-react-native/button , @vant-react-native/icon ). The directory layout looks like:

.\n└── packages\n    ├── button # @vant-react-native/button\n    └── icons  # @vant-react-native/icon\n

Initialize Lerna project

$ mkdir vant-react-native && lerna init --independent

Yarn workspaces

Enable useWorkspaces in lerna.json so that dependencies are hoisted to the root node_modules :

{\n  "npmClient": "yarn",\n  "useWorkspaces": true\n}

Lerna publish config

Configure command.publish.registry and ignoreChanges to control publishing and avoid unnecessary version bumps.

"ignoreChanges": [\n  "ignored-file",\n  "**/__tests__/**",\n  "**/*.md"\n],\n"command": {\n  "publish": {\n    "registry": "https://registry.npmjs.org"\n  }\n}\n

Standardized commits

Use Conventional Commits via commitizen , cz-customizable , @commitlint/cli , and yorkie . The author provides an init-commit command in @youngjuning/cli to set everything up automatically.

Code linting and formatting

Install ESLint plugins for React Native and extend @youngjuning/eslint-config/react-native . Prettier configuration is imported from @youngjuning/prettier-config . EditorConfig enforces spacing, line endings and final newlines.

// .eslintrc.js\nmodule.exports = {\n  extends: ['@youngjuning/eslint-config/react-native']\n}\n

First component – Icon

Generate React Native icons from an Iconfont script using react-native-iconfont-cli . The workflow creates iconfont.json , runs npx iconfont-rn , and adds build scripts:

{\n  "build": "npx iconfont-rn",\n  "prepublishOnly": "yarn build"\n}\n

Create Lerna sub‑package

$ lerna create vant-react-native -y\n$ lerna create @vant-react-native/icons -y\n

Export Icon component

// packages/vant-react-native/src/index.ts\nexport { default as Icon } from '@vant-react-native/icons';\nexport * from '@vant-react-native/icons';\n

Development & debugging

Initialize a React Native app with TypeScript template, merge it with the monorepo, and run lerna run build before launching the app via yarn ios . Because Lerna creates symlinks inside the root, Metro can resolve the packages without --parallel issues.

Real‑time compilation

Add a dev script ( tsc -w ) to each package and run them in parallel with lerna run dev --parallel . For the icon package, onchange watches iconfont.json and triggers a rebuild.

On‑demand loading

Since Metro lacks tree‑shaking, the author uses babel-plugin-import (and a custom babel-plugin-import-vant ) to rewrite imports like import { Button } from 'vant-react-native' into per‑package paths, dramatically reducing bundle size.

Component library documentation

Integrate Dumi with dumi-theme-mobile and umi-plugin-react-native . Add scripts "start:dumi": "dumi dev" and "build:dumi": "lerna run build && dumi build" . Deploy the site to GitHub Pages and preview PRs with Surge.

Unit testing

Configure Jest with react-native preset, Enzyme adapters, and snapshot serializers. Example test for the Button component uses shallow rendering and snapshot comparison.

Conclusion

The article provides a complete, production‑ready workflow for building, testing, documenting, and publishing a React Native component library, illustrating best practices for monorepo management, code quality, on‑demand loading, CI/CD, and community contribution.

TestingBabelcomponent libraryDocumentationReact NativelernaYarn Workspaces
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

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.