目录

Asynchronous Package Splitting

In the atomic service, different subpackages correspond to different download units. If subpackages share a custom component or require a JS module, these resources must be placed in the main package. This ensures proper functionality across subpackages but increases the main package size, potentially impacting startup performance.

The asynchronous package splitting feature enables some content spanning subpackages to be downloaded and used asynchronously via configurations and new APIs. This reduces the main package size and improves startup performance.

This feature is implemented by configuring common package splitting. After a subpackage is configured as a common one, it can be referenced across packages. Below shows some use cases:

Enabling preloading may prolong the loading duration of common subpackages. You are advised not to configure preloading when using asynchronous loading of subpackages.

Common Subpackage

Common subpackages are a special type of subpackages within atomic services and cannot run independently. Once configured, all resource types in common subpackages can be asynchronously referenced by other subpackages.

It is recommended that common packages be shared as reusable capability units. You can configure common capabilities that are not strongly dependent on startup into common subpackages and use resources in common subpackages asynchronously, solving the problem of oversized main packages. Only JS modules and custom components support this feature. An atomic service can have multiple common subpackages. You are advised to configure only one common subpackage to avoid affecting the running performance due to multiple downloads.

Differences from ordinary subpackages

Example configuration

Below shows the directory structure of an atomic service that supports common subpackages:

├── app.css
├── app.js
├── app.json
├── packageA
│   └── pages
│       ├── pageOne
│       └── pageTwo
├── packageB
│   └── components
│       ├── component1
│       └── component2
├── pages
│   ├── index
│   └── logs
└── utils

In the subpackages configuration item of app.json, you can set common to true to declare a subpackage as a common subpackage.

The following configures packageB as a common subpackage:
{
  "pages": ["pages/index", "pages/logs"],
  "subpackages": [
    {
       "root": "packageA",
       "pages": ["pages/pageOne", "pages/pageTwo"] 
    }, 
    { 
       "root": "packageB",
       "pages": [], 
       "common": true 
     } 
    ]
}

Use restrictions

Common subpackages comply with all restrictions that apply to ordinary subpackages. The processing method of custom components in common subpackages is the same as that in common subpackages. In addition, note the following when using common subpackages:

Referencing Custom Components of Common Subpackages

When a subpackage references custom components from other subpackages, those components will be unavailable until their respective subpackages are downloaded and injected. You can set a placeholder component for the custom component of another subpackage and render the placeholder component as a substitute. After the main content on the page is rendered, the subpackage is downloaded to replace the placeholder component.

Below shows how the main package or a subpackage references the custom component of a common subpackage:

{
  "usingComponents": {
    "custom-button": "/packageB/components/component1/component1" 
  },
  "componentPlaceholder": {
    "custom-button": "view" 
  }
}

In this configuration, the custom-button component is referenced across subpackages. During rendering, it uses the built-in view component as a placeholder. Once the main page elements are rendered, packageB is downloaded and replaces the placeholder component.

You can call has.onLazyLoadError to listen to the loading event.

Referencing the JS of a Common Subpackage

When the code of a subpackage references the code of another subpackage, the reference result needs to be obtained asynchronously to avoid blocking code execution during the download process.

[h2]require

Import the modules. Return the APIs exposed by the module through module.exports or exports. To import a module from another package, you can configure the callback function to asynchronously obtain the specified module. If the asynchronous obtaining fails, the error callback function is triggered. Alternatively, the require.async method is called, and the value is returned using a promise.

Syntax

require(path, callback, error);

Parameters

Name

Type

Mandatory

Description

Earliest Supported Version

path

string

Yes

Path of the module file to be imported relative to the current file. The absolute path is not supported by default.

1.0.0

callback

function

No

Callback function for an asynchronous loading success. The parameter of this callback function is the successfully loaded module.

This parameter is mandatory when the asynchronous require capability is used. If this parameter is not specified, synchronous reference is used.

1.0.8

error

function

No

Callback function for an asynchronous loading failure. The parameters of this callback function are the error information and module name.

1.0.8

Return values

Return values of errors

Name

Type

Description

Earliest Supported Version

mod

string

Input path.

1.0.8

errMsg

string

Error details.

1.0.8

Example

require("common.js", (mod) => {
  console.log('Loading succeeded', JSON.stringify(mod));
},(error) = > {
  console.warn('Loading failed', JSON.stringify(error));
});

[h2]require.async Chain Call

The following describes the chain call of require.async.

Syntax

require.async(path);

Parameters

Parameter

Type

Mandatory

Description

Earliest Supported Version

path

string

Yes

Path of the module file to be imported relative to the current file. The absolute path is not supported by default.

1.0.8

Return values

Promise<Object>: execution result of require

Return values of errors

Parameter

Type

Description

Earliest Supported Version

mod

string

Input path.

1.0.8

errMsg

string

Error details.

1.0.8

Example

require
  .async("common.js")
  .then((mod) => {
    console.log('Loading succeeded', JSON.stringify(mod));
  })
  .catch((error) => {
    console.warn('Loading failed', JSON.stringify(error));
  });

Enumerated values of task status in errMsg are described as follows.

Name

Value

Description

CREATE_TASK_FAILED

-4

Creating a download task fails.

HIGHER_VERSION_INSTALLED

-3

This version or a later version is already installed locally.

TASK_ALREADY_EXISTS

-2

The download task already exists.

TASK_UNFOUND

-1

The download task does not exist.

DOWNLOAD_PAUSING

2

The download task is paused.

DOWNLOAD_FAILED

5

The download fails.

DOWNLOAD_WAIT_WIFI

6

Downloads are allowed only over Wi-Fi. Currently, mobile data is being used, so users need to wait for a Wi-Fi connection.

INSTALL_FAILED

23

The installation fails.

Enumerated values of error code in errMsg are described as follows.

Name

Value

Description

MODULE_ALREADY_EXISTS

-8

The module already exists.

MODULE_UNAVAILABLE

-7

The module does not exist or does not match the device.

INVALID_REQUEST

-6

The request is invalid because it contains inaccurate information.

NETWORK_ERROR

-5

The request fails due to a network error.

INVOKER_VERIFICATION_FAILED

-4

The caller information is abnormal.

FOREGROUND_REQUIRED

-3

On-demand loading is allowed for only foreground requests.

ACTIVE_SESSION_LIMIT_EXCEEDED

-2

The request is denied due to existing download requests.

FAILURE

-1

Failure.

DOWNLOAD_WAIT_WIFI

1

Downloads are allowed only over Wi-Fi. Currently, mobile data is being used, so users need to wait for a Wi-Fi connection.