辛宝Otto

辛宝Otto 的玄酒清谈

北漂前端程序员儿 / 探索新事物 / Web Worker 主播之一/内向话痨
xiaoyuzhou
email

[Summary Post] A comprehensive guide to understanding the uvm dependency of uni-app management.

【Summary】In-depth understanding of managing uvm dependencies for uni-app
Summary: In-depth understanding of managing uvm dependencies for uni-app

Objective of Experience Sharing#

While browsing the forum, I found that some issues are related to @dcloudio/uvm. The problems are similar and the solutions are also similar. Here, I will create a summary post in order to solve common issues at once.

The goal of this article is to read and understand the uvm source code, familiarize oneself with the design ideas and functions of uvm, and summarize common issues. Ultimately, the aim is to be able to independently solve problems by familiarizing oneself with the uvm source code.

The full name of uvm is uni-app version manager, which can be compared to nvm - node version manager.

Background Introduction#

As an official solution, uvm is mentioned in the official website documentation at https://uniapp.dcloud.net.cn/quickstart-cli.html#cliversion:

You can use @dcloudio/uvm to manage the version of the compiler. This tool only automatically adds or updates the main dependencies of the uni-app compiler. It does not automatically handle newly added compilation commands (scripts), which need to be manually configured according to the new project.

Internal jump [[uni-app Learning#uni-app Dependency Upgrade uvm]]

As a rapidly iterating technology framework, uni-app and its surrounding ecosystem develop and code every day. Apart from the regular front-end solutions, it also needs to support hbuilderX. Outdated dependencies are meaningless, and the latest versions have obvious significance for the current project.

It becomes necessary to automatically upgrade front-end dependencies through a solution, preferably with a one-click upgrade that does not require attention to the current version and the specific latest version.

Therefore, @dcloudio/uvm was created. By executing npx @dcloudio/uvm in the project directory, the automatic update of the relevant dependencies in package.json can be achieved.

Due to some historical reasons, the source code of uvm is not publicly displayed, but the npm product does not go through compression and compilation. Reading the source code and developing the source code have the same effect. Here is a brief introduction to the source code and the overall code structure.

Project Source Code#

Visit the npm repository @dcloudio/uvm and click on the Code section. You can see the final product, which is no different from the original code. https://www.npmjs.com/package/@dcloudio/uvm?activeTab=code

Pasted image 20231123175924

First, look at package.json to identify the relevant dependencies and registered commands.

package.json#

"dependencies": {
"cross-spawn": "^7.0.3",
"inquirer": "^8.2.0",
"minimist": "^1.2.5",
"node-fetch": "^2"
},
"devDependencies": {
"xmldom": "^0.6.0"
}

The dependencies are relatively simple, cross-platform command execution, interactive cli, and request sending. The main focus is on the bin registration.

The command registration can be seen in the bin registration bin/index.js, and the source code is as follows, which is relatively simple and neat.

Pasted image 20231122171157

By reading the source code, it can be seen that when the registered command is started, the current argv parameter will be read. For example, if it is not passed, the default value will be latest, and the project address represented by the current command line will also be read.

Process#

In line 30 of the screenshot, start() will be executed, and it will go through info(), find(), get(), and finally merge().

info()#

In the info() method, the package.json in the current directory will be read to analyze whether the devDependencies dependencies include the following dependencies:

const plugins = {
  vue2: '@dcloudio/vue-cli-plugin-uni',
  vue3: '@dcloudio/vite-plugin-uni'
}

Finally, the corresponding dependencies and whether it is vue3 will be returned, which means that the dependencies to be upgraded for vue2 and vue3 are different. Here, I will leave a gap and bring up the principle of the @dcloudio/vite-plugin-uni dependency later. If you are interested, please let me know in the comments.

find()#

Located at /@dcloudio/uvm/lib/version.js#find.

In the find method, the current plugin, specific version characteristics or "latest", and whether it is vue3 will be read for passing judgment.

The actual processing uses the last segment of the current version to fetch data remotely, which is nothing more than three possible values: latest alpha release. The remote version value is obtained, such as 3.96.2023110403. Let's take a look at a screenshot with a breakpoint:

Pasted image 20231122173836

Breakpoint into related historical judgments.

Afterwards, continue to request 'https://registry.npmmirror.com/@dcloudio/vite-plugin-uni', still various characteristic value judgments.

Here, remote data will be requested to obtain hbuilderX version information and registry information. This requires a network connection.

Pasted image 20231123181106

The default registry here is cnpm, which depends on the stability of cnpm and has a certain risk of network fluctuations. However, it can at least ensure that users in China can access it.

get()#

The get method will continue to be judged. Taking vue3 as an example, it will ultimately retrieve the information from https://gitee.com/dcloud/uni-preset-vue/blob/vite/package.json, which means it will be processed based on the remote repository.

In order to accommodate changes in historical versions, the logic here is basically unreadable, and a lot of version compatibility has been done. When browsing the uvm issues in the ask community, you can see some tearful histories of compatibility.

If it is vue3, it will enter getVue3(), which will read the remote repository information from gitee by default. If, for some reason, the github and gitee repositories are not correctly synchronized, it will result in mismatched information.

merge()#

This step is the final execution phase. The deps will be obtained and prepared for specific execution. spawnAsync will be used to update the dependencies and developer dependencies separately.

This part uses cross-spawn to bypass the problem of executing commands on different systems.

Technical Summary#

Through the simple core logic reading above, it can be seen that the essence of uvm execution is to execute commands across systems, obtain the current version information and the package.json of a typical repository on remote gitee, and make complex judgments to determine the upgrades that need to be made.

Common QA#

Running the program gives an error message "Not find version xxx, please provide the specific version number."

This issue currently does not exist. There may be some problems with some outdated versions. If you encounter this issue, please provide your current version number.

Running the program gives an error message "code ETARGET."

This may be a cache and network issue. Try deleting the cache and the current node_modules and reinstall the dependencies. It may also be a network synchronization issue. It takes some time for the release to be synchronized in China. You can take a break and try again later.

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.