1# Module Loading Side Effects and Optimization 2## Overview 3When using [ArkTS modularization](module-principle.md), the loading and execution of modules may cause side effects. Side effects refer to extra behavior or state changes in addition to exporting functions or objects during module import. These behaviors may affect other parts of the program and cause unexpected top-level code execution, global state changes, prototype chain modification, and undefined imported content. 4 5## Scenarios and Optimization Methods of Side Effects Caused by ArkTS Modularization 6### Executing the Top-level Code 7**Scenario** 8 9When a module is imported, the top-level code in the entire module file is executed immediately, not just the exported part. This means that even if you only want to use some of the exported content in the module, any code executed in the top-level scope will be run, resulting in side effects. 10```typescript 11// module.ets 12console.log ("Module loaded!"); // The code is executed immediately after being imported, which may cause side effects. 13export const data = 1; 14 15// main.ets 16import {data} from './module' // When data is imported, the console.log file in module.ets is executed and output is generated. 17console.log(data); 18``` 19The outputs are listed as follows: 20```typescript 21Module loaded! 221 23``` 24**Side effects** 25 26Even if only data is required, console.log ("Module loaded!") still runs. As a result, developers may expect that only the value of data is output, but "Module loaded!" is output, which affects the output content. 27 28**Optimized mode** 29 30Optimization method 1: Remove the top-level code and export only the required content to avoid unnecessary code execution. 31```typescript 32// module.ets 33export const data = 1; 34 35// main.ets 36import { data } from './module' 37console.log(data); 38``` 39The outputs are listed as follows: 40```typescript 411 42``` 43Optimization method 2: Place the code that may cause side effects in the function or method and execute the code only when necessary, instead of executing the code immediately when the module is loaded. 44```typescript 45// module.ets 46export function initialize() { 47 console.log("Module loaded!"); 48} 49export const data = 1; 50 51// main.ets 52import { data } from './module' 53console.log(data); 54``` 55The outputs are listed as follows: 56```typescript 571 58``` 59### Modifying a global object 60**Scenario** 61 62The top-level code or imported module may directly operate global variables to change the global state and cause side effects. 63```typescript 64// module.ets 65export let data1 = "data from module" 66globalThis.someGlobalVar = 100; // The global state is changed. 67 68// sideEffectModule.ets 69export let data2 = "data from side effect module" 70globalThis.someGlobalVar = 200; // The global state is changed. 71 72// moduleUseGlobalVar.ets 73import {data1} from './module' // The value of the global variable someGlobalVar may be expected to be 100. 74export function useGlobalVar() { 75 console.log(data1); 76 console.log (globalThis.someGlobalVar); // The value of someGlobalVar is changed to 200 because the sideEffectModule module is loaded to main.ets. 77} 78 79// main.ets (execution entry) 80import {data1} from ."/module" // Change the value of the global variable someGlobalVar to 100. 81import {data2} from ."/sideEffectModule" // Change the value of the global variable someGlobalVar to 200. 82import { useGlobalVar } from './moduleUseGlobalVar' 83 84useGlobalVar(); 85function maybeNotCalledAtAll() { 86 console.log(data1); 87 console.log(data2); 88} 89``` 90The outputs are listed as follows: 91``` 92data from module 93200 94``` 95**Side effects** 96 97When a module is loaded, the value of the global variable globalThis.someGlobalVar is directly changed, affecting other modules or code that use the variable. 98 99**Optimized mode** 100 101Code that may cause side effects is placed inside a function or method and executed only when necessary, instead of being executed immediately when the module is loaded. 102```typescript 103// module.ets 104export let data1 = "data from module" 105export function changeGlobalVar() { 106 globalThis.someGlobalVar = 100; 107} 108 109// sideEffectModule.ets 110export let data2 = "data from side effect module" 111export function changeGlobalVar() { 112 globalThis.someGlobalVar = 200; 113} 114 115// moduleUseGlobalVar.ets 116import { data1, changeGlobalVar } from './module' 117export function useGlobalVar() { 118 console.log(data1); 119 changeGlobalVar (); // Execute the code when necessary instead of when the module is loaded. 120 console.log(globalThis.someGlobalVar); 121} 122 123// main.ets (execution entry) 124import { data1 } from "./module" 125import { data2 } from "./sideEffectModule" 126import { useGlobalVar } from './moduleUseGlobalVar' 127 128useGlobalVar(); 129function maybeNotCalledAtAll() { 130 console.log(data1); 131 console.log(data2); 132} 133``` 134The outputs are listed as follows: 135``` 136data from module 137100 138``` 139### Modifying State Variables of Application-level ArkUI Components 140**Scenario** 141 142The top-level code or imported module may directly modify the state variable information of the application-level ArkUI component, thereby changing the global state and causing side effects. 143```typescript 144// module.ets 145export let data = "data from module" 146AppStorage.setOrCreate ("SomeAppStorageVar," 200); // Modify the global UI state of the application. 147 148// Index.ets 149import {data} from ."/module" // Change SomeAppStorageVar in AppStorage to 200. 150 151@Entry 152@Component 153struct Index { 154 // The expected value is 100. However, the value has been changed to 200 due to module import. However, the developer may not know that the value has been changed. 155 @StorageLink("SomeAppStorageVar") message: number = 100; 156 build() { 157 Row() { 158 Column() { 159 Text("test" + this.message) 160 .fontSize(50) 161 } 162 .width("100%") 163 } 164 .height("100%") 165 } 166} 167function maybeNotCalledAtAll() { 168 console.log(data); 169} 170``` 171Display 172``` 173test200 174``` 175**Side effects** 176 177When a module is loaded, the value of SomeAppStorageVar in AppStorage is changed, affecting other modules or code that use the variable. 178 179The state variables of the ArkUI component can be modified through some application-level APIs. For details, see [ArkUI State Management](../quick-start/arkts-state-management-overview.md). 180 181**Optimized mode** 182 183Code that may cause side effects is placed inside a function or method and executed only when necessary, instead of being executed immediately when the module is loaded. 184```typescript 185// module.ets 186export let data = "data from module" 187export function initialize() { 188 AppStorage.setOrCreate("SomeAppStorageVar", 200); 189} 190 191// Index.ets 192import { data } from "./module" 193 194@Entry 195@Component 196struct Index { 197 @StorageLink("SomeAppStorageVar") message: number = 100; 198 build() { 199 Row() { 200 Column() { 201 Text("test" + this.message) 202 .fontSize(50) 203 } 204 .width("100%") 205 } 206 .height("100%") 207 } 208} 209function maybeNotCalledAtAll() { 210 console.log(data); 211} 212``` 213Display 214``` 215test100 216``` 217### Modifying Built-in Global Variables or Prototype Chains (Modifying Object Prototypes or Built-in Methods in ArkTS Is Forbidden) 218**Scenario** 219 220Some third-party libraries or frameworks may modify built-in global objects or prototype chains to support modern JavaScript features in older browsers or runtime environments. This may affect the running of other code. 221```typescript 222// modifyPrototype.ts 223export let data = "data from modifyPrototype" 224Array.prototype.includes = function (value) { 225 return this.indexOf(value) !== -1; 226}; 227 228// main.ets 229import {data} from ."/modifyPrototype" // The prototype chain of the array is modified. 230let arr = [1, 2, 3, 4]; 231console.log (arr.includes (1)); // The Array.prototype.includes method in modifyPrototype.ts is called. 232function maybeNotCalledAtAll() { 233 console.log(data); 234} 235``` 236**Side effects** 237 238Modifying a built-in global object or prototype chain affects the running of other code. 239 240**Optimized mode** 241 242When importing a third-party library that may modify the built-in global object or prototype chain, ensure that the behavior of the third-party library meets the expectation. 243### Circular Dependency 244 245**Scenario** 246 247ArkTS modularization supports circular dependency. That is, module A depends on module B, and module B depends on module A. In this case, some imported modules may not be completely loaded. As a result, some code behaves abnormally during execution, causing unexpected side effects. 248```typescript 249// a.ets 250import { b } from "./b" 251console.log('Module A: ', b); 252export const a = 'A'; 253 254// b.ets 255import { a } from "./a" 256console.log('Module B: ', a); 257export const b = 'B'; 258``` 259The outputs are listed as follows: 260``` 261Error message: a is not initialized 262Stacktrace: 263 at func_main_0 (b.ets:2:27) 264``` 265**Side effects** 266 267Modules are dependent on each other. The execution sequence of modules may cause the exported content to be empty or undefined, affecting the logic flow of the code. 268 269**Optimized mode** 270 271Avoid circular dependency between modules and ensure that the module loading sequence is clear and controllable to avoid unexpected side effects. [@security/no-cycle](https://developer.huawei.com/consumer/en/doc/harmonyos-guides-V5/ide_no-cycle-V5) can be used to assist in circular dependency check. 272### Lazy Import Changes the Module Execution Sequence and Leads to Undefined Global Variables 273**Scenario** 274 275[Lazy Import](arkts-lazy-import.md) prevents the modules to be loaded from being loaded in the cold start phase. The modules are loaded as required only when they are required during the running of the application, in this way, the time required for cold startup of the application is shortened. However, this also changes the execution sequence of the modules. 276```typescript 277// module.ets 278export let data = "data from module" 279globalThis.someGlobalVar = 100; 280 281// moduleUseGlobalVar.ets 282import lazy { data } from "./module" 283console.log (globalThis.someGlobalVar); // The module is not executed due to the lazy feature. The value of someGlobalVar is undefined. 284console.log (data); // Variables of the module are used. When the module is executed, the value of someGlobalVar changes to 100. 285``` 286The outputs are listed as follows: 287``` 288undefined 289data from module 290``` 291**Side effects** 292 293The lazy import feature is used. As a result, the corresponding module is executed when the module variable is used, and the modification of some global variables in the module is delayed. As a result, the running result may not meet the expectation. 294 295**Optimized mode** 296 297Code that may cause side effects is placed inside a function or method and executed only when necessary, instead of being executed immediately when the module is loaded. 298```typescript 299// module.ets 300export let data = "data from module" 301export function initialize() { 302 globalThis.someGlobalVar = 100; // Delay the execution until the function is called. 303} 304 305// moduleUseGlobalVar.ets 306import lazy { data, initialize } from "./module" 307initialize (); // Execute the initialization function to initialize someGlobalVar. 308console.log (globalThis.someGlobalVar); // The value of someGlobalVar must be the expected value. 309console.log(data); 310``` 311The outputs are listed as follows: 312``` 313100 314data from module 315``` 316