In certain scenarios, developers may find it necessary to partition the mini program into different sub-packages. During the construction phase, these are bundled into separate packages, which users can then load on an as-needed basis.
When building a mini program with sub-packages, the construction process will yield one or more separate packages. Each mini program using sub-packages will invariably contain a main package. This main package houses the default launch page/TabBar page, along with any common resources/JS scripts required by all sub-packages. The division of sub-packages is determined based on the developer's configuration.
Upon the initiation of the mini program, the main package is downloaded by default and its internal pages are launched. When a user navigates to a page within a sub-package, the client will download the corresponding sub-package. Once the download is complete, the page is then displayed.
The current size limitations for mini program sub-packages are as follows:
The total size of all sub-packages within the mini program must not exceed 24MB.
The size of an individual sub-package or main package must not exceed 2MB.
Sub-packaging a mini program can optimize the initial download time at launch and enhance decoupled collaboration when multiple teams are working together.
1. Using Subpackage
1.1 Configuration
Assume that the directory structure of a Mini Program supporting subpackages is as follows:
├── app.js
├── app.json
├── app.wxss
├── packageA
│ └── pages
│ ├── cat
│ └── dog
├── packageB
│ └── pages
│ ├── apple
│ └── banana
├── pages
│ ├── index
│ └── logs
└── utils
The developer declares the subpackage structure of a project in the subpackages field via app.json:
The field can also be written as subPackages.
{
"pages":[
"pages/index",
"pages/logs"
],
"subpackages": [
{
"root": "packageA",
"pages": [
"pages/cat",
"pages/dog"
]
}, {
"root": "packageB",
"name": "pack2",
"pages": [
"pages/apple",
"pages/banana"
]
}
]
}
In subpackages
, each subpackage are configured with the following fields:
|
root | String | Root directory of subpackage |
name | String | |
pages | StringArray | Subpackage page path, which is relative to the root directory of the subpackage |
independent | Boolean | |
1.2 Packaging Rules
After subpackages is declared, files are packaged based on the paths configured in subpackages, and files in the directories outside the paths in subpackages are packaged into the app (main package);
The app (main package) can also have its own pages (i.e. the outermost pages field);
The root directory of subpackage cannot be a subdirectory configured in another subpackage;
The tabBar page must be in the app (main package).
1.3 Referencing Rules
packageA cannot require JS files in packageB, but can require JS files in app and packageA;
packageA cannot import templates in packageB, but can import templates in app and packageA;
packageA cannot use resources in packageB, but can use resources in app and packageA.
2. Independent Subpackage
An independent subpackage is a special type of subpackage in Mini Programs. It can run independently of the main package and other subpackages. When a user enters a Mini Program from a page of an independent subpackage, the main package will not be downloaded, unless the user enters a page of an ordinary subpackage or a main package.
Developers can add some functionally independent pages to an independent subpackage as needed. When a Mini Program is launched from a page of an ordinary subpackage, the main package should be downloaded first. However, an independent subpackage can run independently of the main package. Therefore, subpackages greatly improve the startup speed of Mini Programs.
A Mini Program can have multiple independent subpackages.
2.1 Configuration
Assume that the directory structure of a Mini Program is as follows:
├── app.js
├── app.json
├── app.wxss
├── moduleA
│ └── pages
│ ├── rabbit
│ └── squirrel
├── moduleB
│ └── pages
│ ├── pear
│ └── pineapple
├── pages
│ ├── index
│ └── logs
└── utils
The developer declares a subpackage as an independent subpackage by defining the independent field in the subpackage configuration item in the subpackages
field of app.json
.
{
"pages": [
"pages/index",
"pages/logs"
],
"subpackages": [
{
"root": "moduleA",
"pages": [
"pages/rabbit",
"pages/squirrel"
]
}, {
"root": "moduleB",
"pages": [
"pages/pear",
"pages/pineapple"
],
"independent": true
}
]
}
2.2 Limits
The independent subpackage is a type of subpackage. All limits on ordinary subpackages are applicable to independent subpackages. Plug-ins and custom components in an independent subpackage are processed in the same way as with those in an ordinary subpackage:
Also note the following when using independent subpackages:
The content of an independent subpackage must be independent of the main package and other subpackages, including JS files, template, wxss, custom components, and plug-ins. app.wxss in the main package does not take effect for independent subpackages. Therefore, the styles in app.wxss should be avoided on pages of independent subpackages;
App can be defined only in the main package. Defining App in independent subpackages will cause unexpected behaviors;
Plug-ins are not supported in independent subpackages.
2.3 Notes
2.3.1 About getApp()
Unlike ordinary sub-packages, when an independent subpackage is running, App is not necessarily registered. Therefore, an App object can not necessarily be obtained via getApp():
When a user starts a Mini Program from a page of an independent subpackage, neither main package nor App exists. In this case, undefined is obtained when getApp() is called. The main package is downloaded and App can be registered only when the user opens a page of an ordinary subpackage or a main package.
When a user is redirected to a page of an independent subpackage from a page of an ordinary subpackage or the main package, the main package already exists, and the actual App can be obtained by calling getApp().
Because of this restriction, developers can not share global variables between independent subpackages and other parts of a Mini Program by using the App object.
To satisfy this requirement in a standalone sub-package, getApp supports the [allowDefault] parameter, which returns a default implementation when the App is undefined. When the main package is loaded and the App is registered, the properties defined in the default implementation will be overridden and merged into the real App.
Sample code:
In the independent subpackage
const app = getApp({allowDefault: true})
app.data = 456
app.global = {}
In the app.js file
App({
data: 123,
other: 'hello'
})
console.log(getApp())
2.3.2 About the lifecycle of App
If the Mini Program is launched from a page of an independent subpackage, onLaunch and first-time onShow of App
in the main package are called when the user is redirected from the page of the independent subpackage to a page of the main package or an ordinary subpackage for the first time.
3. Subpackage Preload
Developers can configure the framework to automatically preload required subpackages when a user enters a Mini Program page, to speed up the subsequent startup of subSubcontracting Asynchronisationpackaged pages. For Independent Subpackages, the main package can also be preloaded. Subpackages can be preloaded only via configuration.
Log prefixed with preloadSubpackages is available in vConsole to verify the preload status
3.1 Configuration
Subpackage preload is triggered when a user enters a specific page, and is controlled by adding preloadRule
configuration items via app.json
.
{
"pages": ["pages/index"],
"subpackages": [
{
"root": "important",
"pages": ["index"],
},
{
"root": "sub1",
"pages": ["index"],
},
{
"name": "hello",
"root": "path/to",
"pages": ["index"]
},
{
"root": "sub3",
"pages": ["index"]
},
{
"root": "indep",
"pages": ["index"],
"independent": true
}
],
"preloadRule": {
"pages/index": {
"network": "all",
"packages": ["important"]
},
"sub1/index": {
"packages": ["hello", "sub3"]
},
"sub3/index": {
"packages": ["path/to"]
},
"indep/index": {
"packages": ["__APP__"]
}
}
}
In preloadRule
, key
is the page path, and value
is the preload configuration for entering the page. Each configuration includes the following items:
|
packages | StringArray | Yes | No | Indicates root or name of a subpackage preloaded after a user enters a page. __APP__ indicates the main package. |
network | String | No | wifi | Indicates a specified network over which a subpackage is preloaded. Values:
all: Any network
wifi: Wi-Fi only |
3.2 Limits
Pages of the same subpackage share the same maximum preload size of 2 MB, which is verified when the pages are packaged via the DevTools.
For example, Page A and Page B are in the same subpackage. If a subpackage with a total size of 0.5 MB is preloaded on Page A, a maximum of 1.5 MB subpackages can be preloaded on Page B.
4. Subcontracting Asynchronisation
In mini programs, different sub-packages correspond to different download units; therefore, except for non-independent sub-packages that can rely on the main package, sub-packages cannot use custom components or require each other. the "sub-package asynchronisation" feature will allow this limitation to be solved to a certain extent by allowing, through some configurations and new interfaces, some cross-sub-packages to wait for the download and then use the content asynchronously.
4.1 Cross-subcontract custom component references
When a sub-package uses a custom component from another sub-package, the other sub-package's component is in an unavailable state because the other sub-package has not yet downloaded or injected it. By setting a placeholder component for the custom component of the other sub-package, we can render the placeholder component as a replacement first, and then replace it after the sub-package has finished downloading. Example: // subPackageA/pages/index.json
{
"usingComponents": {
"button": "../../commonPackage/components/button",
"list": "../../subPackageB/components/full-list",
"simple-list": "../components/simple-list",
"plugin-comp": "plugin://pluginInSubPackageB/comp"
},
"componentPlaceholder": {
"button": "view",
"list": "simple-list",
"plugin-comp": "view"
}
}
In this configuration, the button and list custom components are cross-package references, where the button is rendered using the built-in component view as a replacement, and the list is rendered using the current sub-package's custom component simple-list as a replacement; after these two sub-packages have been downloaded, the placeholder component is replaced with the corresponding cross-package component After both packages are downloaded, the placeholder component is replaced with the corresponding cross-package component.
4.2 Cross-Subpackage JS Code References
When code in a sub-package references code in another sub-package, we need to asynchronously get the result of the reference in order to prevent the download from blocking the code. For example:
require('../subPackageB/utils.js', utils => {
console.log(utils.whoami)
}, ({mod, errMsg}) => {
console.error(`path: ${mod}, ${errMsg}`)
})
require.async('../commonPackage/index.js').then(pkg => {
pkg.getPackageName()
}).catch(({mod, errMsg}) => {
console.error(`path: ${mod}, ${errMsg}`)
})
Was this page helpful?