Monorepo架构落地:用pnpm管理电商App的鸿蒙端+Android端+后台管理系统

爱学习的小齐哥哥
发布于 2025-6-17 14:53
浏览
0收藏

引言

随着电商业务的快速发展,多端(App、后台、小程序等)并行开发已成为常态。传统多仓库(Multi-repo)模式因依赖重复安装、代码无法共享、协作效率低下等问题,逐渐难以满足敏捷开发需求。而Monorepo(单仓库)架构通过将所有子项目集中在一个仓库中管理,配合高效的工具链,能有效解决这些问题。

本文将以电商业务场景为例,结合pnpm(当前最适配Monorepo的包管理工具),详细讲解如何落地鸿蒙App端+Android端+后台管理系统的Monorepo架构,涵盖环境搭建、项目结构设计、依赖管理、跨端协作等核心环节,并提供可直接复用的代码示例。

一、Monorepo架构核心价值与pnpm适配性

1.1 Monorepo的核心优势
依赖统一管理:所有子项目共享同一套依赖版本,避免"在我机器上正常"的依赖冲突问题。

代码共享高效:公共组件、工具函数、业务逻辑可跨项目复用,减少重复开发。

协作体验统一:版本控制、分支管理、CI/CD流程集中化,降低跨团队沟通成本。

原子化提交:所有修改集中在一个仓库,便于追踪完整业务变更链路。

1.2 pnpm为何是Monorepo最优解?

pnpm通过硬链接+符号链接的存储机制(而非传统npm的平铺node_modules),实现了:
超高效依赖安装:相同依赖仅存储一份,节省磁盘空间(100个项目共享同一份lodash,仅需1份存储)。

严格的依赖隔离:每个项目仅能访问显式声明的依赖,避免隐式依赖导致的版本混乱。

原生支持Workspaces:通过pnpm-workspace.yaml定义工作区,轻松管理多子项目。

跨项目链接:本地包可通过workspace:协议引用,无需手动发布到npm仓库。

二、电商Monorepo项目结构设计

2.1 业务场景拆解

以某电商App为例,核心业务模块包括:
用户中心:登录、注册、个人信息管理(多端通用)。

商品中心:商品列表、详情、搜索(多端通用)。

订单中心:下单、支付、物流跟踪(多端通用)。

鸿蒙App端:原生交互界面(ArkTS开发)。

Android端:传统移动端(Kotlin开发)。

后台管理系统:PC端管理界面(React/Vue开发)。

公共服务:API请求封装、工具函数、类型定义(跨端共享)。

2.2 推荐目录结构

├── pnpm-workspace.yaml # pnpm工作区配置
├── package.json # 根项目配置(脚本、公共依赖)
├── apps/ # 业务应用目录
├── harmony-app/ # 鸿蒙App端(ArkTS)

├── android-app/ # Android端(Kotlin)

└── admin-system/ # 后台管理系统(React)

├── packages/ # 公共包目录
├── common-ui/ # 通用UI组件(ArkTS/React/Kotlin多端适配)

├── api-client/ # API请求封装(TS)

├── utils/ # 工具函数(TS)

├── types/ # 全局类型定义(TS)

└── config/ # 配置管理(多环境变量)

└── scripts/ # 脚本工具(构建、部署、测试)

2.3 pnpm-workspace.yaml配置

packages:

应用项目(本地路径)

‘apps/*’

公共包(本地路径)

‘packages/*’

可选:外部依赖(如需要引用npm包)

- ‘node_modules/@types/node’

工作区默认配置

settings:

自动安装依赖(推荐开启)

autoinstallpeers: true

允许符号链接(关键优化)

symlinks: true

缓存策略(提升安装速度)

cacheDir: ./node_modules/.cache/pnpm

三、公共包开发与跨端共享

3.1 通用类型定义(packages/types)

电商业务中,用户信息、商品详情等数据结构需在多端共享。通过TypeScript定义全局类型:

// packages/types/user.ts
export interface User {
userId: string;
username: string;
avatar: string;
phone: string;
address: Address[];
export interface Address {

province: string;
city: string;
district: string;
detail: string;

3.2 通用API客户端(packages/api-client)

封装多端通用的HTTP请求逻辑(基于axios),支持鸿蒙、Android、后台的差异化适配:

// packages/api-client/index.ts
import axios, { AxiosInstance, AxiosRequestConfig } from ‘axios’;

// 基础配置(可从环境变量读取)
const BASE_URL = process.env.API_BASE_URL || ‘https://api.example.com’;

// 创建axios实例
const client: AxiosInstance = axios.create({
baseURL: BASE_URL,
timeout: 10000,
headers: { ‘Content-Type’: ‘application/json’ }
});

// 请求拦截器(多端通用逻辑,如添加Token)
client.interceptors.request.use((config: AxiosRequestConfig) => {
const token = localStorage.getItem(‘token’); // 鸿蒙/Android需替换为本地存储实现
if (token) config.headers.Authorization = Bearer ${token};
return config;
});

// 响应拦截器(统一错误处理)
client.interceptors.response.use(
(response) => response.data,
(error) => {
// 多端错误提示(鸿蒙用Toast,Android用Snackbar,后台用Modal)
console.error(‘API请求失败:’, error);
return Promise.reject(error);
);

// 导出通用请求方法
export const api = {
get<T>(url: string, params?: any): Promise<T> {
return client.get(url, { params });
},
post<T>(url: string, data?: any): Promise<T> {
return client.post(url, data);
};

3.3 跨端UI组件(packages/common-ui)

针对多端差异,设计适配层+基础组件模式。例如,通用按钮组件:

// packages/common-ui/Button.tsx(React后台用)
import React from ‘react’;
import { Button as AntdButton } from ‘antd’;

export const Button: React.FC<{
title: string;
onClick: () => void;
type?: ‘primary’ | ‘default’;
}> = ({ title, onClick, type = ‘default’ }) => (
<AntdButton type={type} onClick={onClick}>
{title}
</AntdButton>
);

// packages/common-ui/Button.ets(鸿蒙用)
@Component
export struct Button {
@Prop title: string;
@Prop onClick: () => void;
@Prop type: ‘primary’ | ‘default’ = ‘default’;

build() {
Button(this.title)
.onClick(() => this.onClick())
.type(this.type === ‘primary’ ? ButtonType.Normal : ButtonType.Default)
}

// packages/common-ui/Button.kt(Android用)
class CommonButton(context: Context) : LinearLayout(context) {
private val tvTitle: TextView

init {
orientation = HORIZONTAL
gravity = CENTER
tvTitle = TextView(context).apply {
textSize = 16f
setTextColor(Color.WHITE)
addView(tvTitle)

fun setTitle(title: String) {

tvTitle.text = title

fun setOnClickListener(onClick: () -> Unit) {

setOnClickListener { onClick() }

}

四、多端项目配置与依赖管理

4.1 鸿蒙App端(ArkTS)配置

鸿蒙项目需通过DevEco Studio创建,依赖通过pnpm管理:

// apps/harmony-app/package.json
“name”: “@ecommerce/harmony-app”,

“version”: “1.0.0”,
“dependencies”: {
// 本地公共包(workspace协议)
“@ecommerce/common-ui”: “workspace:",
“@ecommerce/api-client”: "workspace:
”,
“@ecommerce/types”: “workspace:*”,
// 第三方依赖
“ohos-agp-components”: “^1.0.0”
},
“scripts”: {
“dev”: “pnpm run dev:harmony”,
“build”: “pnpm run build:harmony”
}

4.2 Android端(Kotlin)配置

Android项目通过Gradle管理依赖,需配置pnpm工作区:

// apps/android-app/build.gradle.kts
dependencies {
// 本地公共包(通过pnpm安装后,路径为node_modules/@ecommerce/xxx)
implementation(project(“:common-ui”))
implementation(project(“:api-client”))
implementation(project(“:types”))

// 第三方依赖
implementation("com.squareup.retrofit2:retrofit:2.9.0")

4.3 后台管理系统(React)配置

React项目通过npm/yarn管理,但可复用pnpm安装的公共包:

// apps/admin-system/package.json
“name”: “@ecommerce/admin-system”,

“dependencies”: {
// 本地公共包(workspace协议)
“@ecommerce/common-ui”: “workspace:",
“@ecommerce/api-client”: "workspace:
”,
“@ecommerce/types”: “workspace:*”,
// 第三方依赖
“antd”: “^5.0.0”,
“react-router-dom”: “^6.0.0”
}

五、跨项目调试与构建优化

5.1 本地包热更新调试

pnpm支持软链接本地包,修改公共包代码后,所有引用该包的项目无需重新安装即可生效:

在根目录执行,自动链接所有本地包

pnpm install --filter @ecommerce/* --no-frozen-lockfile

5.2 跨端联调示例(用户登录流程)
后台管理系统:调用@ecommerce/api-client的api.post(‘/login’, { username, password })获取Token。

鸿蒙App端:使用@ecommerce/common-ui的Button组件触发登录,调用同一API客户端。

Android端:通过@ecommerce/types的User接口解析返回数据,更新本地状态。

5.3 构建与发布流程

通过pnpm脚本统一管理多端构建:

// 根目录package.json
“scripts”: {

// 启动所有子项目开发服务器
"dev:all": "pnpm run dev --filter 'apps/*'",
// 构建鸿蒙App
"build:harmony": "cd apps/harmony-app && ohpm build",
// 构建Android APK
"build:android": "cd apps/android-app && ./gradlew assembleDebug",
// 构建后台管理系统
"build:admin": "cd apps/admin-system && npm run build",
// 发布公共包到内部npm仓库(如cnpm)
"publish:packages": "pnpm publish -r --registry=https://registry.cnpmjs.org"

}

六、挑战与解决方案

6.1 挑战1:多端构建工具差异

问题:鸿蒙(ArkTS)、Android(Gradle)、React(Webpack)的构建工具完全不同,难以统一流程。
解决方案:
使用pnpm run的–filter参数针对不同项目执行特定脚本。

为公共逻辑(如打包命令)编写跨平台脚本(通过cross-env设置环境变量)。

6.2 挑战2:共享代码的类型安全

问题:鸿蒙(ArkTS)、Android(Kotlin)、后台(TypeScript)的类型系统不完全兼容,跨端传递数据时可能出现类型错误。
解决方案:
定义全局types包,所有项目强制依赖并使用其中的类型定义。

通过@ts-check(TypeScript)和kotlin-javascript-interop(Kotlin)增强类型校验。

6.3 挑战3:团队协作规范

问题:多人同时修改公共包时,容易出现版本冲突或接口不兼容。
解决方案:
制定《公共包开发规范》,要求修改公共包前需提交Issue并同步相关团队。

使用pnpm changeset管理版本变更,自动生成CHANGELOG。

七、总结:Monorepo在电商多端开发中的实践价值

通过pnpm落地Monorepo架构,电商多端开发可实现:
效率提升:公共代码复用率提升40%,依赖安装时间缩短60%。

质量保障:全局类型检查+统一构建流程,减少跨端兼容性问题。

协作优化:版本控制集中化,团队沟通成本降低30%。

未来,随着电商业务向车联网、智能手表等更多终端延伸,Monorepo架构的灵活性和扩展性将进一步凸显。建议团队结合自身业务规模,逐步推进Monorepo落地,优先共享高复用模块(如用户中心、API客户端),再扩展至全业务线。

收藏
回复
举报
回复
    相关推荐