5

If you have dreams and dry goods, search [Moving the World] pay attention to this Shawanzhi who is still washing dishes in the early morning.

This article has been included in GitHub https://github.com/qq449245884/xiaozhi . There are complete test sites, materials and my series of articles for interviews with first-tier manufacturers.

subcontract

What is subcontracting

Subcontracting refers to dividing a complete applet project into different subpackages according to the requirements , which are packaged into different subpackages during construction, and users can load them on demand when using them.

The benefits of subcontracting

The benefits of subcontracting small programs are mainly as follows:

  • The download time of the first launch of the applet can be optimized
  • Better decoupling and collaboration when multiple teams develop together

uniapp subpackage configuration

According to the official website, it is assumed that the uni-app directory structure that supports subcontracting is as follows:

┌─pages               
│  ├─index
│  │  └─index.vue    
│  └─login
│     └─login.vue    
├─pagesA   
│  ├─static
│  └─list
│     └─list.vue 
├─pagesB    
│  ├─static
│  └─detail
│     └─detail.vue  
├─static             
├─main.js       
├─App.vue          
├─manifest.json  
└─pages.json            

Then you need to fill in pages.json:

{
    "pages": [{
        "path": "pages/index/index",
        "style": { ...}
    }, {
        "path": "pages/login/login",
        "style": { ...}
    }],
    "subPackages": [{
        "root": "pagesA",
        "name": "分包的别名"
        "pages": [{
            "path": "list/list",
            "style": { ...}
        }]
    }, {
        "root": "pagesB",
        "pages": [{
            "path": "detail/detail",
            "style": { ...}
        }]
    }],
}

Hands-on: https://github.com/qq449245884/uniapp-subpackage-demo/tree/feature/01.%E5%B0%8F%E7%A8%8B%E5%BA%8F%E5%88%86 %E5%8C%85%E9%85%8D%E7%BD%AE

After running, you can view the subcontracting information in the developer details:

Is the directory structure configured in this way really good?

According to the example of the official website, if we want to divide into two packages, then create two directories pagesA and pagesB under the same level of pages. Is this really good? Suppose we have an activity business template, and the corresponding activity details address is /pages/activity/detail . pages.json is configured as follows:

    "pages": [
        {
            "path": "pages/index/index",
            "style": {
                "navigationBarTitleText": "首页"
            }
        },
        {
            "path": "pages/activity/detail",
            "style": {
                "navigationBarTitleText": "活动详情"
            }
        }
    ],

With the development of the business, the functions of this module are also increasing. Someday, when we want to subcontract the package, if we follow the previous subcontracting method, if we create a subpackage directory under the same level as pages , assuming we call pagesA here, and then put the file of the corresponding active module are moved to this directory, and the corresponding pages.json configuration is as follows:

"subPackages": [{
  "root": "pagesA",
  "pages": [{
    "path": "activity/detail"
   }]
}]

At this time, the corresponding activity details address is /pagesA/activity/detail , which will cause a problem. At this time, the activity details path has changed, so if the subcontracting can work normally, the previous path must be changed. If there are other small programs that jump It is also necessary to change the details page. Obviously, this subcontracting structure is very unreliable. For one subcontracting, multiple files and even multiple small programs must be changed.

So how to solve this problem? Obviously, this problem can be solved as long as the path does not change, but the subcontracting can be done correctly.

When thinking about subcontracting, it is nothing more than specifying a subcontracting name in subPackages , and the subcontracting page corresponds to the file under the subcontracting name. Therefore, we can specify the module under the original pages as a sub-package, so that the configuration can solve the problem of inconsistent paths after sub-package. The rewritten structure is as follows:

  "subPackages": [
    {
      "root": "pages/activity",
      "pages": [
        {
          "path": "detail"
        }
      ]
    }
  ],

Example address: https://github.com/qq449245884/uniapp-subpackage-demo/tree/feature/02.%E9%85%8D%E7%BD%AE%E7%9B%AE%E5%BD%95 %E7%BB%93%E6%9E%84%E7%9A%84%E5%90%88%E7%90%86%E6%80%A7

Subpackage preload

Subpackage preload configuration. After configuring preloadRule , when entering a certain page of the applet, the framework will automatically pre-download the sub-packages that may be required, which improves the startup speed when entering subsequent sub-package pages.

Suppose, we have two subcontracts pagesA and pagesB , when we enter the details page, we want to pre-add pagesA , the corresponding configuration is as follows:

{
    "pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
        {
            "path": "pages/index/index",
            "style": {
                "navigationBarTitleText": "首页"
            }
        },
        {
            "path": "pages/detail/index",
            "style": {
                "navigationBarTitleText": "详情"
            }
        }
    ],
    "subPackages": [{
        "root": "pagesA",
        "pages": [{
            "path": "detail/index"
        }]
    }, {
        "root": "pagesB",
        "pages": [{
            "path": "detail/index"
        }]
    }],
    "preloadRule": {
        "pages/detail/index": {
            "network": "wifi",
            "packages": ["pagesA", "pagesB"]
        }
    }
}

preloadRule , key is the page path, value is the pre-download configuration for entering this page, and packages is the pre-download sub-package after entering the page. network is pre-downloaded under the specified network. The optional values are: all (unlimited network), wifi (pre-download only under wifi).

Case address:

https://github.com/qq449245884/uniapp-subpackage-demo/tree/feature/03.%E5%88%86%E5%8C%85%E9%A2%84%E5%8A%A0%E8%BD%BD

Loading rules for subpackages

One thing to note about subcontracting is: tabBar page needs to be placed in the main package, assuming we have two tabBars, the configuration is as follows:

{
    "pages": [
        {
      "path": "pages/channel/index",
      "style": {
        "disableScroll": true
      }
    },
    {
      "path": "pages/member/index",
      "style": {
        "disableScroll": true
        }
      }
    ],
    "tabBar": {
    "color": "#BBBBBD",
    "selectedColor": "#1C1C1C",
    "borderStyle": "white",
    "backgroundColor": "#ffffff",
    "list": [
      {
        "pagePath": "pages/channel/index",
        "iconPath": "static/tabbar_icon_channel.png",
        "selectedIconPath": "static/tabbar_icon_channel_active.png",
        "text": "会员专属"
      },
      {
        "pagePath": "pages/member/index",
        "iconPath": "static/tabbar_icon_member.png",
        "selectedIconPath": "static/tabbar_icon_member_active.png",
        "text": "掌通会员"
      }
    ]
  }
}

If we configure the tabBar page to subPackages , there will be an error:

Example address: https://github.com/qq449245884/uniapp-subpackage-demo/tree/feature/04.%E5%88%86%E5%8C%85%E7%9A%84%E9%99%90 %E5%88%B6

Subcontracting optimization

Add "optimization":{"subPackages":true} under the configuration of the corresponding platform to enable subcontracting optimization.

Subcontract optimization specific logic

  • Static files: The subpackage supports copying of static resources such as static, that is, the static resources placed in the subpackage directory will not be packaged into the main package, nor can they be used in the main package
  • js file: When a js is only referenced by one sub-package, the js will be packaged into the sub-package, otherwise it will still be sent to the main package (that is, referenced by the main package, or referenced by more than one sub-package)
  • Custom component: If a custom component is only referenced by one sub-package and is not placed in the sub-package, a prompt message will be output when compiling

First, let's test the first rule, and create the corresponding configuration on the home page:

{
    "pages": [
        {
            "path": "pages/index/index",
        }
    ],
    "subPackages": [{
        "root": "pagesA",
        "pages": [{
            "path": "detail/index"
        }]
    }],
}

Here, we have a sub-package pagesA corresponding to a details page. The details page uses an image, which is placed under the static file under the current package. The content is as follows:

  <view class="content">
    <image class="logo" src="../static/test.png" />
  </view>

Then, we start packaging, then click details in the developer tool, click local code -> Dependency analysis, you can view the packaging details, as shown in the following figure:

As you can see, we click under the main package of static , which does not have the test.png picture we used in the sub-package. Instead, it is packaged under its own sub-package. means that the static resources placed in the subpackage directory will not be packaged into the main package, and is established.

Next, let's verify, what if the subcontracted test.png image is used in the main package? Rewrite the contents of the index file of our main package:

<view class="content">
  <image class="logo" src="../../pagesA/static/test.png" />
</view>

After running, the console gives the error:

Therefore, the subpackage supports static resource copying such as static, that is, the static resources placed in the subpackage directory will not be packaged into the main package, nor can be used in the main package.

Example address: https://github.com/qq449245884/uniapp-subpackage-demo/tree/feature/05.%E5%88%86%E5%8C%85%E4%BC%98%E5%8C%96__ %E9%9D%99%E6%80%81%E6%96%87%E4%BB%B6

Then, let's verify the second rule: js file: when a js is only referenced by one sub-package, the js will be packaged into the sub-package, otherwise it will still be sent to the main package (that is, referenced by the main package , or referenced by more than 1 subpackage) .

First, we create a common.ts in src/utils in the main package, the content is as follows:

export const add = (a: number, b:number) => {
  return a + b
}

Then, we import in subpackage pagesA using:

<script lang="ts">
import Vue from 'vue'
import { add } from '@/utils/common'
export default Vue.extend({
  created() {
    console.log(add(1, 2))
  }
})
</script>

Similarly, package, and then click details in developer tools, click local code -> Dependency analysis:

As can be seen from the above figure, we did not find the add method in src/utils/common.ts in the in the main package of vender.js , but found it in the subpackage pagesA .

What if a js is referenced by multiple subpackages?

Let's create a subpackage pagesB and import common.ts in the subpackage pagesB in the same way:

<script lang="ts">
import Vue from 'vue'
import { add } from '@/utils/common'
export default Vue.extend({
  created() {
    console.log(add(1, 2))
  }
})
</script>

Similarly, package, and then click details in developer tools, click local code -> Dependency analysis:

As can be seen from the figure, we can find the add method we used in the vendor.js in the main package, and the corresponding vendor.js is not found in the subpackage, so When a js is only referenced by multiple subpackages, the js will be Packaged into the main package .

Example address: https://github.com/qq449245884/uniapp-subpackage-demo/tree/feature/05.%E5%88%86%E5%8C%85%E4%BC%98%E5%8C%96__JS %E6%96%87%E4%BB%B6

Finally, let's verify the third rule: Custom component: If a custom component is only referenced by one sub-package and is not placed in the sub-package, a prompt message will be output during compilation

First, we create a custom component SayHello in src/components in the main package, the content is as follows:

<template>
    <view class="content">
    Hello World
    </view>
</template>

Then, create a subcontract in the same way (the steps are the same as the above example), and reference our component SayHello in the subcontract:

<template>
  <view class="content">
    <SayHello />
  </view>
</template>

<script lang="ts">
import Vue from 'vue'
import SayHello from '@/components/SayHello.vue'

export default Vue.extend({
  components: {
    SayHello
  }
})
</script>

Then, compile and you can see the prompt information in the console:

What if the custom component is referenced by multiple subpackages? The prompt should disappear. For the sake of rigor, we will create a subpackage pagesB to reference the component in the same posture, then compile it, and then view the console:

As you can see, the prompt message has disappeared.

So far, we have verified the specific logic of subcontracting optimization mentioned on the official website of UniApp, Nice.

Example address: https://github.com/qq449245884/uniapp-subpackage-demo/tree/feature/0.5.%E5%88%86%E5%8C%85%E4%BC%98%E5%8C%96__ %E7%BB%84%E4%BB%B6


The bugs that may exist after the code is deployed cannot be known in real time. In order to solve these bugs afterwards, a lot of time is spent on log debugging. By the way, I recommend a useful bug monitoring tool Fundebug .

communicate with

If you have dreams and dry goods, search [Moving the World] attention to this Shawanzhi who is still washing dishes in the early morning.

This article has been included in GitHub https://github.com/qq449245884/xiaozhi , and there are complete test sites, materials and my series of articles for interviews with first-tier manufacturers.


王大冶
68k 声望104.9k 粉丝