1# Dynamic Import
2
3## Overview
4
5When an application loads a page, importing statically all modules significantly slows the loading, and it is often the case that these modules are not all needed. For example, when the home page uses the **Navigation** component, loading the home page loads all subpages by default. As a result, the loading takes a long time, especially when there are a large number of subpages. In effect, the subpages are irrelevant to home page rendering. If they are loaded at a later time, the home page load time can be greatly reduced.
6This is where dynamic import comes into play. In this document, we will improve the performance of an application by dynamically importing modules.
7
8## Example
9
10| Home page                                      | Subpage                                       |
11|------------------------------------------|--------------------------------------------|
12| ![Home](./figures/dynamic-import-home.png) | ![Subpage](./figures/dynamic-import-pages.png) |
13
14The following example compares static import and dynamic import of the **Navigation** component to describe how to trigger on-demand loading during redirection.
15
16### Static Import
17
18When using the **Navigation** component, you may import subpage components to the home page and add methods to buttons to implement redirection. The following code shows a static import example.
19
201. Subpage modules are imported. The **Navigation** component uses these modules to redirect the user to subpages. As the subpages are not immediately needed when the user accesses the home page, loading these subpages is redundant and slows down home page loading.
21    ```ts
22    import { pageOne, pageOneData } from './pageOne';
23    import { pageTwo, pagesTwoData } from './pageTwo';
24    ...
25    import router from '@ohos.router';
26    ```
272. The home page uses the **Navigation** component to redirect the user to different subpages when they click a specific button.
28    ```ts
29    @Provide('pathInfos') pageInfos: NavPathStack = new NavPathStack();
30
31    @Builder
32    PageMap(name: string) {
33      if (name === 'pageOne') {
34        pageOne(new pagesOneData(name, this.pageInfos));
35      } else if (name === 'pageTwo') {
36        pageTwo(new pagesTwoData(name, this.pageInfos));
37      }
38      ...
39    }
40
41    build() {
42      Navigation(this.pageInfos) {
43        Button('Back', { stateEffect: true, type: ButtonType.Capsule })
44          .onClick(() => {
45             router.back();
46          })
47        Column() {
48          Button('pageOne', { stateEffect: true, type: ButtonType.Capsule })
49            .onClick(() => {
50               this.pageInfos.pushPath({ name: 'pageOne' }); // Push the navigation destination page specified by name to the navigation stack.
51            })
52          Button('pageTwo', { stateEffect: true, type: ButtonType.Capsule })
53            .onClick(() => {
54               this.pageInfos.pushPath({ name: 'pageTwo' });
55            })
56          ...
57        }
58      }.title('Home').navDestination(this.PageMap)
59    }
60    ```
61
62### Dynamic Import
63
64If the **Navigation** component loads all modules statically at a time, the loading of the home page can be slow, especially when there are a large number of complex child components. To reduce page load time, you can use dynamic import, so that child components are dynamically imported as needed during page redirection. To implement dynamic import, perform the following steps:
65
661. Encapsulate the **pageOne** component to be dynamically imported through the **PageOneLoader** function. This way, when the **PageOneLoader** function is called, the **pageOne** page is rendered.
67    ```ts
68    import { pageOne } from './pageOne';
69
70    @Builder
71    export function PageOneLoader() {
72      pageOne();
73    }
74    ```
752. Because the **navDestination** component in **PageMap** of the **Navigation** component cannot directly load components (**import** is a function and cannot be referenced in components), you need to declare the **@BuilderParam PageOneLoader** function and initialize it when the corresponding button is clicked. This way, **this.PageOneLoader()** can be called in the **navDestination** component to load the **pageOne** component.
76To dynamically load **pageOne** on the home page **DynamicHome**, perform the following steps:
77   a. Define the **@BuilderParam PageOneLoader: () => void** function in the home page **DynamicHome** to receive the result of asynchronously importing **pageOneLoader** by **await import**.
78    ```ts
79    @BuilderParam PageOneLoader: () => void;
80    ```
81   b. Defines an asynchronous function so that when the button is clicked, **PageOneLoader** is initialized.
82    ```ts
83    async loadPageOne(key: string){
84      if (key === "pageOne") {
85        let PageObj: ESObject = await import("../pages/PageOneLoader");
86        this.PageOneLoader = PageObj.PageOneLoader;
87      }
88    }
89    ```
90   c. Click the button to trigger the click function and call **loadPageOne**. In this case, **@BuilderParam PageOneLoader** is initialized and **Navigation** is used to load the component.
91    ```ts
92    private onEntryClick(): void {
93      try {
94        this.loadPageOne('pageOne');
95        this.pageInfos.clear();
96        this.pageInfos.pushPathByName('pageOne', '');
97        logger.info('DynamicImport Success');
98      } catch (error) {
99        logger.info('DynamicImport Fail');
100      }
101    }
102    ```
103   d. Trigger the initialized **PageOneLoader** function in **PageMap** to dynamically load the **PageOne** component.
104    ```ts
105    @Builder
106    PageMap(name: string) {
107      if (name === 'pageOne') {
108        this.PageOneLoader();
109      }
110    }
111    ```
112The complete code of the **DynamicHome** home page is as follows:
113```ts
114import router from '@ohos.router';
115import { logger } from '../../ets/utils/Logger';
116
117@Entry
118@Component
119struct DynamicHome {
120  @Provide('pathInfos') pageInfos: NavPathStack = new NavPathStack();
121  @State active: boolean = false;
122  @BuilderParam PageOneLoader: () => void;
123
124  @Builder
125  PageMap(name: string) {
126    if (name === 'pageOne') {
127      this.PageOneLoader();
128    }
129  }
130
131  build() {
132    Navigation(this.pageInfos) {
133      Column() {
134        Button('Back', { stateEffect: true, type: ButtonType.Capsule })
135          .width('80%')
136          .height(40)
137          .margin(20)
138          .onClick(() => {
139            router.back();
140          })
141        Button('PageOne-Dynamic', { stateEffect: true, type: ButtonType.Capsule })
142          .width('80%')
143          .height(40)
144          .margin(20)
145          .onClick(() => {
146            this.onEntryClick();
147          })
148      }
149    }.title('HOME').navDestination(this.PageMap)
150  }
151
152  async loadPageOne(key: String) {
153    if (key === "pageOne") {
154      let PageObj: ESObject = await import("../pages/PageOneLoader");
155      this.PageOneLoader = PageObj.PageOneLoader;
156    }
157  }
158
159  // Trigger dynamic loading.
160  private onEntryClick(): void {
161    try {
162      this.loadPageOne('pageOne');
163      this.pageInfos.clear();
164      this.pageInfos.pushPathByName('pageOne', '');
165      logger.info('DynamicImport Success');
166    } catch (error) {
167      logger.info('DynamicImport Fail');
168    }
169  }
170}
171```
172In sum, when there are a large number of subpages in the **Navigation** component, using static import to load all subpages at once can significantly slow the loading of the home page. To reduce the page load time and overall resource consumption and prevent the main thread from being blocked, use dynamic import so subpages are loaded on demand.
173