1# Side Effects and Optimization of Module Loading 2## Overview 3When using [ArkTS modularization](module-principle.md), the process of loading and executing modules may introduce side effects. These side effects refer to additional behavior or state changes that occur when importing a module, beyond simply exporting functions or objects. Such behavior might affect other parts of the program, leading to unintended consequences such as unexpected top-level code execution, global state changes, prototype chain modifications, and undefined imported content. 4 5## Scenarios and Optimization Methods for Side Effects 6### Top-Level Code Execution in Modules 7**Scenario of Side Effects** 8 9When a module is imported, all top-level code within the module file is executed immediately, not just the exported parts. This means that even if only specific exports are needed, any code in the top-level scope will run, potentially causing side effects. 10```typescript 11// module.ets 12console.log("Module loaded!"); // The code is executed immediately upon import, 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 output is as follows: 20```typescript 21Module loaded! 221 23``` 24**Side effects produced** 25 26Even though only **data** is required, **console.log("Module loaded!")** still runs, causing the unexpected output of "Module loaded!" in addition to the value of **data**. 27 28**Optimized methods** 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 output is as follows: 40```typescript 411 42``` 43Optimization method 2: Encapsulate code that may cause side effects within functions or methods, and execute the code only when needed, rather than upon module loading. 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 output is as follows: 56```typescript 571 58``` 59### Modifying Global Objects 60**Scenario of side effects** 61 62The top-level code or imported modules may directly manipulate global variables, thereby changing the global state and causing 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 expected value of the global variable someGlobalVar is 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 (entry point) 80import { data1 } from "./module" // The value of the global variable someGlobalVar is changed to 100. 81import { data2 } from "./sideEffectModule" // The value of the global variable someGlobalVar is changed to 200. 82import { useGlobalVar } from './moduleUseGlobalVar' 83 84useGlobalVar(); 85function maybeNotCalledAtAll() { 86 console.log(data1); 87 console.log(data2); 88} 89``` 90The output is as follows: 91``` 92data from module 93200 94``` 95**Side effects produced** 96 97Modules directly change the value of the **global variable globalThis.someGlobalVar**, affecting other modules or code that depends on this variable. 98 99**Optimized methods** 100 101Encapsulate code that may cause side effects within functions or methods, and execute the code only when needed, rather than upon module loading. 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 needed, not upon module loading. 120 console.log(globalThis.someGlobalVar); 121} 122 123// main.ets (entry point) 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 output is as follows: 135``` 136data from module 137100 138``` 139### Modifying State Variables of Application-level ArkUI Components 140**Scenario of side effects** 141 142The top-level code or imported modules may directly modify the state variables of application-level ArkUI components, thereby changing the global state and causing side effects. 143```typescript 144// module.ets 145export let data = "data from module" 146AppStorage.setOrCreate("SomeAppStorageVar", 200); // The global UI state of the application is changed. 147 148// Index.ets 149import { data } from "./module" // SomeAppStorageVar in AppStorage is changed 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. 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``` 171The following content is displayed: 172``` 173test200 174``` 175**Side effects produced** 176 177Modules directly change the value of **SomeAppStorageVar** in AppStorage, affecting other modules or code that depends on this variable. 178 179For more information on modifying ArkUI component state variables, see [State Management Overview](../ui/state-management/arkts-state-management-overview.md). 180 181**Optimized methods** 182 183Encapsulate code that may cause side effects within functions or methods, and execute the code only when needed, rather than upon module loading. 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``` 213The following content is displayed: 214``` 215test100 216``` 217### Modifying Built-in Global Variables or Prototype Chains (Modifying Object Prototypes or Built-in Methods Is Forbidden in ArkTS) 218**Scenario of side effects** 219 220To support modern JavaScript features in old browsers or runtime environments, third-party libraries or frameworks may modify built-in global objects or prototype chains. This can affect the execution 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) = " + arr.includes(1)); // The Array.prototype.includes method in modifyPrototype.ts is called. 232function maybeNotCalledAtAll() { 233 console.log(data); 234} 235``` 236**Side effects produced** 237 238Modifying built-in global objects or prototype chains affects the execution of other code. 239 240**Optimized methods** 241 242When importing third-party libraries that may modify built-in global objects or prototype chains, ensure that the behavior of the third-party library is as expected. 243### Circular Dependencies 244 245**Scenario of side effects** 246 247ArkTS modularization supports circular dependencies, where module A depends on module B, and module B depends on module A. In such cases, some imported modules may not be fully loaded, leading to abnormal behavior and unintended side effects during execution. 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 output is as follows: 260``` 261Error message: a is not initialized 262Stacktrace: 263 at func_main_0 (b.ets:2:27) 264``` 265**Side effects produced** 266 267Due to mutual dependencies between modules, the execution order of modules may result in undefined exports, affecting the logic flow of the code. The specific error message is "Variable name is not initialized." 268 269**Optimized methods** 270 271Avoid circular dependencies between modules whenever possible, and ensure that the loading order of modules is clear and controllable to prevent unexpected side effects. You can use [@security/no-cycle](https://developer.huawei.com/consumer/en/doc/harmonyos-guides/ide_no-cycle) when detecting circular dependencies. 272### Lazy Import Changing the Module Execution Sequence and Leading to Undefined Global Variables 273**Scenario of side effects** 274 275The [Lazy Import](arkts-lazy-import.md) feature allows modules to be loaded on-demand during the application runtime, rather than during the cold start phase, thereby reducing the cold start time. However, this also changes the execution sequence of 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 lazy import. The value of someGlobalVar is undefined. 284console.log(data); // During the value of the variable, the module is executed and the value of someGlobalVar changes to 100. 285``` 286The output is as follows: 287``` 288undefined 289data from module 290``` 291**Side effects produced** 292 293Using the lazy import feature delays the execution of modules until they are needed. Modifications to global variables within these modules are also delayed, potentially leading to unexpected results. 294 295**Optimized methods** 296 297Encapsulate code that may cause side effects within functions or methods, and execute the code only when needed, rather than upon module loading. 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); // someGlobalVar will have the expected value. 309console.log(data); 310``` 311The output is as follows: 312``` 313100 314data from module 315``` 316