# Side Effects and Optimization of Module Loading ## Overview When 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. ## Scenarios and Optimization Methods for Side Effects ### Top-Level Code Execution in Modules **Scenario of Side Effects** When 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. ```typescript // module.ets console.log("Module loaded!"); // The code is executed immediately upon import, which may cause side effects. export const data = 1; // main.ets import { data } from './module' // When data is imported, the console.log file in module.ets is executed and output is generated. console.log(data); ``` The output is as follows: ```typescript Module loaded! 1 ``` **Side effects produced** Even 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**. **Optimized methods** Optimization method 1: Remove the top-level code and export only the required content to avoid unnecessary code execution. ```typescript // module.ets export const data = 1; // main.ets import { data } from './module' console.log(data); ``` The output is as follows: ```typescript 1 ``` Optimization 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. ```typescript // module.ets export function initialize() { console.log("Module loaded!"); } export const data = 1; // main.ets import { data } from './module' console.log(data); ``` The output is as follows: ```typescript 1 ``` ### Modifying Global Objects **Scenario of side effects** The top-level code or imported modules may directly manipulate global variables, thereby changing the global state and causing side effects. ```typescript // module.ets export let data1 = "data from module" globalThis.someGlobalVar = 100; // The global state is changed. // sideEffectModule.ets export let data2 = "data from side effect module" globalThis.someGlobalVar = 200; // The global state is changed. // moduleUseGlobalVar.ets import { data1 } from './module' // The expected value of the global variable someGlobalVar is 100. export function useGlobalVar() { console.log(data1); console.log(globalThis.someGlobalVar); // The value of someGlobalVar is changed to 200 because the sideEffectModule module is loaded to main.ets. } // main.ets (entry point) import { data1 } from "./module" // The value of the global variable someGlobalVar is changed to 100. import { data2 } from "./sideEffectModule" // The value of the global variable someGlobalVar is changed to 200. import { useGlobalVar } from './moduleUseGlobalVar' useGlobalVar(); function maybeNotCalledAtAll() { console.log(data1); console.log(data2); } ``` The output is as follows: ``` data from module 200 ``` **Side effects produced** Modules directly change the value of the **global variable globalThis.someGlobalVar**, affecting other modules or code that depends on this variable. **Optimized methods** Encapsulate code that may cause side effects within functions or methods, and execute the code only when needed, rather than upon module loading. ```typescript // module.ets export let data1 = "data from module" export function changeGlobalVar() { globalThis.someGlobalVar = 100; } // sideEffectModule.ets export let data2 = "data from side effect module" export function changeGlobalVar() { globalThis.someGlobalVar = 200; } // moduleUseGlobalVar.ets import { data1, changeGlobalVar } from './module' export function useGlobalVar() { console.log(data1); changeGlobalVar(); // Execute the code when needed, not upon module loading. console.log(globalThis.someGlobalVar); } // main.ets (entry point) import { data1 } from "./module" import { data2 } from "./sideEffectModule" import { useGlobalVar } from './moduleUseGlobalVar' useGlobalVar(); function maybeNotCalledAtAll() { console.log(data1); console.log(data2); } ``` The output is as follows: ``` data from module 100 ``` ### Modifying State Variables of Application-level ArkUI Components **Scenario of side effects** The 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. ```typescript // module.ets export let data = "data from module" AppStorage.setOrCreate("SomeAppStorageVar", 200); // The global UI state of the application is changed. // Index.ets import { data } from "./module" // SomeAppStorageVar in AppStorage is changed to 200. @Entry @Component struct Index { // The expected value is 100. However, the value has been changed to 200 due to module import. @StorageLink("SomeAppStorageVar") message: number = 100; build() { Row() { Column() { Text("test" + this.message) .fontSize(50) } .width("100%") } .height("100%") } } function maybeNotCalledAtAll() { console.log(data); } ``` The following content is displayed: ``` test200 ``` **Side effects produced** Modules directly change the value of **SomeAppStorageVar** in AppStorage, affecting other modules or code that depends on this variable. For more information on modifying ArkUI component state variables, see [State Management Overview](../ui/state-management/arkts-state-management-overview.md). **Optimized methods** Encapsulate code that may cause side effects within functions or methods, and execute the code only when needed, rather than upon module loading. ```typescript // module.ets export let data = "data from module" export function initialize() { AppStorage.setOrCreate("SomeAppStorageVar", 200); } // Index.ets import { data } from "./module" @Entry @Component struct Index { @StorageLink("SomeAppStorageVar") message: number = 100; build() { Row() { Column() { Text("test" + this.message) .fontSize(50) } .width("100%") } .height("100%") } } function maybeNotCalledAtAll() { console.log(data); } ``` The following content is displayed: ``` test100 ``` ### Modifying Built-in Global Variables or Prototype Chains (Modifying Object Prototypes or Built-in Methods Is Forbidden in ArkTS) **Scenario of side effects** To 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. ```typescript // modifyPrototype.ts export let data = "data from modifyPrototype" Array.prototype.includes = function (value) { return this.indexOf(value) !== -1; }; // main.ets import { data } from "./modifyPrototype" // The prototype chain of the array is modified. let arr = [1, 2, 3, 4]; console.log("arr.includes(1) = " + arr.includes(1)); // The Array.prototype.includes method in modifyPrototype.ts is called. function maybeNotCalledAtAll() { console.log(data); } ``` **Side effects produced** Modifying built-in global objects or prototype chains affects the execution of other code. **Optimized methods** When 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. ### Circular Dependencies **Scenario of side effects** ArkTS 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. ```typescript // a.ets import { b } from "./b" console.log('Module A: ', b); export const a = 'A'; // b.ets import { a } from "./a" console.log('Module B: ', a); export const b = 'B'; ``` The output is as follows: ``` Error message: a is not initialized Stacktrace: at func_main_0 (b.ets:2:27) ``` **Side effects produced** Due 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." **Optimized methods** Avoid 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. ### Lazy Import Changing the Module Execution Sequence and Leading to Undefined Global Variables **Scenario of side effects** The [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. ```typescript // module.ets export let data = "data from module" globalThis.someGlobalVar = 100; // moduleUseGlobalVar.ets import lazy { data } from "./module" console.log(globalThis.someGlobalVar); // The module is not executed due to lazy import. The value of someGlobalVar is undefined. console.log(data); // During the value of the variable, the module is executed and the value of someGlobalVar changes to 100. ``` The output is as follows: ``` undefined data from module ``` **Side effects produced** Using 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. **Optimized methods** Encapsulate code that may cause side effects within functions or methods, and execute the code only when needed, rather than upon module loading. ```typescript // module.ets export let data = "data from module" export function initialize() { globalThis.someGlobalVar = 100; // Delay the execution until the function is called. } // moduleUseGlobalVar.ets import lazy { data, initialize } from "./module" initialize(); // Execute the initialization function to initialize someGlobalVar. console.log(globalThis.someGlobalVar); // someGlobalVar will have the expected value. console.log(data); ``` The output is as follows: ``` 100 data from module ```