1# 动态加载 2 3<!--Kit: ArkTS--> 4<!--Subsystem: ArkCompiler--> 5<!--Owner: @huyunhui1; @oh-rgx1; @zmw1--> 6<!--Designer: @ctw-ian--> 7<!--Tester: @kirl75; @zsw_zhushiwei--> 8<!--Adviser: @foryourself--> 9 10动态import支持条件延迟加载,支持部分反射功能,可以提升页面的加载速度;动态import支持加载HSP模块/HAR模块/OHPM包/Native库等,并且HAR模块间只有变量动态import时还可以进行模块解耦。 11 12## 技术适用场景介绍 13应用开发的有些场景中,如果希望根据条件导入模块或者按需导入模块,可以使用动态import代替[静态import](../quick-start/introduction-to-arkts.md#导入)。下面是可能会需要动态import的场景: 14 15* 当静态import的模块明显降低了代码的加载速度且很少被使用,或者并不需要马上使用它。 16* 当静态import的模块明显占用了大量的系统内存且很少被使用。 17* 当被导入的模块,在加载时并不存在,需要异步获取。 18* 当需要动态构建模块说明符时,应使用动态import。静态import仅支持静态说明符。 19* 当导入的模块存在副作用(即模块中包含直接运行的代码),这些副作用仅在满足特定条件时才需要。 20 21## 业务扩展场景介绍 22动态import在业务上除了能实现条件延迟加载,还可以实现部分反射功能。实例如下,HAP动态import HAR包harlibrary,并调用类Calc的静态成员函数staticAdd()、成员函数instanceAdd(),以及全局方法addHarLibrary()。 23```typescript 24// harlibrary's src/main/ets/utils/Calc.ets 25export class Calc { 26 public static staticAdd(a: number, b: number): number { 27 let c = a + b; 28 console.info('DynamicImport I am harlibrary in staticAdd, %d + %d = %d', a, b, c); 29 return c; 30 } 31 32 public instanceAdd(a: number, b: number): number { 33 let c = a + b; 34 console.info('DynamicImport I am harlibrary in instanceAdd, %d + %d = %d', a, b, c); 35 return c; 36 } 37} 38 39export function addHarLibrary(a: number, b: number): number { 40 let c = a + b; 41 console.info('DynamicImport I am harlibrary in addHarLibrary, %d + %d = %d', a, b, c); 42 return c; 43} 44``` 45 46```typescript 47// harlibrary's Index.ets 48export { Calc, addHarLibrary } from './src/main/ets/utils/Calc' 49``` 50 51```json5 52// HAP's oh-package.json5 53"dependencies": { 54 "harlibrary": "file:../harlibrary" 55} 56``` 57 58```typescript 59// HAP's src/main/ets/pages/Index.ets 60import('harlibrary').then((ns:ESObject) => { 61 ns.Calc.staticAdd(8, 9); // 调用静态成员函数staticAdd() 62 let calc:ESObject = new ns.Calc(); // 实例化类Calc 63 calc.instanceAdd(10, 11); // 调用成员函数instanceAdd() 64 ns.addHarLibrary(6, 7); // 调用全局方法addHarLibrary() 65 66 // 使用类、成员函数和方法的字符串名字进行反射调用 67 let className = 'Calc'; 68 let methodName = 'instanceAdd'; 69 let staticMethod = 'staticAdd'; 70 let functionName = 'addHarLibrary'; 71 ns[className][staticMethod](12, 13); // 调用静态成员函数staticAdd() 72 let calc1:ESObject = new ns[className](); // 实例化类Calc 73 calc1[methodName](14, 15); // 调用成员函数instanceAdd() 74 ns[functionName](16, 17); // 调用全局方法addHarLibrary() 75}); 76``` 77 78## 动态import实现方案介绍 79动态import根据入参是常量或变量,分为动态import常量表达式和动态import变量表达式两大特性规格。 80以下是动态import支持的规格列表: 81 82| 动态import场景 | 动态import详细分类 | 说明 | 83| :------------- | :----------------------------- | :------------------------------------------------------- | 84| 本地工程模块 | 动态import模块内文件路径 | 要求路径以./或../开头。 | 85| 本地工程模块 | 动态import HSP模块名 | - | 86| 本地工程模块 | 动态import HSP模块文件路径 | - | 87| 本地工程模块 | 动态import HAR模块名 | - | 88| 本地工程模块 | 动态import HAR模块文件路径 | - | 89| 远程包 | 动态import远程HAR模块名 | - | 90| 远程包 | 动态import ohpm包名 | - | 91| API | 动态import @system.* | - | 92| API | 动态import @ohos.* | - | 93| API | 动态import @arkui-x.* | - | 94| 模块Native库 | 动态import libNativeLibrary.so | - | 95 96>**说明:** 97> 98> 1.当前所有import中使用的模块名都是依赖方oh-package.json5文件中dependencies项的别名。</br> 99> 2.本地模块在依赖方的dependencies中配置的别名建议与moduleName以及packageName三者一致。moduleName指的是被依赖的HSP/HAR的module.json5中配置的名字,packageName指的是被依赖的HSP/HAR的oh-package.json5中配置的名字。</br> 100> 3.import一个模块名,实际的行为是import该模块的入口文件,一般为Index.ets/ts。 101 102## 动态import实现中的关键点 103 104### 动态import常量表达式 105 106动态import常量表达式是指动态import的入参为常量的场景。下面以HAP引用其他模块的API的示例来说明典型用法。 107 108本文示例代码中的路径,如Index.ets,是根据当前DevEco Studio的模块配置设置的。如果后续有变化,请调整文件的位置和相对路径。 109 110- **HAP常量动态import HAR模块名** 111 112 ```typescript 113 // HAR's Index.ets 114 export function add(a: number, b: number): number { 115 let c = a + b; 116 console.info('DynamicImport I am a HAR, %d + %d = %d', a, b, c); 117 return c; 118 } 119 ``` 120 121 ```typescript 122 // HAP's src/main/ets/pages/Index.ets 123 import('myhar').then((ns:ESObject) => { 124 console.info('DynamicImport ns.add(3, 5) = %d', ns.add(3, 5)); 125 }); 126 127 // 可使用 await 处理动态import (必须在 async 函数内使用) 128 async function asyncDynamicImport() { 129 let ns:ESObject = await import('myhar'); 130 console.info('DynamicImport ns.add(3, 5) = %d', ns.add(3, 5)); 131 } 132 ``` 133 134 ```json5 135 // HAP's oh-package.json5 136 "dependencies": { 137 "myhar": "file:../myhar" 138 } 139 ``` 140 141- **HAP常量动态import HAR模块文件路径** 142 143 ```typescript 144 // HAR's Index.ets 145 export function add(a: number, b: number): number { 146 let c = a + b; 147 console.info('DynamicImport I am a HAR, %d + %d = %d', a, b, c); 148 return c; 149 } 150 ``` 151 152 ```typescript 153 // HAP's src/main/ets/pages/Index.ets 154 import('myhar/Index').then((ns:ESObject) => { 155 console.info('DynamicImport ns.add(3, 5) = %d', ns.add(3, 5)); 156 }); 157 ``` 158 159 ```json5 160 // HAP's oh-package.json5 161 "dependencies": { 162 "myhar": "file:../myhar" 163 } 164 ``` 165 166- **HAP常量动态import HSP模块名** 167 168 ```typescript 169 // HSP's Index.ets 170 export function add(a: number, b: number): number { 171 let c = a + b; 172 console.info('DynamicImport I am a HSP, %d + %d = %d', a, b, c); 173 return c; 174 } 175 ``` 176 177 ```typescript 178 // HAP's src/main/ets/pages/Index.ets 179 import('myhsp').then((ns:ESObject) => { 180 console.info('DynamicImport ns.add(3, 5) = %d', ns.add(3, 5)); 181 }); 182 ``` 183 184 ```json5 185 // HAP's oh-package.json5 186 "dependencies": { 187 "myhsp": "file:../myhsp" 188 } 189 ``` 190 191- **HAP常量动态import HSP模块名文件路径** 192 193 ```typescript 194 // HSP's Index.ets 195 export function add(a: number, b: number): number { 196 let c = a + b; 197 console.info('DynamicImport I am a HSP, %d + %d = %d', a, b, c); 198 return c; 199 } 200 ``` 201 202 ```typescript 203 // HAP's src/main/ets/pages/Index.ets 204 import('myhsp/Index').then((ns:ESObject) => { 205 console.info('DynamicImport ns.add(3, 5) = %d', ns.add(3, 5)); 206 }); 207 ``` 208 209 ```json5 210 // HAP's oh-package.json5 211 "dependencies": { 212 "myhsp": "file:../myhsp" 213 } 214 ``` 215 216- **HAP常量动态import远程HAR模块名** 217 218 ```typescript 219 // HAP's src/main/ets/pages/Index.ets 220 import('@ohos/crypto-js').then((ns:ESObject) => { 221 console.info('DynamicImport @ohos/crypto-js: ' + ns.CryptoJS.MD5(123456)); 222 }); 223 ``` 224 225 ```json5 226 // HAP's oh-package.json5 227 "dependencies": { 228 "@ohos/crypto-js": "2.0.3-rc.0" 229 } 230 ``` 231 232- **HAP常量动态import ohpm包** 233 234 ```typescript 235 // HAP's src/main/ets/pages/Index.ets 236 import('json5').then((ns:ESObject) => { 237 console.info('DynamicImport json5'); 238 }); 239 ``` 240 241 ```json5 242 // HAP's oh-package.json5 243 "dependencies": { 244 "json5": "1.0.2" 245 } 246 ``` 247 248- **HAP常量动态import自己的单文件** 249 250 ```typescript 251 // HAP's src/main/ets/Calc.ets 252 export function add(a: number, b: number): number { 253 let c = a + b; 254 console.info('DynamicImport I am a HAP, %d + %d = %d', a, b, c); 255 return c; 256 } 257 ``` 258 259 ```typescript 260 // HAP's src/main/ets/pages/Index.ets 261 import('../Calc').then((ns:ESObject) => { 262 console.info('DynamicImport ns.add(3, 5) = %d', ns.add(3, 5)); 263 }); 264 ``` 265 266- **HAP常量动态import自己的Native库** 267 268 ```typescript 269 // libnativeapi.so's index.d.ts 270 export const add: (a: number, b: number) => number; 271 ``` 272 273 ```typescript 274 // HAP's src/main/ets/pages/Index.ets 275 import('libnativeapi.so').then((ns:ESObject) => { 276 console.info('DynamicImport libnativeapi.so: ' + ns.default.add(2, 3)); 277 }); 278 ``` 279 280 ```json5 281 // HAP's oh-package.json5 282 "dependencies": { 283 "libnativeapi.so": "file:./src/main/cpp/types/libnativeapi" 284 } 285 ``` 286 287- **HAP常量动态import加载API** 288 289 ```typescript 290 // HAP's src/main/ets/pages/Index.ets 291 import('@system.app').then((ns:ESObject) => { ns.default.terminate(); }); 292 import('@system.router').then((ns:ESObject) => { ns.default.clear(); }); 293 import('@ohos.curves').then((ns:ESObject) => { ns.default.springMotion(0.555, 0.75, 0.001); }); 294 import('@ohos.matrix4').then((ns:ESObject) => { ns.default.identity(); }); 295 import('@ohos.hilog').then((ns:ESObject) => { ns.default.info(0x0000, 'testTag', '%{public}s', 'DynamicImport @ohos.hilog.'); }); 296 ``` 297 298### 动态import变量表达式 299 300DevEco Studio中模块间的依赖关系通过oh-package.json5中的dependencies字段进行配置。dependencies列表中所有的模块默认都会进行安装(本地模块)或下载(远程模块),但是不会默认参与编译。HAP/HSP编译时会以入口文件(一般为Index.ets/Index.ts)开始搜索依赖关系,搜索到的模块或文件才会加入编译。 301在编译期,静态import和常量动态import可以被打包工具rollup及其插件识别解析,加入依赖树中,参与编译流程,最终生成方舟字节码。但是,如果是变量动态import,该变量值可能需要进行运算或外部传入才能得到,在编译态无法解析其内容,也就无法加入编译。为了将这部分模块/文件加入编译,还需要额外增加一个runtimeOnly的buildOption配置,用于指定动态import的变量实际的模块名或文件路径。 302 303**1. runtimeOnly字段schema配置格式** 304 305在HAP/HSP/HAR的build-profile.json5中的buildOption中增加runtimeOnly配置项,仅在通过变量动态import时配置,静态import和常量动态import无需配置;并且,通过变量动态import加载API时也无需配置runtimeOnly。如下实例说明如何配置通过变量动态import其他模块,以及变量动态import本模块自己的单文件: 306 307```typescript 308// 变量动态import其他模块myhar 309let harName = 'myhar'; 310import(harName).then((obj: ESObject) => { 311 console.info('DynamicImport I am a har'); 312}) 313 314// 变量动态import本模块自己的单文件src/main/ets/index.ets 315let filePath = './utils/Calc'; 316import(filePath).then((obj: ESObject) => { 317 console.info('DynamicImport I am a file'); 318}) 319``` 320 321对应的runtimeOnly配置: 322 323```json 324"buildOption": { 325 "arkOptions": { 326 "runtimeOnly": { 327 "packages": [ "myhar" ], // 配置本模块变量动态import其他模块名,要求与dependencies中配置的名字一致。 328 "sources": [ "./src/main/ets/utils/Calc.ets" ] // 配置本模块变量动态import自己的文件路径,路径相对于当前build-profile.json5文件。 329 } 330 } 331} 332``` 333 334"runtimeOnly"的"packages":用于配置本模块变量动态import其他模块名,要求与dependencies中配置的名字一致。 335"runtimeOnly"的"sources":用于配置本模块变量动态import自己的文件路径,路径相对于当前build-profile.json5文件。 336 337**2. 使用实例** 338 339- **HAP变量动态import HAR模块名** 340 341 ```typescript 342 // HAR's Index.ets 343 export function add(a: number, b: number): number { 344 let c = a + b; 345 console.info('DynamicImport I am a HAR, %d + %d = %d', a, b, c); 346 return c; 347 } 348 ``` 349 ```typescript 350 // HAP's src/main/ets/pages/Index.ets 351 let packageName = 'myhar'; 352 import(packageName).then((ns:ESObject) => { 353 console.info('DynamicImport ns.add(3, 5) = %d', ns.add(3, 5)); 354 }); 355 ``` 356 ```json5 357 // HAP's oh-package.json5 358 "dependencies": { 359 "myhar": "file:../myhar" 360 } 361 ``` 362 ```json5 363 // HAP's build-profile.json5 364 "buildOption": { 365 "arkOptions": { 366 "runtimeOnly": { 367 "packages": [ 368 "myhar" // 仅用于使用变量动态import其他模块名场景,静态import或常量动态import无需配置。 369 ] 370 } 371 } 372 } 373 ``` 374 375- **HAP变量动态import HSP模块名** 376 377 ```typescript 378 // HSP's Index.ets 379 export function add(a: number, b: number): number { 380 let c = a + b; 381 console.info('DynamicImport I am a HSP, %d + %d = %d', a, b, c); 382 return c; 383 } 384 ``` 385 ```typescript 386 // HAP's src/main/ets/pages/Index.ets 387 let packageName = 'myhsp'; 388 import(packageName).then((ns:ESObject) => { 389 console.info('DynamicImport ns.add(3, 5) = %d', ns.add(3, 5)); 390 }); 391 ``` 392 ```json5 393 // HAP's oh-package.json5 394 "dependencies": { 395 "myhsp": "file:../myhsp" 396 } 397 ``` 398 ```json5 399 // HAP's build-profile.json5 400 "buildOption": { 401 "arkOptions": { 402 "runtimeOnly": { 403 "packages": [ 404 "myhsp" // 仅用于使用变量动态import其他模块名场景,静态import或常量动态import无需配置。 405 ] 406 } 407 } 408 } 409 ``` 410 411- **HAP变量动态import远程HAR模块名** 412 413 ```typescript 414 // HAP's src/main/ets/pages/Index.ets 415 let packageName = '@ohos/crypto-js'; 416 import(packageName).then((ns:ESObject) => { 417 console.info('DynamicImport @ohos/crypto-js: ' + ns.CryptoJS.MD5(123456)); 418 }); 419 ``` 420 ```json5 421 // HAP's oh-package.json5 422 "dependencies": { 423 "@ohos/crypto-js": "2.0.3-rc.0" 424 } 425 ``` 426 ```json5 427 // HAP's build-profile.json5 428 "buildOption": { 429 "arkOptions": { 430 "runtimeOnly": { 431 "packages": [ 432 "@ohos/crypto-js" // 仅用于使用变量动态import其他模块名场景,静态import或常量动态import无需配置。 433 ] 434 } 435 } 436 } 437 ``` 438 439- **HAP变量动态import ohpm包** 440 441 ```typescript 442 // HAP's src/main/ets/pages/Index.ets 443 let packageName = 'json5'; 444 import(packageName).then((ns:ESObject) => { 445 console.info('DynamicImport json5'); 446 }); 447 ``` 448 ```json5 449 // HAP's oh-package.json5 450 "dependencies": { 451 "json5": "1.0.2" 452 } 453 ``` 454 ```json5 455 // HAP's build-profile.json5 456 "buildOption": { 457 "arkOptions": { 458 "runtimeOnly": { 459 "packages": [ 460 "json5" // 仅用于使用变量动态import其他模块名场景,静态import或常量动态import无需配置。 461 ] 462 } 463 } 464 } 465 ``` 466 467- **HAP变量动态import自己的单文件** 468 469 ```typescript 470 // HAP's src/main/ets/Calc.ets 471 export function add(a: number, b: number): number { 472 let c = a + b; 473 console.info('DynamicImport I am a HAP, %d + %d = %d', a, b, c); 474 return c; 475 } 476 ``` 477 ```typescript 478 // HAP's src/main/ets/pages/Index.ets 479 let filePath = '../Calc'; 480 import(filePath).then((ns:ESObject) => { 481 console.info('DynamicImport ns.add(3, 5) = %d', ns.add(3, 5)); 482 }); 483 ``` 484 ```json5 485 // HAP's build-profile.json5 486 "buildOption": { 487 "arkOptions": { 488 "runtimeOnly": { 489 "sources": [ 490 "./src/main/ets/Calc.ets" // 仅用于使用变量动态import模块自己单文件场景,静态import或常量动态import无需配置。 491 ] 492 } 493 } 494 } 495 ``` 496 497- **HAP变量动态import自己的Native库** 498 499 ```typescript 500 // libnativeapi.so's index.d.ts 501 export const add: (a: number, b: number) => number; 502 ``` 503 ```typescript 504 // HAP's src/main/ets/pages/Index.ets 505 let soName = 'libnativeapi.so'; 506 import(soName).then((ns:ESObject) => { 507 console.info('DynamicImport libnativeapi.so: ' + ns.default.add(2, 3)); 508 }); 509 ``` 510 ```json5 511 // HAP's oh-package.json5 512 "dependencies": { 513 "libnativeapi.so": "file:./src/main/cpp/types/libnativeapi" 514 } 515 ``` 516 ```json5 517 // HAP's build-profile.json5 518 "buildOption": { 519 "arkOptions": { 520 "runtimeOnly": { 521 "packages": [ 522 "libnativeapi.so" // 仅用于使用变量动态import其他模块名场景,静态import或常量动态import无需配置。 523 ] 524 } 525 } 526 } 527 ``` 528 529- **HAP变量动态import加载API** 530 531 ```typescript 532 // HAP's src/main/ets/pages/Index.ets 533 let packageName = '@system.app'; 534 import(packageName).then((ns:ESObject) => { ns.default.terminate(); }); 535 packageName = '@system.router'; 536 import(packageName).then((ns:ESObject) => { ns.default.clear(); }); 537 packageName = '@ohos.curves'; 538 import(packageName).then((ns:ESObject) => { ns.default.springMotion(0.555, 0.75, 0.001); }); 539 packageName = '@ohos.matrix4'; 540 import(packageName).then((ns:ESObject) => { ns.default.identity(); }); 541 packageName = '@ohos.hilog'; 542 import(packageName).then((ns:ESObject) => { ns.default.info(0x0000, 'testTag', '%{public}s', 'DynamicImport @ohos.hilog.'); }); 543 ``` 544通过变量动态import加载API时无需配置runtimeOnly。 545 546### HAR模块间动态import依赖解耦 547当应用包含多个HAR包,HAR包之间的依赖关系比较复杂。在DevEco Studio中配置依赖关系时,可能会形成循环依赖。这时,如果HAR之间的依赖关系中仅有变量动态import,可以将HAR包之间直接依赖关系转移到HAP/HSP中配置,HAR包之间无需配置依赖关系,从而达到HAR包间依赖解耦的目的。如下示意图: 548 549 550 551HAR之间的依赖关系转移至HAP/HSP后: 552 553 554 555 556**使用限制** 557- 仅限在本地源码HAR包之间存在循环依赖时,使用该规避方案。 558- 被转移依赖的HAR之间只能通过变量动态import,不能有静态import或常量动态import。 559- 转移依赖时,需同时转移**dependencies**和**runtimeOnly**依赖配置。 560- HSP不支持转移依赖。即:HAP->HSP1->HSP2->HSP3,这里的HSP2和HSP3不能转移到HAP上面。 561- 转移依赖的整个链路上只能有HAR包,不能跨越HSP转移。即:HAP->HAR1->HAR2->HSP->HAR3->HAR4,HAR1对HAR2的依赖可以转移到HAP上,HAR3对HAR4的依赖可以转移到HSP上。但是,不能将HAR3或HAR4转移到HAP上。 562- 如果引用了其他工程模块、远程包或集成HSP,需确保**useNormalizedOHMUrl**配置一致,同时设置为true或false,否则可能导致运行错误:**Cannot find dynamic-import module library**。 563 564 565**使用实例** 566 567下面的实例通过在单向依赖HAP->HAR1->HAR2->HAR3之上增加依赖HAR2->HAR1、HAR3->HAR1,形成了循环依赖。 568 569 570 571```typescript 572// HAP's src/main/ets/pages/Index.ets 573let harName = 'har1' 574import(harName).then((ns: ESObject) => { 575 console.info('[DynamicImport] hap -> har1, 0 + 1 = ' + ns.classHar1.add(0, 1)); 576}) 577 578// HAR1's src/main/ets/utils/Calc.ets 579export class classHar1 { 580 static isImportedHar2: boolean = false; 581 582 static add(a: number, b: number): number { 583 const c = a + b; 584 console.info('[DynamicImport] classHar1.add(), %d + %d = %d', a, b, c); 585 586 if (!classHar1.isImportedHar2) { 587 const harName = 'har2'; 588 import(harName).then((ns: ESObject) => { 589 classHar1.isImportedHar2 = true; 590 console.info('[DynamicImport] har1 -> har2, 1 + 2 = ' + ns.classHar2.add(1, 2)); 591 }) 592 } 593 594 return c; 595 } 596} 597// HAR1's Index.ets 598export { classHar1 } from './src/main/ets/utils/Calc'; 599 600// HAR2's src/main/ets/utils/Calc.ets 601export class classHar2 { 602 static isImportedHar1: boolean = false; 603 static isImportedHar3: boolean = false; 604 605 static add(a: number, b: number): number { 606 const c = a + b; 607 console.info('[DynamicImport] classHar2.add(), %d + %d = %d', a, b, c); 608 609 if (!classHar2.isImportedHar1) { 610 const harName = 'har1'; 611 import(harName).then((ns: ESObject) => { 612 classHar2.isImportedHar1 = true; 613 console.info('[DynamicImport] har2 -> har1, 2 + 1 = ' + ns.classHar1.add(2, 1)); 614 }) 615 } 616 617 if (!classHar2.isImportedHar3) { 618 const harName = 'har3'; 619 import(harName).then((ns: ESObject) => { 620 classHar2.isImportedHar3 = true; 621 console.info('[DynamicImport] har2 -> har3, 2 + 3 = ' + ns.classHar3.add(2, 3)); 622 }) 623 } 624 625 return c; 626 } 627} 628// HAR2's Index.ets 629export { classHar2 } from './src/main/ets/utils/Calc'; 630 631// HAR3's src/main/ets/utils/Calc.ets 632export class classHar3 { 633 static isImportedHar1: boolean = false; 634 635 static add(a: number, b: number): number { 636 const c = a + b; 637 console.info('[DynamicImport] classHar3.add(), %d + %d = %d', a, b, c); 638 639 if (!classHar3.isImportedHar1) { 640 const harName = 'har1'; 641 import(harName).then((ns: ESObject) => { 642 classHar3.isImportedHar1 = true; 643 console.info('[DynamicImport] har3 -> har1, 3 + 1 = ' + ns.classHar1.add(3, 1)); 644 }) 645 } 646 647 return c; 648 } 649} 650// HAR3's Index.ets 651export { classHar3 } from './src/main/ets/utils/Calc'; 652``` 653 654若未对HAR之间的**dependencies**和**runtimeOnly**配置进行依赖解耦,ohpm无法解决循环依赖,依赖安装失败。 655 656```json5 657// HAP's oh-package.json5 658"dependencies": { 659 "har1": "file:../har1" 660} 661// HAP's build-profile.json5 662"buildOption": { 663 "arkOptions": { 664 "runtimeOnly": { 665 "packages": [ // 仅用于变量动态加载的场景,静态加载或常量动态加载无需配置。 666 "har1" 667 ] 668 } 669 } 670} 671 672// HAR1's oh-package.json5 673"dependencies": { 674 "har2": "file:../har2" 675} 676// HAR1's build-profile.json5 677"buildOption": { 678 "arkOptions": { 679 "runtimeOnly": { 680 "packages": [ // 仅用于变量动态加载的场景,静态加载或常量动态加载无需配置。 681 "har2" 682 ] 683 } 684 } 685} 686 687// HAR2's oh-package.json5 688"dependencies": { 689 "har1": "file:../har1", 690 "har3": "file:../har3" 691} 692// HAR2's build-profile.json5 693"buildOption": { 694 "arkOptions": { 695 "runtimeOnly": { 696 "packages": [ // 仅用于变量动态加载的场景,静态加载或常量动态加载无需配置。 697 "har1", 698 "har3" 699 ] 700 } 701 } 702} 703 704// HAR3's oh-package.json5 705"dependencies": { 706 "har1": "file:../har1", 707} 708// HAR3's build-profile.json5 709"buildOption": { 710 "arkOptions": { 711 "runtimeOnly": { 712 "packages": [ // 仅用于变量动态加载的场景,静态加载或常量动态加载无需配置。 713 "har1" 714 ] 715 } 716 } 717} 718``` 719 720**对应的报错信息如下:** 721 722```text 723ohpm ERROR: Run install command failed 724Error: 00618005 Invalid Dependency 725Error Message: Invalid dependency har2@~\Coupled\har2 -> har2@1.0.0. 726 727Try the following: 728The name of an indirect dependency cannot be the same as the module name. 729``` 730 731将HAR之间的**dependencies**和**runtimeOnly**配置转移到HAP中,解耦了包间循环依赖,程序能够正确运行。 732 733```json5 734// HAP's oh-package.json5 735"dependencies": { 736 "har1": "file:../har1", 737 "har2": "file:../har2", 738 "har3": "file:../har3" 739} 740// HAP's build-profiles.json5 741"buildOption": { 742 "arkOptions": { 743 "runtimeOnly": { 744 "packages" : [ // 仅用于变量动态加载的场景,静态加载或常量动态加载无需配置。 745 "har1", 746 "har2", 747 "har3" 748 ] 749 } 750 } 751} 752 753// HAR1's oh-package.json5 754"dependencies": {} 755// HAR1's build-profile.json5 756"buildOption": {} 757 758// HAR2's oh-package.json5 759"dependencies": {} 760// HAR2's build-profile.json5 761"buildOption": {} 762 763// HAR3's oh-package.json5 764"dependencies": {} 765// HAR3's build-profile.json5 766"buildOption": {} 767``` 768 769**对应的运行日志如下:** 770 771```text 772[DynamicImport] classHar1.add(), 0 + 1 = 1 773[DynamicImport] hap -> har1, 0 + 1 = 1 774[DynamicImport] classHar2.add(), 1 + 2 = 3 775[DynamicImport] har1 -> har2, 1 + 2 = 3 776[DynamicImport] classHar1.add(), 2 + 1 = 3 777[DynamicImport] har2 -> har1, 2 + 1 = 3 778[DynamicImport] classHar3.add(), 2 + 3 = 5 779[DynamicImport] har2 -> har3, 2 + 3 = 5 780[DynamicImport] classHar1.add(), 3 + 1 = 4 781[DynamicImport] har3 -> har1, 3 + 1 = 4 782``` 783