# 鸿蒙React Native跨平台实践:完整项目构建与交付指南
从零开始构建React Native鸿蒙跨平台应用并成功交付开源项目,需要系统的流程规划和工程技术实践。本文将提供从项目初始化到开源交付的完整技术指南。
## 项目初始化与环境配置
### 工程结构规划
```bash
# 项目目录结构
my-harmony-app/
├── README.md
├── package.json
├── android/ # Android原生代码
├── ios/ # iOS原生代码
├── harmony/ # 鸿蒙原生代码
├── src/
│ ├── components/ # 共享组件
│ ├── screens/ # 页面组件
│ ├── services/ # 业务服务
│ ├── utils/ # 工具函数
│ ├── styles/ # 样式文件
│ └── navigation/ # 导航配置
├── docs/ # 项目文档
├── scripts/ # 构建脚本
└── tests/ # 测试文件
```
```json
// package.json 核心配置
{
"name": "my-harmony-app",
"version": "1.0.0",
"description": "跨平台应用示例",
"main": "src/index.js",
"scripts": {
"start": "react-native start",
"android": "react-native run-android",
"ios": "react-native run-ios",
"harmony": "react-native harmony",
"harmony:build": "react-native harmony build",
"harmony:run": "react-native harmony run",
"harmony:clean": "cd harmony && ohpm clean",
"test": "jest",
"lint": "eslint src --ext .js,.jsx,.ts,.tsx",
"type-check": "tsc --noEmit",
"build:all": "npm run android && npm run harmony:build",
"precommit": "npm run lint && npm run type-check"
},
"dependencies": {
"@ohos/react-native-harmony": "^0.72.6",
"react": "18.2.0",
"react-native": "0.72.6",
"@react-navigation/native": "^6.1.9",
"@react-navigation/stack": "^6.3.20",
"@react-navigation/bottom-tabs": "^6.5.8",
"react-native-safe-area-context": "^4.8.2",
"react-native-gesture-handler": "^2.14.0",
"react-native-reanimated": "^3.5.4",
"react-native-screens": "^3.27.0",
"axios": "^1.6.2",
"redux": "^4.2.1",
"@reduxjs/toolkit": "^1.9.7",
"react-redux": "^8.1.3"
},
"devDependencies": {
"@babel/core": "^7.23.2",
"@babel/runtime": "^7.23.2",
"@react-native/eslint-config": "^0.73.2",
"@types/react": "^18.2.45",
"@types/react-native": "^0.72.8",
"@types/react-test-renderer": "^18.0.7",
"@typescript-eslint/eslint-plugin": "^6.14.0",
"@typescript-eslint/parser": "^6.14.0",
"babel-jest": "^29.7.0",
"eslint": "^8.55.0",
"jest": "^29.7.0",
"metro-react-native-babel-preset": "^0.76.8",
"prettier": "^3.1.1",
"react-test-renderer": "18.2.0",
"typescript": "^5.3.3"
},
"engines": {
"node": ">=18.0.0",
"npm": ">=9.0.0"
},
"keywords": [
"react-native",
"harmonyos",
"cross-platform",
"mobile"
],
"author": "Your Name",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/username/my-harmony-app.git"
},
"bugs": {
"url": "https://github.com/username/my-harmony-app/issues"
},
"homepage": "https://github.com/username/my-harmony-app#readme"
}
```
### 鸿蒙环境配置
```js
// scripts/setup-harmony.js
const { execSync } = require('child_process');
const fs = require('fs');
const path = require('path');
console.log('? 开始配置鸿蒙开发环境...');
// 检查必要工具
const requiredTools = ['node', 'npm', 'ohpm'];
const missingTools = [];
requiredTools.forEach(tool => {
try {
execSync(`${tool} --version`, { stdio: 'ignore' });
} catch {
missingTools.push(tool);
}
});
if (missingTools.length > 0) {
console.error(`❌ 缺少必要工具: ${missingTools.join(', ')}`);
console.log('请先安装以下工具:');
console.log('- Node.js: https://nodejs.org/');
console.log('- ohpm: https://ohpm.openharmony.cn/');
process.exit(1);
}
// 创建鸿蒙目录结构
const harmonyDir = path.join(__dirname, '..', 'harmony');
const requiredDirs = [
'entry',
'entry/src/main',
'entry/src/main/js',
'entry/src/main/js/components',
'entry/src/main/js/services',
'entry/src/main/resources'
];
requiredDirs.forEach(dir => {
const fullPath = path.join(harmonyDir, dir);
if (!fs.existsSync(fullPath)) {
fs.mkdirSync(fullPath, { recursive: true });
console.log(`? 创建目录: ${dir}`);
}
});
// 生成鸿蒙配置文件
const configFiles = {
'oh-package.json5': `{
"license": "MIT",
"description": "HarmonyOS原生模块",
"devDependencies": {},
"dependencies": {
"@ohos/hvigor-ohos-plugin": "3.0.6"
}
}`,
'build-profile.json5': `{
"app": {
"signingConfigs": [],
"products": [
{
"name": "default",
"signingConfig": "default",
"compileSdkVersion": 9,
"compatibleSdkVersion": 9
}
],
"targets": [
{
"name": "default",
"applyToProducts": ["default"]
}
]
},
"modules": [
{
"name": "entry",
"srcPath": "./entry",
"targets": [
{
"name": "default",
"applyToProducts": ["default"]
}
]
}
]
}`,
'hvigorfile.ts': `import { appTasks } from '@ohos/hvigor-ohos-plugin';
export default {
system: appTasks,
plugins: []
};`
};
Object.entries(configFiles).forEach(([filename, content]) => {
const filePath = path.join(harmonyDir, filename);
if (!fs.existsSync(filePath)) {
fs.writeFileSync(filePath, content);
console.log(`? 生成文件: ${filename}`);
}
});
console.log('✅ 鸿蒙环境配置完成!');
console.log('运行以下命令开始开发:');
console.log('1. cd harmony && ohpm install');
console.log('2. npm run harmony');
```
## 跨平台架构设计
### 平台适配层
```typescript
// src/platform/index.ts
import { Platform } from 'react-native';
export type PlatformType = 'ios' | 'android' | 'harmony' | 'web';
class PlatformAdapter {
static getPlatform(): PlatformType {
const platform = Platform.OS;
// 鸿蒙平台检测
if (platform === 'harmony' ||
(typeof ohos !== 'undefined' && ohos.system)) {
return 'harmony';
}
return platform as PlatformType;
}
static isHarmony(): boolean {
return this.getPlatform() === 'harmony';
}
static isNative(): boolean {
const platform = this.getPlatform();
return platform === 'ios' || platform === 'android' || platform === 'harmony';
}
// 平台特定样式
static createPlatformStyles
const platform = this.getPlatform();
return {
...styles.base,
...(styles[platform] || {}),
...(this.isHarmony() ? styles.harmony : {})
};
}
// 平台特定实现
static withPlatformImplementation
implementations: Record
): T {
const platform = this.getPlatform();
const implementation = implementations[platform] || implementations.default;
if (!implementation) {
throw new Error(`No implementation for platform: ${platform}`);
}
return implementation();
}
}
// 使用示例
const styles = PlatformAdapter.createPlatformStyles({
base: {
flex: 1,
backgroundColor: '#FFFFFF'
},
ios: {
paddingTop: 44
},
android: {
paddingTop: 24
},
harmony: {
paddingTop: 32,
// 鸿蒙特有样式
backdropFilter: 'blur(10px)'
}
});
export default PlatformAdapter;
```
### 原生模块桥接
```typescript
// src/native/HarmonyBridge.ts
import { NativeModules, Platform } from 'react-native';
interface HarmonyNativeModule {
// 设备信息
getDeviceInfo(): Promise
// 振动反馈
vibrate(duration: number): Promise
// 获取鸿蒙能力
getCapabilities(): Promise
// 文件系统操作
readFile(path: string): Promise
writeFile(path: string, content: string): Promise
}
interface DeviceInfo {
deviceId: string;
deviceType: 'phone' | 'tablet' | 'wearable' | 'tv';
brand: string;
model: string;
apiLevel: number;
}
interface HarmonyCapabilities {
hasDistributedData: boolean;
hasArkUI: boolean;
hasHapticFeedback: boolean;
hasEdgeGesture: boolean;
}
class HarmonyBridge {
private static instance: HarmonyBridge;
private module: HarmonyNativeModule | null = null;
private constructor() {
if (Platform.OS === 'harmony') {
this.module = NativeModules.HarmonyModule as HarmonyNativeModule;
}
}
static getInstance(): HarmonyBridge {
if (!HarmonyBridge.instance) {
HarmonyBridge.instance = new HarmonyBridge();
}
return HarmonyBridge.instance;
}
// 安全的方法调用
async callMethod
methodName: keyof HarmonyNativeModule,
...args: any[]
): Promise
if (!this.module) {
console.warn(`Harmony模块不可用,跳过方法调用: ${methodName}`);
return this.getFallbackValue(methodName, args);
}
<"s3.j9k5.org.cn"><"f7.j9k5.org.cn"><"z9.j9k5.org.cn">
try {
const method = this.module[methodName];
if (typeof method !== 'function') {
throw new Error(`方法不存在: ${methodName}`);
}
return await method(...args);
} catch (error) {
console.error(`调用Harmony原生方法失败 ${methodName}:`, error);
return this.getFallbackValue(methodName, args);
}
}
private getFallbackValue(methodName: string, args: any[]): any {
const fallbacks: Record
getDeviceInfo: () => ({
deviceId: 'simulated_device',
deviceType: 'phone',
brand: 'Generic',
model: 'Simulator',
apiLevel: 8
}),
vibrate: () => {
// 使用React Native的振动API
if (NativeModules.Vibration) {
NativeModules.Vibration.vibrate(args[0] || 50);
}
}
};
return fallbacks[methodName] ? fallbacks[methodName]() : null;
}
// 便捷方法
async getDeviceInfo(): Promise
return this.callMethod('getDeviceInfo') || this.getFallbackValue('getDeviceInfo', []);
}
async triggerVibration(duration = 50): Promise
await this.callMethod('vibrate', duration);
}
}
export default HarmonyBridge;
```
## 开发流程与工具集成
### 自动化构建脚本
```bash
#!/bin/bash
# scripts/build-all.sh
set -e
echo "? 开始构建跨平台应用..."
# 参数处理
BUILD_MODE="debug"
PLATFORM="all"
CLEAN_BUILD=false
while [[ $# -gt 0 ]]; do
case $1 in
--mode)
BUILD_MODE="$2"
shift 2
;;
--platform)
PLATFORM="$2"
shift 2
;;
--clean)
CLEAN_BUILD=true
shift
;;
*)
echo "未知参数: $1"
exit 1
;;
esac
done
# 清理构建
if [ "$CLEAN_BUILD" = true ]; then
echo "? 清理构建缓存..."
rm -rf android/app/build
rm -rf ios/build
rm -rf harmony/build
npm run clean
fi
# 安装依赖
echo "? 安装依赖..."
npm ci
# 类型检查
echo "? 类型检查..."
npm run type-check
# 代码检查
echo "? 代码检查..."
npm run lint
# 运行测试
echo "? 运行测试..."
npm test -- --passWithNoTests
# 平台特定构建
build_platform() {
case $1 in
android)
echo "? 构建Android应用..."
cd android && ./gradlew assemble${BUILD_MODE^} || exit 1
cd ..
;;
ios)
echo "? 构建iOS应用..."
cd ios && xcodebuild \
-workspace MyHarmonyApp.xcworkspace \
-scheme MyHarmonyApp \
-configuration ${BUILD_MODE^} \
-destination 'generic/platform=iOS' \
build || exit 1
cd ..
;;
harmony)
echo "? 构建鸿蒙应用..."
npm run harmony:build || exit 1
;;
all)
build_platform android
build_platform ios
build_platform harmony
;;
*)
echo "未知平台: $1"
exit 1
;;
esac
}
build_platform $PLATFORM
echo "✅ 构建完成!"
echo "构建产物位置:"
[ "$PLATFORM" = "all" ] || [ "$PLATFORM" = "android" ] && echo "- Android: android/app/build/outputs/apk/"
[ "$PLATFORM" = "all" ] || [ "$PLATFORM" = "ios" ] && echo "- iOS: ios/build/"
[ "$PLATFORM" = "all" ] || [ "$PLATFORM" = "harmony" ] && echo "- Harmony: harmony/build/outputs/"
```
### 持续集成配置
```yaml
# .github/workflows/ci-cd.yml
name: CI/CD Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x, 20.x]
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Type check
run: npm run type-check
- name: Lint code
run: npm run lint
- name: Run tests
run: npm test -- --passWithNoTests --coverage
- name: Upload coverage
uses: codecov/codecov-action@v3
with:
file: ./coverage/lcov.info
build-android:
runs-on: ubuntu-latest
needs: test
steps:
- uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
- name: Install dependencies
run: npm ci
- name: Build Android
run: |
cd android
./gradlew assembleDebug
env:
ANDROID_HOME: ${{ secrets.ANDROID_HOME }}
- name: Upload APK
uses: actions/upload-artifact@v3
with:
name: android-apk
path: android/app/build/outputs/apk/debug/
build-harmony:
runs-on: ubuntu-latest
needs: test
if: false # 鸿蒙构建在CI中需要特殊环境
steps:
- uses: actions/checkout@v3
- name: Setup Harmony SDK
run: |
# 这里需要配置鸿蒙SDK环境
echo "Harmony构建需要特殊配置"
- name: Build Harmony
run: npm run harmony:build
```
## 开源项目交付准备
### 项目文档规范
```markdown
# MyHarmonyApp - 跨平台应用示例
## ? 特性
- 支持 iOS、Android、HarmonyOS 三端
- 基于 React Native 开发
- 完整的 TypeScript 支持
- 现代化的 UI/UX 设计
- 完善的测试覆盖
## ? 快速开始
### 环境要求
- Node.js >= 18.0.0
- npm >= 9.0.0
- React Native CLI
- 各平台开发环境
### 安装
```bash
git clone https://github.com/username/my-harmony-app.git
cd my-harmony-app
npm install
```
### 运行应用
```bash
# 运行 iOS
npm run ios
# 运行 Android
npm run android
# 运行 HarmonyOS
npm run harmony
# 构建所有平台
npm run build:all
```
## ?️ 项目结构
```
src/
├── components/ # 可复用组件
├── screens/ # 页面组件
├── services/ # API服务
├── navigation/ # 导航配置
├── utils/ # 工具函数
├── styles/ # 样式文件
└── types/ # TypeScript类型定义
```
## ? 开发指南
### 添加新功能
1. 创建相关组件/服务
2. 添加类型定义
3. 编写单元测试
4. 更新文档
### 代码规范
- 使用 TypeScript
- 遵循 ESLint 规则
- 提交前运行测试
- 编写清晰的注释
## ? 贡献指南
请阅读 [CONTRIBUTING.md](CONTRIBUTING.md) 了解如何参与项目开发。
## ? 许可证
本项目基于 MIT 许可证开源。
```
### 发布与版本管理
```json
// scripts/release.js
const { execSync } = require('child_process');
const fs = require('fs');
const path = require('path');
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
<"j2.j9k5.org.cn"><"n5.j9k5.org.cn"><"w1.j9k5.org.cn">
class ReleaseManager {
constructor() {
this.version = this.getCurrentVersion();
}
getCurrentVersion() {
const packageJson = JSON.parse(
fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf8')
);
return packageJson.version;
}
async prompt(question) {
return new Promise(resolve => {
rl.question(question, answer => {
resolve(answer);
});
});
}
async run() {
console.log(`? 当前版本: ${this.version}`);
// 选择发布类型
const releaseType = await this.prompt(
'选择发布类型 (major/minor/patch): '
);
if (!['major', 'minor', 'patch'].includes(releaseType)) {
console.error('❌ 无效的发布类型');
process.exit(1);
}
// 确认版本号
const newVersion = this.calculateNewVersion(releaseType);
const confirm = await this.prompt(
`确认发布版本 ${newVersion}? (y/N): `
);
if (confirm.toLowerCase() !== 'y') {
console.log('❌ 发布取消');
process.exit(0);
}
// 运行测试
console.log('? 运行测试...');
execSync('npm test', { stdio: 'inherit' });
// 更新版本号
this.updateVersion(newVersion);
// 生成更新日志
this.generateChangelog(newVersion);
// 提交更改
execSync(`git add .`, { stdio: 'inherit' });
execSync(`git commit -m "release: v${newVersion}"`, { stdio: 'inherit' });
execSync(`git tag v${newVersion}`, { stdio: 'inherit' });
// 推送
execSync('git push', { stdio: 'inherit' });
execSync(`git push origin v${newVersion}`, { stdio: 'inherit' });
console.log(`✅ 版本 ${newVersion} 发布成功!`);
rl.close();
}
calculateNewVersion(releaseType) {
const [major, minor, patch] = this.version.split('.').map(Number);
switch (releaseType) {
case 'major':
return `${major + 1}.0.0`;
case 'minor':
return `${major}.${minor + 1}.0`;
case 'patch':
return `${major}.${minor}.${patch + 1}`;
}
}
updateVersion(newVersion) {
const packagePath = path.join(__dirname, '..', 'package.json');
const packageJson = JSON.parse(fs.readFileSync(packagePath, 'utf8'));
packageJson.version = newVersion;
fs.writeFileSync(packagePath, JSON.stringify(packageJson, null, 2));
console.log(`? 更新版本号: ${newVersion}`);
}
generateChangelog(newVersion) {
const changelogPath = path.join(__dirname, '..', 'CHANGELOG.md');
let changelog = '';
if (fs.existsSync(changelogPath)) {
changelog = fs.readFileSync(changelogPath, 'utf8');
}
const newEntry = `## ${newVersion} (${
new Date().toISOString().split('T')[0]
})\n\n- TODO: 添加更新内容\n\n`;
fs.writeFileSync(changelogPath, newEntry + changelog);
console.log('? 更新变更日志');
}
}
// 运行发布流程
const manager = new ReleaseManager();
manager.run().catch(console.error);
```
## 质量保障与测试
### 测试配置
```javascript
// jest.config.js
module.exports = {
preset: 'react-native',
setupFiles: [
'
],
setupFilesAfterEnv: [
'@testing-library/jest-native/extend-expect'
],
transform: {
'^.+\\.(js|jsx|ts|tsx)$': 'babel-jest'
},
transformIgnorePatterns: [
'node_modules/(?!(react-native|@react-native|@react-navigation|@testing-library)/)'
],
moduleNameMapper: {
'^@/(.*)$': '
},
testMatch: [
'
'
],
collectCoverageFrom: [
'src/**/*.{js,jsx,ts,tsx}',
'!src/**/*.d.ts',
'!src/**/__tests__/**',
'!src/**/index.{js,ts}'
],
coverageThreshold: {
global: {
branches: 80,
functions: 80,
lines: 80,
statements: 80
}
},
reporters: [
'default',
['jest-junit', {
outputDirectory: 'test-results',
outputName: 'junit.xml'
}]
]
};
```
### 组件测试示例
```typescript
// src/components/Button/__tests__/Button.test.tsx
import React from 'react';
import { render, fireEvent } from '@testing-library/react-native';
import Button from '../Button';
describe('Button Component', () => {
it('渲染正确文本', () => {
const { getByText } = render();
expect(getByText('点击我')).toBeTruthy();
});
it('点击时调用onPress', () => {
const >
const { getByText } = render(
);
fireEvent.press(getByText('测试按钮'));
expect(onPressMock).toHaveBeenCalledTimes(1);
});
it('禁用时不响应点击', () => {
const >
const { getByText } = render(
);
fireEvent.press(getByText('禁用按钮'));
expect(onPressMock).not.toHaveBeenCalled();
});
it('显示加载状态', () => {
const { getByTestId } = render(
);
expect(getByTestId('loading-indicator')).toBeTruthy();
});
});
```
## 总结与最佳实践
1. **工程化规范**:
- 建立标准的目录结构
- 统一代码风格和类型检查
- 自动化构建和测试流程
2. **跨平台策略**:
- 抽象平台特定代码
- 提供统一的API接口
- 支持渐进式增强
3. **质量保障**:
- 完整的测试覆盖
- 持续集成部署
- 代码审查机制
4. **开源交付**:
- 完善的文档体系
- 清晰的贡献指南
- 规范的版本管理
5. **鸿蒙集成**:
- 充分利用鸿蒙特性
- 提供降级方案
- 保持代码可维护性
通过系统化的项目管理和技术实践,可以成功构建并交付高质量的React Native鸿蒙跨平台应用,为开源社区贡献有价值的技术方案。