# uni_modules

# 什么是 uni_modules

主流的语言/平台,都有自己包管理方案,js有npm、yarn或pnpm、Android有仓储、iOS有cocoapods、鸿蒙有ohpm、dart有pub。。。

uni-app是大一统开发,包括客户端和uniCloud服务器。在客户端部分包括web、Android、iOS、各家小程序。

在uni-app中可以调用npm库,可以调用Android仓储里的aar,可以调用iOS的cocoapods里framework,以及鸿蒙的ohpm。

甚至uts语言本身也可以编译为js、kotlin、swift。

那么uni-app的开发者,需要一个大一统的包管理方案,那就是uni_modules

uni_modules是uni-app的包管理方案(HBuilderX 3.1.0+支持),它是一个海纳百川型的设计,

  • 不管是js/uts库、组件、页面、uniCloud云函数、公共模块等的封装,甚至是整个项目,都可以封装成一个uni_modules。(类似Android的aar)
  • 不管是npm、Android仓储、iOS的cocoapods、鸿蒙的ohpm,都可以纳入uni_modules中。

由于uni-app有自己的项目目录结构规范(uni-app详见、uni-app x详见), 所以你可以简单理解,把一个项目的这些工程目录都挪到了一个uni_modules下,打包成了一个模块,这里面只要符合uni-app规范的文件都可以放。

详细的uni_modules目录结构见下

# uni_modules的优势

  1. uni_modules支持在插件市场计费销售。由DCloud提供商业插件的代码加密和版权保护。
  2. HBuilderX提供了对uni_modules的便捷管理,可以对一个uni_modules点右键(如果是项目型uni_modules,是对根目录的package.json点右键),直接上传uni_modules、更新uni_modules、安装依赖。版本更新时还会给出新旧代码的详细对比。

与之前插件市场的普通插件相比,uni_modules有何优势?

  1. 支持在HBuilderX里直接发布、更新、删除。而无需在web界面操作。
  2. 支持依赖(在package.json中配置)
  3. 插件文件位置统一。以往下载一个插件,不知道给工程下多少个目录写入了多少个文件,这种困惑不再存在。删除插件时也可以一处统一删除

node_modules了,为何还发明一个uni_modules的轮子?

  1. node_modules 不满足全平台包管理需求,无法容纳Android仓储、iOS的cocoapods、鸿蒙的ohpm。
  2. node_modules 不满足云端一体的需求。uniCloud的云函数、公共模块、schema和前端部分,无法在node_modules模式下有效融合。很多组件是云端一体组件,即有客户端又有服务器,需要按uni-app的目录规范放置。
  3. uni_modules 有付费和商业的插件,DCloud插件市场提供了版权保护。而node_modules不支持付费和版权保护。
  4. node_modules 层层嵌套node_modules,造成数量惊人的文件数目。uni_modules支持依赖但不支持module嵌套,鼓励开发者优化包体积。当然这算差异,并非uni_modules的优势
  5. uni_modules 在js支持的平台,也容纳了node_modules,没有排斥。

除了发布插件,uni_modules同时也是一种大型工程的模块分割方案。比如一个旅游应用,可以把机票、酒店、火车票、自由行等模块分拆成不同的uni_modules,由不同的部门来开发。

# 目录结构

# 项目插件的uni_modules

If the uni_modules plugin is a project type plugin, you only need to put a package.json that conforms to the uni_modules specification in the root directory of the project.

Right-click on the package.json to update the project plugin or publish it to the plugin marketplace.

For example uni-admin, uni-starter , can be updated in this way.

# 非项目插件的uni_modules

If it is a plug-in of non-project type, such as component, js sdk, page template and cloud function, it needs to be placed in the uni_modules directory of the project.

At this time, the directory structure under the uni_modules directory is the same as the project structure of uni-app, as follows:

	
uni_modules                                项目根目录下
└── [plugin_id] // 插件 ID
    ├── uniCloud                           插件内的uniCloud内容会被虚拟合并到项目根目录的uniCloud中(注意:插件内的uniCloud目录,没有-aliyun,-tcb后缀)
    ├── components                         符合vue组件规范的uni-app组件目录,支持easycom规范
    ├── utssdk                             存放uts插件
    ├── hybrid                             存放本地网页的目录,详见
    ├── pages                              业务页面文件存放的目录 
    ├── static                             存放应用引用静态资源(如图片、视频等)的目录,注意:静态资源只能存放于此
    ├── wxcomponents                       存放小程序组件的目录,详见
    ├── license.md                         插件使用协议说明
    ├── package.json                       插件配置,必选(除此之外均`可选`)                          
    ├── readme.md                          插件文档
    ├── changelog.md                       插件更新日志
    ├── menu.json                          如果是uniCloud admin插件,可以通过menu.json注册动态菜单,详见 menu.json 配置
	

That is, the uni_modules directory is equivalent to duplicating the project structure of uni-app.

Tips

  • 插件目录不支持pages.json、App.vue/uvue、main.js/uts、manifest.json、uni.scss文件,如果需要插件使用者修改这些文件内容,请在插件文档(readme.md)中详细说明。
  • The plugin directory supports pages_init.json, which can easily register pages to the project's pages.json, see below
  • When referencing resources or jumping pages inside plug-ins, please use relative paths as much as possible.
  • The components directory in the plug-in also supports easycom specification. Plugin users can directly use the components meeting the easycom specification in the plug-in in the project. When there is an easycom component conflict in the project or plug-in, a prompt will be given during compilation and you can resolve the conflict by modifying the component directory and component file name.

In HBuilderX, if uni_modules contains the contents of the uniCloud directory, it will be displayed in uniCloud in the root directory of the main project by way of reference. A shortcut arrow will appear in the lower left corner of the icon in front of the file.

As shown in the figure below, there is a uni_modules named uni-config-center in the project, which contains a public module named uni-config-center. Therefore, under the common module directory common in the project root directory, there will also be an additional uni-config-center.

Opening a file indicated by a reference icon in HBuilderX will open the original address.

# uts插件

在uni_modules的utssdk目录,可以放置uts插件。

uts插件是非常重要的一种跨端插件。它支持API插件和组件插件。

在utssdk目录下,可以放置一个interface.uts的声明,然后可以新建app-android、app-ios、web、mp-weixin、app-harmony等目录,每个目录下可以存放不同客户端平台的代码。

以获取电量的API为例,uni.getBatteryInfo(),在根目录的interface.uts中定义了api的对外暴露接口、定义统一的错误码,然后在各个客户端平台的目录中,实现电量获取这个API。

uni.getBatteryInfo的插件和源码详见:https://ext.dcloud.net.cn/plugin?id=9295

在app-android、app-ios目录,可以放置Android原生的aar、iOS原生的framework,也支持配置Android仓储和iOS的cocoapods。

uts插件开发的详细指南见:https://doc.dcloud.net.cn/uni-app-x/plugin/uts-plugin.html

# 使用 uni_modules 插件

# 下载uni_modules插件

  1. Find the uni_modules plugin in Plugin Market
  2. 在插件详情页,右侧会标明该插件是否支持uni_modules,点击使用 HBuilderX 导入插件
  3. 选择要导入的uni-app项目

Tips

  • uni_modules supports the component easycom, and users can directly use the components meeting the easycom specification in the plug-in
  • Other resources, such as images and js, can be directly introduced and used according to the directory structure in the project. For example:
import {test} from '@/uni_modules/xx-yy/js_sdk/test.js'
  • If you want to use pages from uni_modules, see below

# 安装uni_modules插件依赖

  1. When importing a plug-in, HBuilderX will automatically install all third-party dependencies of the current plug-in.
  2. 您还可以在插件目录右键手动执行安装插件三方依赖

# 更新uni_modules插件

  1. 可以通过插件目录右键从插件市场更新,来检查更新当前所使用的插件
  2. 对比插件,确认更新内容

# 卸载uni_modules插件

The uni_modules plug-in directory is standalone. If you no longer need the plug-in, you can delete it directly.

Tips

  • Importing the uni_modules specification plug-in requires HBuilderX 3.1.0+

# 配置

# package.json

package.json must exist in every uni_modules plug-in and contains the basic information of plug-ins. The following is a detailed configuration description of package.json

{
    //Note that you cannot directly copy this code into the editor, and package.json currently does not support comments. The comments added in this paragraph are only used to explain the code.
    "id": "作者ID-插件英文名称", // 必填,插件ID,格式为:'作者ID-插件英文名称',例如:'xx-yy',其中作者ID和插件名称只能包含英文、数字,作者ID不能使用'DCloud'、'uni'等关键字
    "displayName": "插件显示名称", // 必填,用于展示在插件市场的显示名称
    "version": "1.0.0", // 必填,插件版本
    "description": "插件描述", // 必填,插件描述
    "keywords": [], // 必填,插件标签关键词,最多5个
    "repository": "github:user/repo", // 仓库地址
    "engines": { // HBuilderX/cli 最低兼容版本
        "HBuilderX": "^3.1.0"
    },
    "dcloudext": { // DCloud插件市场配置
      "category": ["前端组件", "通用组件"], // 可选(HBuilderX低于3.6.0时必填), 插件市场分类
      "type": "component-vue", // 必填(HBuilderX 3.6.0 以上支持),插件市场分类标识,分类标识可以参考下边列出的表格
      "sale": { // 销售 (目前仅限uniCloud类插件)
          "regular": { // 普通授权版价格,单位为元,如果为免费插件,设置普通授权版价格为 0 即可。
              "price": "0.00"
          },
          "sourcecode": { // 源码授权版价格,单位为元
              "price": "0.00"
          }
      },
      "contact": { // 插件作者 QQ,方便管理员审核时与作者快速沟通。
          "qq": ""
      },
      "declaration": { // 隐私、权限及商业化声明
          "ads": "", //  必填,本插件是否包含广告,如包含需详细说明广告表达方式、展示频率,请如实填写,如不包含,可填“无”
          "data": "", // 必填,本插件采集的数据、发送的服务器地址、以及数据用途说明,请如实填写,如不采集任何数据,可填写“插件不采集任何数据”,如果使用的三方SDK需要采集数据,可填写“插件使用的 XX SDK会采集数据,详情可参考:https://other-sdk.com/"
          "permissions": "" // 必填,本插件需要申请的系统权限列表,请如实填写,如不需要任何权限,可填“无”
      },
      "npmurl":"" // npm 地址
    },
    "uni_modules": { // uni_modules配置
        "scripts": {
            "init": "node scripts/init.js" // 新增于 HBuilderX 3.6.7,初次安装此插件时执行,如果一次安装多个插件及依赖会在所有插件安装完毕执行
        },
        "dependencies": [], // 依赖的 uni_modules 插件ID列表
        "encrypt": [ // 配置云函数,公共模块,clientDB Action加密
            "uniCloud/cloudfunctions/uni-admin/controller/permission.js" // 注意这里是真实的文件路径,uni_modules下的uniCloud不带-aliyun、-tcb后缀,但是项目根目录下的uniCloud是带有后缀的
        ],
        "platforms": { // 平台兼容性:y 表示 Yes,支持;n 表示 No,不支持;u 表示 Unknown,不确定;默认为 u
            "cloud": { // 云端平台兼容性
                "tcb": "y",
                "aliyun": "y"
            },
            "client": { // 前端平台兼容性
                "App": {
                    "app-vue": "y",
                    "app-nvue": "n"
                },
                "H5-mobile": {
                    "Safari": { // 当需要指定最小版本才支持时,可以配置minVersion
                        "minVersion": "14.0.2"
                    },
                    "Android Browser": "y",
                    "微信浏览器(Android)": "u",
                    "QQ浏览器(Android)": "u"
                },
                "H5-pc": {
                    "Chrome": "y",
                    "IE": "u",
                    "Edge": "u",
                    "Firefox": "u",
                    "Safari": "u"
                },
                "小程序": {
                    "微信": "y",
                    "阿里": "y",
                    "百度": "y",
                    "抖音": "y",
                    "QQ": "y"
                },
                "快应用": {
                    "华为": "u",
                    "联盟": "u"
                }
            }
        }
    }
}

Tips

  • The above configuration is based on the npm package.json specification extension, so the standard package.json attributes are also supported, for example, through files to control the content of the plugin package to be uploaded
  • Plug-in market classification identification (corresponding: package.json->dcloudext->type)
Primary classification Secondary classification type
Front-end components Common components component-vue
front-end components MiniApp components component-mp
JS SDK Universal SDK sdk-js
uts plugin uts plugin uts
uni-app front-end template front-end page template uniapp-template-page
uni-app front-end template uni-app front-end project template uniapp-template-project
uniCloud cloud function template unicloud-template-function
uniCloud Cloud One Page Template unicloud-template-page
uniCloud Cloud-integrated project template unicloud-template-project
uniCloud Admin plugin unicloud-admin
uniCloud DB Schema and validation functions unicloud-database

# uni_modules.config.json

uni_modules.config.json In the root directory of the project, you can configure the trigger script updated by the plug-in (usually used to perform customized automation tasks) and the service space supported by the plug-in uniCloud. The following is a detailed configuration description of uni_modules.config.json

{
	"scripts": {
		"postupdate": "node scripts/upgrade.js", // 更新插件后执行该脚本,可从process.env.UNI_MODULES_ID获取当前被更新的插件ID,如果存在多个,以,隔开
		"preupload": "node scripts/preupload.js", // 上传插件之前执行该脚本,可从process.env.UNI_MODULES_ID获取当前被更新的插件ID,如果存在多个,以,隔开
		"postupload": "node scripts/postupload.js" // 上传插件之后(无论上传成功还是失败)执行该脚本,可从process.env.UNI_MODULES_ID获取当前被更新的插件ID,如果存在多个,以,隔开
	},
	"uni_modules": {
		"uni-id": { // 插件ID
			"uniCloud": ["aliyun", "tcb"] // 当项目同时存在aliyun,tcb时可手动指定该插件所属的服务空间
		}
	}
}

Tips

  • 当项目内仅关联了一个服务空间,此时uni_modules插件内的uniCloud相关资源会自动归属至该服务空间,无需在uni_modules.config.json中配置uniCloud所属服务空间
  • When there are two service spaces in the project (Alibaba Cloud and Tencent Cloud exist at the same time)
    • If the platform is not configured in uni_modules.config.json, then when uploading the uniCloud resources of this plug-in, you will be prompted to select which service space to upload to
    • If the platform has been configured in uni_modules.config.json, the configuration will prevail when uploading and it will be automatically attributed to the specified service space

# npmignore

When uni_modules plug-in is released to plug-in market, it is usually necessary to ignore some directories or files, such as unpackage, .hbuilderx, node_modules and so on, then the file can be ignored by npmignore file.

File name: .npmignore. Note that there is a dot at the beginning. Contents of a typical npmignore file are as follows:

.hbuilderx
unpackage
node_modules
package-lock.json

Notice

  • The .npmignore in the project root directory is effective for publishing projects and plug-in templates. uni_modules/Plug-in Id/.npmignore Effective for published plug-ins

# pages_init页面注册

Added in HBuilderX 3.5.0+

In the past, when plugin authors provided page class plugins, they needed to manually inform users in the documentation which pages to register in pages.json. like:

{
  "pages":[{
    "path":"uni_modules/xx-yy/pages/demo/demo" // 按插件所在目录引入对应的页面
  }]
}

pages_init.json solves this annoyance.

When the pages_init.json file exists in the root directory of the uni_modules plugin, when the plugin imports the project, a pages.json modification interface for merging page routes will pop up. Plug-in users click the Confirm button to complete the registration of the plug-in page to the project pages.json.

Example plugin: Problem Feedback Page Admin Template

The sample code is as follows:

{
    "pages": [{
            "path": "uni_modules/uni-feedback-admin/pages/uni-feedback-admin/add",
            "style": {
                "navigationBarTitleText": "新增"
            }
        },
        {
            "path": "uni_modules/uni-feedback-admin/pages/uni-feedback-admin/edit",
            "style": {
                "navigationBarTitleText": "编辑"
            }
        },
        {
            "path": "uni_modules/uni-feedback-admin/pages/uni-feedback-admin/list",
            "style": {
                "navigationBarTitleText": "列表"
            }
        }
    ]
}

Complete pages parameters details view

Notice

  • The pages_init.json file will not eventually be imported into the project.
  • pages_init.json does not support annotations (including: conditional compilation).
  • If the HBuilderX version is lower than 3.5, or the plugin author does not provide pages_init.json, you still need to manually edit the pages.json registration page.

# 开发 uni_modules 插件

# 新建uni_modules目录

In the root directory of the uni-app project, create the uni_modules directory, and you can click Create uni_modules directory on the right-click menu of the project.

Tips:

  • In case of vue-cli project, the uni_modules directory is located under src, which is src/uni_modules

# 新建uni_modules插件

  1. Right-click the uni_modules directory in HBuilderX Create uni_modules plug-in

  1. Fill in the correct plug-in ID and select the plug-in classification

Plugin ID naming specification:

  • In the format of: 'Author ID - English name of plug-in'. For example, xx-yy, where the author ID and English name of plug-in can only contain English and numbers
  • Author ID is defined by the plug-in author, and cannot use 'DCloud', 'uni' and other keywords. Its length is required at least 2 characters
  • The plug-in name should visually express the function of the plug-in. For example: tag, button, etc.

Tips

  • The uni_modules plug-in can be configured with three-party dependencies in the uni_modules->dependencies node of package.json (the dependent plug-in must also be the uni_modules plug-in). If it is an npm plug-in that relies on three parties, you can use the standard dependencies node configuration.

通过 uni_modules->dependencies 配置三方uni_modules插件依赖

{
  "id": "uni-badge",
  "displayName": "uni-badge 数字角标",
  "version": "1.2.2",
  "description": "数字角标(徽章)组件,在元素周围展示消息提醒,一般用于列表、九宫格、按钮等地方。",
  "uni_modules": {
    "dependencies": ["uni-scss"]
  }
}

# 发布到插件市场

当您的插件开发完毕,可以直接发布到插件市场供其他人免费或付费使用,插件市场提供了变现、评价等机制,优秀的插件作者可以做到月入数万元。

Release process:

  1. 在HBuilderX中插件目录右键点击发布到插件市场
  2. 填写插件信息 Tips
  • If you need to release it as a project template, please create package.json in the root directory of the project, and then right-click the menu to release to the plug-in market.
  • 发布插件时,可以选择上传当前项目作为示例工程,完整的示例工程,可以方便用户快速上手。

# 修改插件基本信息

When your plug-in is released to the plug-in market, if you need to adjust some basic information in the plug-in market, such as Chinese name, description, keywords, and readme.md, you can right-click the Modify the plug-in basic information directly in the plug-in directory.

  1. 在HBuilderX中插件目录右键点击修改插件基本信息
  2. 修改插件基本信息

# 发布新版本

When your plug-in has added new functions or fixed bugs, and a new version needs to be released, the operation is the same as that of the first release, and you can right-click the Release to plug-in market directly in the plug-in directory.

Tips

  • The update log filled in the releasing window will automatically be synchronized with changelog.md in the root directory

# 已有插件迁移为 uni_modules 插件指南

  1. Migrate the plug-in content to the directory named after the plug-in ID under the root directory of your uni-app sample project uni_modules. For example, if your existing plug-in ID is xx-yy, the directory structure is: uni_modules/xx-yy
  2. Run your own sample project to verify that if all functions are normal after the plug-in migrates to the directory
  • When migrating directories, you will usually encounter problems with resource reference paths. So all path references should be modified as relative paths as much as possible.
  • If the plug-in has a cloud function or database of uniCloud, please note that uniCloud in the plug-in directory cannot have suffixes of the vendor when migrating. You can specify the cloud service provider supported by the plug-in when releasing the plug-in.
  • Files of pages.json, App.vue, main.js, manifest.json and uni.scss are not supported in the plug-in directory. If plug-in users need to modify the contents of these files, please elaborate in detail in the plug-in document (readme.md).
  1. When all the functions of the migrated plug-ins are normal, you can release a new version of the plug-in that supports uni_modules to the plug-in market (the plug-in market will keep your last version of the non-uni_modules plug-in at the same time)
  • Create package.json in the root directory of plug-in, you can simply fill in one plug-in ID temporarily, and fill in other information through the release window (it will be automatically synchronized back to package.json)
{
  "id":"您的插件ID"
}
  • Plug-in document, migrate to readme.md in the root directory of plug-in
  • Right-click package.json and click Release to plug-in market, select the classification, and fill in the plug-in information (consistent with the existing information in the plug-in market as much as possible)
  • 发布成功后,您可以在插件市场的插件详情页右侧,查看到您的插件已同时提供了uni_modules版本和非uni_modules版本(仅保留最后一个非uni_modules版本)