已合并
refactor: use react-native submodule + patch instead of private react-native-core submodule #1373
zheng-jun-feng创建于 2025年8月6日
refactor: use react-native submodule + patch instead of private react-native-core submodule #1373
已合并
zheng-jun-feng创建于 2025年8月6日
从已删除 :0.77.1-rc.1-ohos合入到CPF-RN/ohos_react_native0.77.1-rc.1-ohos
共 9 个文件变更+4574-157
@@ -1,7 +1,3 @@
1-[submodule "packages/react-native-core"]
2-path = packages/react-native-core
3-url = https://gl.swmansion.com/rnoh/react-native-core.git
4-branch = react-native-core/v0.77.1
5[submodule "packages/tester/harmony/react_native_openharmony/src/main/cpp/third-party/boost"]1[submodule "packages/tester/harmony/react_native_openharmony/src/main/cpp/third-party/boost"]
6 path = packages/tester/harmony/react_native_openharmony/src/main/cpp/third-party/boost2 path = packages/tester/harmony/react_native_openharmony/src/main/cpp/third-party/boost
7 url = https://github.com/boostorg/boost.git3 url = https://github.com/boostorg/boost.git
@@ -26,3 +22,6 @@ branch = react-native-core/v0.77.1
26[submodule "packages/tester/harmony/react_native_openharmony/src/main/cpp/third-party/hermes"]22[submodule "packages/tester/harmony/react_native_openharmony/src/main/cpp/third-party/hermes"]
27 path = packages/tester/harmony/react_native_openharmony/src/main/cpp/third-party/hermes23 path = packages/tester/harmony/react_native_openharmony/src/main/cpp/third-party/hermes
28 url = https://github.com/facebook/hermes.git24 url = https://github.com/facebook/hermes.git
25+[submodule "packages/react-native"]
26+ path = packages/react-native
27+ url = https://github.com/facebook/react-native
@@ -6,4 +6,5 @@ RNOH maintainers and contributors.
6 6 
7- [Project Setup](./project-setup.md)7- [Project Setup](./project-setup.md)
8- [Style Guide](./style-guide.md)8- [Style Guide](./style-guide.md)
9+- [Modifying and Upgrading React Native](./modifying-and-upgrading-react-native.md)
9- [Performance Analysis Instructions](./performance-analysis-instructions.md)10- [Performance Analysis Instructions](./performance-analysis-instructions.md)
@@ -0,0 +1,56 @@
1+# Modifying and Upgrading React Native
linhandev
linhandevlinhandev2025年8月7日

doc needs update

likedislike
2+ 
3+## Definitions
4+ 
5+- RNC (React Native Core) — Unofficial name for the (ideally) platform-agnostic, reusable part of React Native.
6+ 
7+## Target Audience
8+ 
9+- RNOH maintainers who need to modify React Native to accomplish their tasks (RNOH contributors can't introduce changes to RNC)
10+- RNOH maintainers responsible for upgrading the React Native used by RNOH
11+- RN maintainers who want to help reduce friction between RN and RNOH
12+ 
13+## Modifying React Native and Handling OpenHarmony-specific code
14+ 
15+RNOH maintainers should avoid introducing changes to React Native. However, sometimes this isn't feasible or possible. In those situations, an RNOH maintainer can modify React Native by contributing to the unofficial, private RNC repository.
16+The contribution should aim to modify RN in a platform-agnostic manner, because those changes should be submitted later to the React Native repo. At the same time, changes should be as small as possible to avoid generating conflicts when upgrading React Native. These changes should help create an interface between RN and Out-of-Tree RN platforms. OpenHarmony-specific changes should be kept in `<RNOH>/packages/react-native-harmony`.
17+Once the contribution is merged, the RNOH maintainer should generate a new `react-native.patch` by running the following commands in the RNC repo:
18+ 
19+```
20+yarn install
21+yarn generate-patch
22+```
23+ 
24+The generated patch file should replace `<RNOH>/packages/react-native.patch`. RNOH and RN maintainers should work towards eliminating that patch.
25+ 
26+### Which RNC branch should be used?
27+ 
28+`react-native-core/v<RN_VERSION>`. RN_VERSION can be found in `<RNOH>/packages/tester/package.json::dependencies::react-native`. In case of multiple branches for the same RN_VERSION, check the comment at the first line in `<RNOH>/packages/react-native.patch`.
29+ 
30+### Where can I find the RNC repo?
31+ 
32+If you are an RNOH contributor, you can't. If you are a new RNOH maintainer, ask other RNOH maintainers.
33+ 
34+### Why can't RNC be public?
35+ 
36+Bureaucracy...
37+ 
38+## Upgrading React Native used by RNOH
39+ 
40+RNOH maintainers should keep RNOH as close as possible to RN to simplify the RN upgrading process for RNOH library and application maintainers. The difficulty of upgrading RN grows exponentially with time. This is a complex task. It should be done by an experienced RNOH maintainer.
41+ 
42+1. Create a temporary branch in the RNC repo, and cherry-pick patch commits from the current active branch.
43+1. Simplify patch commits to avoid resolving unnecessary conflicts (some commits may introduce changes and remove them later). Rebase that temporary branch and squash/delete commits if possible.
44+1. Create a new branch `react-native-core/v<NEW_RN_VERSION>`, let's call it NEW RNC BRANCH.
45+1. Cherry-pick simplified commits from the temporary branch to the NEW RNC BRANCH and resolve conflicts.
46+1. Update `<RNOH>/packages/react-native` submodule to point to the same revision as the one used by the starting point of NEW RNC BRANCH.
47+1. Regenerate the patch (as described [here](#modifying-react-native-and-handling-openharmony-specific-code)) and run pnpm init-ws (work directly on the NEW RNC BRANCH, consider creating an oneliner that generates a patch, copies it to the RNOH repo and runs `pnpm init-ws`).
48+1. Resolve compilation errors (it may require many iterations).
49+1. Resolve runtime issues - use concurrent and sequential tests in the tester app.
50+1. Resolve issues arising during reloads - keep reloading the tester application for ~2 minutes (memory leaks, deadlocks, and crashes can be detected with this approach).
51+1. Unlink failing libraries from `<RNOH>/tester-ecosystem` and document errors.
52+1. Create a new branch for the Release Candidate in the RNOH repo (follow the naming convention already used in the repo).
53+1. Submit a Merge Request (MR) to that new branch.
54+1. Once the MR is merged, make the NEW RNC BRANCH default.
55+ 
56+At this stage, RN is updated. However, it's likely RNOH isn't stable enough, and some new RN features may need to be implemented. RNOH with upgraded RN should be distributed gradually, but it's reasonable to publish a Release Candidate relatively quickly, so that RNOH library maintainers can start adapting incompatible libraries. Once the Release Candidate is public, notify maintainers of those libraries and send them documented errors, to speed up the process of migrating the RNOH ecosystem to the newer RN version.
@@ -0,0 +1 @@
1+Subproject commit 110450105e140d0846c63d3d15f356beefaeb020
@@ -1 +0,0 @@
1-Subproject commit d67f3d38e10146091d291c0a58614f77321ce707
@@ -58,126 +58,6 @@ importers:
58 specifier: 5.0.458 specifier: 5.0.4
59 version: 5.0.459 version: 5.0.4
60 60 
61- packages/react-native-core/packages/react-native:
62- dependencies:
63- '@jest/create-cache-key-function':
64- specifier: ^29.6.3
65- version: 29.7.0
66- '@react-native/assets-registry':
67- specifier: 0.77.1
68- version: 0.77.1
69- '@react-native/codegen':
70- specifier: 0.77.1
71- version: 0.77.1(@babel/preset-env@7.26.7(@babel/core@7.26.7))
72- '@react-native/community-cli-plugin':
73- specifier: 0.77.1
74- version: 0.77.1(@babel/core@7.26.7)(@babel/preset-env@7.26.7(@babel/core@7.26.7))(@react-native-community/cli-server-api@15.0.1)
75- '@react-native/gradle-plugin':
76- specifier: 0.77.1
77- version: 0.77.1
78- '@react-native/js-polyfills':
79- specifier: 0.77.1
80- version: 0.77.1
81- '@react-native/normalize-colors':
82- specifier: 0.77.1
83- version: 0.77.1
84- '@react-native/virtualized-lists':
85- specifier: 0.77.1
86- version: 0.77.1(@types/react@18.3.18)(react-native@0.77.1(@babel/core@7.26.7)(@babel/preset-env@7.26.7(@babel/core@7.26.7))(@react-native-community/cli-server-api@15.0.1)(@types/react@18.3.18)(react@18.3.1))(react@18.3.1)
87- '@types/react':
88- specifier: ^18.2.6
89- version: 18.3.18
90- abort-controller:
91- specifier: ^3.0.0
92- version: 3.0.0
93- anser:
94- specifier: ^1.4.9
95- version: 1.4.10
96- ansi-regex:
97- specifier: ^5.0.0
98- version: 5.0.1
99- babel-jest:
100- specifier: ^29.7.0
101- version: 29.7.0(@babel/core@7.26.7)
102- babel-plugin-syntax-hermes-parser:
103- specifier: 0.25.1
104- version: 0.25.1
105- base64-js:
106- specifier: ^1.5.1
107- version: 1.5.1
108- chalk:
109- specifier: ^4.0.0
110- version: 4.1.2
111- commander:
112- specifier: ^12.0.0
113- version: 12.1.0
114- event-target-shim:
115- specifier: ^5.0.1
116- version: 5.0.1
117- flow-enums-runtime:
118- specifier: ^0.0.6
119- version: 0.0.6
120- glob:
121- specifier: ^7.1.1
122- version: 7.2.3
123- invariant:
124- specifier: ^2.2.4
125- version: 2.2.4
126- jest-environment-node:
127- specifier: ^29.6.3
128- version: 29.7.0
129- jsc-android:
130- specifier: ^250231.0.0
131- version: 250231.0.0
132- memoize-one:
133- specifier: ^5.0.0
134- version: 5.2.1
135- metro-runtime:
136- specifier: ^0.81.0
137- version: 0.81.1
138- metro-source-map:
139- specifier: ^0.81.0
140- version: 0.81.1
141- nullthrows:
142- specifier: ^1.1.1
143- version: 1.1.1
144- pretty-format:
145- specifier: ^29.7.0
146- version: 29.7.0
147- promise:
148- specifier: ^8.3.0
149- version: 8.3.0
150- react:
151- specifier: ^18.2.0
152- version: 18.3.1
153- react-devtools-core:
154- specifier: ^6.0.1
155- version: 6.1.0
156- react-refresh:
157- specifier: ^0.14.0
158- version: 0.14.2
159- regenerator-runtime:
160- specifier: ^0.13.2
161- version: 0.13.11
162- scheduler:
163- specifier: 0.24.0-canary-efb381bbf-20230505
164- version: 0.24.0-canary-efb381bbf-20230505
165- semver:
166- specifier: ^7.1.3
167- version: 7.7.1
168- stacktrace-parser:
169- specifier: ^0.1.10
170- version: 0.1.10
171- whatwg-fetch:
172- specifier: ^3.0.0
173- version: 3.6.20
174- ws:
175- specifier: ^6.2.3
176- version: 6.2.3
177- yargs:
178- specifier: ^17.6.2
179- version: 17.7.2
180- 
181 packages/react-native-harmony:61 packages/react-native-harmony:
182 dependencies:62 dependencies:
183 '@react-native/assets-registry':63 '@react-native/assets-registry':
@@ -381,8 +261,8 @@ importers:
381 specifier: ^2.2.3261 specifier: ^2.2.3
382 version: 2.2.3262 version: 2.2.3
383 memfs:263 memfs:
384- specifier: ^4.12.0264+ specifier: 4.12.0
385- version: 4.17.0265+ version: 4.12.0
386 metro:266 metro:
387 specifier: ^0.81.0267 specifier: ^0.81.0
388 version: 0.81.1268 version: 0.81.1
@@ -6325,8 +6205,8 @@ packages:
6325 resolution: {integrity: sha512-qvwipnozMohxLXG1pOqoLiZKNkC4r4qqRucSoDwXowsNGDSULiqFTRUF05vcZWnwJSG22qTsynQhxbaMtnX9gw==}6205 resolution: {integrity: sha512-qvwipnozMohxLXG1pOqoLiZKNkC4r4qqRucSoDwXowsNGDSULiqFTRUF05vcZWnwJSG22qTsynQhxbaMtnX9gw==}
6326 engines: {node: '>=8'}6206 engines: {node: '>=8'}
6327 6207 
6328- memfs@4.17.0:6208+ memfs@4.12.0:
6329- resolution: {integrity: sha512-4eirfZ7thblFmqFjywlTmuWVSvccHAJbn1r8qQLzmTO11qcqpohOjmY2mFce6x7x7WtskzRqApPD0hv+Oa74jg==}6209+ resolution: {integrity: sha512-74wDsex5tQDSClVkeK1vtxqYCAgCoXxx+K4NSHzgU/muYVYByFqa+0RnrPO9NM6naWm1+G9JmZ0p6QHhXmeYfA==}
6330 engines: {node: '>= 4.0.0'}6210 engines: {node: '>= 4.0.0'}
6331 6211 
6332 memoize-one@5.2.1:6212 memoize-one@5.2.1:
@@ -11535,7 +11415,7 @@ snapshots:
11535 fs-extra: 11.3.011415 fs-extra: 11.3.0
11536 inquirer: 12.8.2(@types/node@22.13.1)11416 inquirer: 12.8.2(@types/node@22.13.1)
11537 json5: 2.2.311417 json5: 2.2.3
11538- memfs: 4.17.011418+ memfs: 4.12.0
11539 metro: 0.81.111419 metro: 0.81.1
11540 mustache: 4.2.011420 mustache: 4.2.0
11541 tar: 6.2.111421 tar: 6.2.1
@@ -12321,9 +12201,7 @@ snapshots:
12321 transitivePeerDependencies:12201 transitivePeerDependencies:
12322 - '@babel/core'12202 - '@babel/core'
12323 - '@babel/preset-env'12203 - '@babel/preset-env'
12324- - bufferutil
12325 - supports-color12204 - supports-color
12326- - utf-8-validate
12327 12205 
12328 '@react-native/normalize-color@2.1.0': {}12206 '@react-native/normalize-color@2.1.0': {}
12329 12207 
@@ -16189,7 +16067,7 @@ snapshots:
16189 mimic-fn: 2.1.016067 mimic-fn: 2.1.0
16190 p-is-promise: 2.1.016068 p-is-promise: 2.1.0
16191 16069 
16192- memfs@4.17.0:16070+ memfs@4.12.0:
16193 dependencies:16071 dependencies:
16194 '@jsonjoy.com/json-pack': 1.1.1(tslib@2.8.1)16072 '@jsonjoy.com/json-pack': 1.1.1(tslib@2.8.1)
16195 '@jsonjoy.com/util': 1.5.0(tslib@2.8.1)16073 '@jsonjoy.com/util': 1.5.0(tslib@2.8.1)
@@ -5,7 +5,6 @@ packages:
5 - 'packages/tester'5 - 'packages/tester'
6 - 'packages/tester-ecosystem'6 - 'packages/tester-ecosystem'
7 - 'packages/testerino'7 - 'packages/testerino'
8- - 'packages/react-native-core/packages/react-native'
9 - 'packages/hdc-server'8 - 'packages/hdc-server'
10 - 'packages/react-native-harmony-test-kit'9 - 'packages/react-native-harmony-test-kit'
11 - 'packages/react-native-harmony-61-interop'10 - 'packages/react-native-harmony-61-interop'
@@ -3,27 +3,38 @@ import pathUtils from 'node:path';
3import { execSync } from 'child_process';3import { execSync } from 'child_process';
4import { unlinkSync } from 'fs';4import { unlinkSync } from 'fs';
5 5 
6-const repoRootPath = pathUtils.resolve(__dirname, '..');6+const REPO_ROOT_PATH = pathUtils.resolve(__dirname, '..');
7-const rnohPkgRootPath = pathUtils.join(7+const RNOH_PKG_ROOT_PATH = pathUtils.join(
8- repoRootPath,8+ REPO_ROOT_PATH,
9 'packages',9 'packages',
10 'react-native-harmony'10 'react-native-harmony'
11);11);
12-const reactNativePkgRootPath = pathUtils.join(12+ 
13- repoRootPath,13+const REACT_NATIVE_SUBMODULE_PATH = pathUtils.join(
14- 'packages',14+ REPO_ROOT_PATH,
15- 'react-native-core',
16 'packages',15 'packages',
17 'react-native'16 'react-native'
18);17);
19 18 
20-const reactCommonSrcPath = pathUtils.join(19+const REACT_NATIVE_PATCH_PATH = pathUtils.join(
21- reactNativePkgRootPath,20+ REPO_ROOT_PATH,
21+ 'packages',
22+ 'react-native.patch'
23+);
24+ 
25+const REACT_NATIVE_PKG_ROOT_PATH = pathUtils.join(
26+ REACT_NATIVE_SUBMODULE_PATH,
27+ 'packages',
28+ 'react-native'
29+);
30+ 
31+const REACT_COMMON_SRC_PATH = pathUtils.join(
32+ REACT_NATIVE_PKG_ROOT_PATH,
22 'ReactCommon'33 'ReactCommon'
23);34);
24 35 
25-const reactCommonDestPath = pathUtils.join(36+const REACT_COMMON_DEST_PATH = pathUtils.join(
26- repoRootPath,37+ REPO_ROOT_PATH,
27 'packages',38 'packages',
28 'tester',39 'tester',
29 'harmony',40 'harmony',
@@ -36,20 +47,38 @@ const reactCommonDestPath = pathUtils.join(
36 'ReactCommon'47 'ReactCommon'
37);48);
38 49 
39-syncJS('delegates');50+try {
40-syncJS('Libraries');51+ applyPatch();
41-syncJS('src');52+ syncJS('delegates');
42-syncJS('types');53+ syncJS('Libraries');
43-syncCpp();54+ syncJS('src');
55+ syncJS('types');
56+ syncCpp();
57+} finally {
58+ cleanReactNativeSubmodule();
59+}
60+ 
61+function applyPatch() {
62+ cleanReactNativeSubmodule();
63+ execSync(`git apply --whitespace=fix ${REACT_NATIVE_PATCH_PATH}`, {
64+ cwd: REACT_NATIVE_SUBMODULE_PATH,
65+ });
66+}
67+ 
68+function cleanReactNativeSubmodule() {
69+ execSync('git reset --hard HEAD && git clean -dfx', {
70+ cwd: REACT_NATIVE_SUBMODULE_PATH,
71+ });
72+}
44 73 
45function syncJS(pathRelativeToRNRoot: string) {74function syncJS(pathRelativeToRNRoot: string) {
46- const destPath = pathUtils.join(rnohPkgRootPath, pathRelativeToRNRoot);75+ const destPath = pathUtils.join(RNOH_PKG_ROOT_PATH, pathRelativeToRNRoot);
47 if (!fs.existsSync(destPath)) {76 if (!fs.existsSync(destPath)) {
48 fs.mkdirSync(destPath);77 fs.mkdirSync(destPath);
49 }78 }
50 removeUntrackedFiles(destPath);79 removeUntrackedFiles(destPath);
51 fs.cpSync(80 fs.cpSync(
52- pathUtils.join(reactNativePkgRootPath, pathRelativeToRNRoot),81+ pathUtils.join(REACT_NATIVE_PKG_ROOT_PATH, pathRelativeToRNRoot),
53 destPath,82 destPath,
54 { recursive: true }83 { recursive: true }
55 );84 );
@@ -70,12 +99,12 @@ function removeUntrackedFiles(dirPath: string): void {
70}99}
71 100 
72function syncCpp() {101function syncCpp() {
73- if (!fs.existsSync(reactCommonDestPath)) {102+ if (!fs.existsSync(REACT_COMMON_DEST_PATH)) {
74- fs.mkdirSync(reactCommonDestPath);103+ fs.mkdirSync(REACT_COMMON_DEST_PATH);
75 }104 }
76- removeUntrackedFiles(reactCommonDestPath);105+ removeUntrackedFiles(REACT_COMMON_DEST_PATH);
77- fs.cpSync(reactCommonSrcPath, reactCommonDestPath, { recursive: true });106+ fs.cpSync(REACT_COMMON_SRC_PATH, REACT_COMMON_DEST_PATH, { recursive: true });
78 console.log(107 console.log(
79- `synchronized: ${pathUtils.relative(process.cwd(), reactCommonDestPath)}`108+ `synchronized: ${pathUtils.relative(process.cwd(), REACT_COMMON_DEST_PATH)}`
80 );109 );
81}110}