uni-app x 插件生态开发指南:uni_modules 包管理、uts 插件与插件市场全解析
【免费下载链接】uni-appA cross-platform framework using Vue.js项目地址: https://gitcode.com/gh_mirrors/un/uni-app
uni-app x 通过一套开放、兼容的插件系统,将前端组件、uts SDK、页面模板、项目模板与原生能力封装统一纳入官方插件市场与uni_modules包管理规范。本文以仓库 docs/plugin/README.md 为骨架,结合 uni_modules 规范、uts 插件开发、插件发布与变现 等配套文档及仓库源码,系统讲解 uni-app x 插件生态的构成、跨平台原生能力的封装方式,以及插件从开发、发布到商业化的完整链路,帮助读者快速上手插件开发与生态接入。
一、uni-app x 插件生态总览
uni-app x 积极拥抱社区,创建了开放、兼容的插件系统。整个生态围绕两条主线展开:
- 官方插件市场:uni-app x 官方插件生态集中地,支持前端组件、uts SDK、页面模板、项目模板、uts 插件等多种类型。
- uni_modules 包管理方案:海纳百川式的大一统包管理设计,可同时容纳 npm、Android 仓储、iOS 的 CocoaPods、鸿蒙的 ohpm 等各类库,方便封装跨平台插件。
生态建设有一条明确的设计原则:把常用的部分 uni 化,不常用的各平台特色不限制使用,都可以在条件编译里调用。这意味着 uni-app x 在统一多端开发体验的同时,并不封锁平台独有的能力,而是提供"统一与个性化"之间的平衡点。
各平台生态接入方式
根据编译目标平台的不同,插件生态的接入方式如下:
| 编译目标 | 可调用的生态能力 |
|---|---|
| Web | 浏览器全部 API,可混合使用 JS,可使用 web 生态的各种库(含 npm) |
| 小程序 | 小程序全部 API,可混合使用 JS,小程序自定义组件生态(如 wxml 组件)、小程序 npm 库 |
| Android | Android OS 全部 API,可混合使用 Kotlin、Java,可使用所有适配 Android 的 SDK(含 so 库)、gradle 仓储 |
| iOS | iOS 全部 API,可混合使用 Swift(Objective-C 需封装为库后使用,不能直接使用 OC 源码),可使用所有适配 iOS 的 SDK(含 CocoaPods) |
| Harmony | 鸿蒙全部 API,可混合使用 ArkTS,可使用所有适配鸿蒙的 SDK(含 ohpm) |
在非 Web 平台使用 Web 生态
当编译到不支持 web 的平台时,如需使用 web 生态内容,官方提供了三种途径:
- 在 uni-app x 的
web-view组件内使用 web 库,uni-app x 提供了 web-view 组件内 js 和 uts 的通信机制; - 集成 uni 小程序 SDK,或集成 v8/quickjs 等库来调用 js 生态内容;
- 从蒸汽模式起,app 平台兼容 js/ts 生态,npm 上很多流行库可以直接使用。
二、插件市场:插件分类与付费机制
插件市场按"7 大类、20 多个子类"对插件进行分类,具体体系如下:
| 插件市场 | 一级分类 | 二级分类 |
|---|---|---|
| DCloud 市场 | 前端组件 | 通用组件、nvue 组件、小程序组件、DataCom 组件 |
| JS SDK | 通用 SDK、微信小程序 SDK、Native.js | |
| uts 插件 | API 插件、组件插件 | |
| uni-app 前端模板 | 前端页面模板、nvue 页面模板、uni-app 前端项目模板 | |
| App 原生插件 | App 原生插件 | |
| web 项目 | web 项目模板 | |
| uniCloud | 云函数模板、云端一体页面模板、云端一体项目模板、Admin 插件、DB Schema 及验证函数 | |
| HBuilderX | HBuilderX、语言包 |
市场还提供优秀作者及热门插件排行榜,并支持对 uniCloud 插件、uts/原生插件设置付费销售,对免费插件设置"先看广告后下载"的广告解锁机制。
付费插件版本机制
付费插件支持普通授权版与源码授权版两种形式,两者功能完全一致(本质是同一套代码),区别在于代码可见性与授权范围:
| 版本名称 | 代码保护 | 授权 | 交易方式 |
|---|---|---|---|
| 普通授权版 | 部分源码不可见 | 基于该项目和/或该服务空间的使用权、未加密部分的二次开发权 | 买方自助下单,即买即用,买方实名信息对卖方保密 |
| 源码授权版 | 所有代码源码可见 | 完整的二次开发权、完整可控的基于源码审查的安全性 | 签署带数字签名的三方电子协议,先签协议后付款获取源码 |
插件作者上传插件时可仅选择普通授权版,源码授权版为可选项,也可拒绝与特定买家签订源码授权版的电子合同。加密文件的清单由插件作者配置,无论试用还是购买普通授权版,都看不到加密文件源码。
各类型付费插件的试用机制:
- uts 插件:针对项目申请试用,插件内容对试用者不可见,只能用于打包自定义基座,不能用于正式发布,无有效期限制;
- App 原生插件:针对项目申请试用,插件不下载,只能用于云端打包自定义基座;
- uniCloud 插件:针对服务空间申请试用,加密云函数试用期(一般 7 天)结束后自动删除;
- 前端组件:针对项目申请试用,只能用于本地运行或打包自定义基座。
详细机制可参阅 插件市场介绍 与 插件变现指南。
三、uni_modules:大一统的包管理方案
什么是 uni_modules
主流语言/平台都有自己的包管理方案——js 有 npm/yarn/pnpm,Android 有仓储,iOS 有 CocoaPods,鸿蒙有 ohpm。而 uni-app 是大一统开发,涵盖客户端与 uniCloud 服务器,客户端又包括 web、Android、iOS 与各家小程序。因此 uni-app 需要一个大一统的包管理方案,这就是uni_modules(HBuilderX 3.1.0+ 支持)。
它是一个海纳百川型的设计:
- 不管是 js/uts 库、组件、页面、uniCloud 云函数、公共模块,甚至是整个项目,都可以封装成一个
uni_modules(类似 Android 的 aar); - 不管是 npm、Android 仓储、iOS 的 CocoaPods、鸿蒙的 ohpm,都可以纳入
uni_modules中。
可以简单理解:把一个项目符合 uni-app 规范的工程目录整体挪到一个uni_modules下,打包成一个模块。
与 node_modules 的对比
既然已有node_modules,为何还需要uni_modules:
node_modules不满足全平台包管理需求,无法容纳 Android 仓储、iOS 的 CocoaPods、鸿蒙的 ohpm;node_modules不满足云端一体需求,uniCloud 的云函数、公共模块、schema 与前端部分无法有效融合;uni_modules支持付费与商业插件,DCloud 插件市场提供版权保护,而node_modules不支持;node_modules层层嵌套造成海量文件数,uni_modules支持依赖但不支持 module 嵌套,鼓励优化包体积;uni_modules在 js 支持的平台同样容纳node_modules,没有排斥。
除发布插件外,uni_modules也是大型工程的模块分割方案。例如旅游应用可以把机票、酒店、火车票等模块分拆为不同的uni_modules,由不同团队并行开发。
目录结构
非项目类型插件(组件、js sdk、页面模板、云函数)需放置在项目的uni_modules目录下,其目录结构与 uni-app 项目结构一致:
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注册动态菜单注意事项:
- 插件目录不支持
pages.json、App.vue/uvue、main.js/uts、manifest.json、uni.scss文件,如需使用者修改这些内容,请在 readme.md 中说明; - 插件目录支持
pages_init.json,可方便地注册页面到项目的 pages.json; - 插件内引用资源、跳转页面尽量使用相对路径;
- 插件内 components 目录支持 easycom 规范,与项目内组件冲突时编译会提示,可通过修改组件目录及文件名解决。
在 HBuilderX 中,uni_modules下包含的 uniCloud 目录内容会以引用方式显示在主项目根目录的 uniCloud 中(文件图标左下角显示快捷方式箭头)。仓库 src/uni_modules 下提供了大量可参考的插件实例,例如 uni-getbatteryinfo(含 package.json、readme.md、changelog.md 与 utssdk 目录)、uni-storage、uni-network、uni-payment 等。
package.json 插件配置
package.json在每个uni_modules插件中必须存在,包含插件基本信息。以 HBuilderX 4.71 为分界,平台兼容性规范有所不同。
HBuilderX 4.71 之前版本规范(节选):
{ "id": "作者ID-插件英文名称", // 必填,格式如'xx-yy',作者ID和插件名称只能包含英文、数字 "displayName": "插件显示名称", // 必填 "version": "1.0.0", // 必填 "description": "插件描述", // 必填 "keywords": [], // 必填,最多5个 "repository": "github:user/repo", // 仓库地址 "engines": { // HBuilderX/cli 最低兼容版本 "HBuilderX": "^3.1.0" }, "dcloudext": { // DCloud插件市场配置 "category": ["前端组件", "通用组件"], "type": "component-vue", // 插件市场分类标识 "sale": { // 销售(目前仅限uniCloud类插件) "regular": { "price": "0.00" }, "sourcecode": { "price": "0.00" } }, "contact": { "qq": "" }, "declaration": { // 隐私、权限及商业化声明 "ads": "", "data": "", "permissions": "" }, "npmurl": "" }, "uni_modules": { "scripts": { "init": "node scripts/init.js" }, "dependencies": [], // 依赖的 uni_modules 插件ID列表 "encrypt": [ // 配置云函数、公共模块、clientDB Action加密 "uniCloud/cloudfunctions/uni-admin/controller/permission.js" ], "platforms": { // 平台兼容性:y 支持 / n 不支持 / u 不确定,默认为 u "cloud": { "tcb": "y", "aliyun": "y" }, "client": { ... } }, "treeShaking": { // 摇树配置 "app": { "android": true, "ios": true, "harmony": false }, "web": false } } }HBuilderX 4.71 起平台兼容性改版:平台兼容性针对 uni-app 与 uni-app x 两个维度拆分,兼容性标记由 y/n/u 调整为√(支持)、x(不支持)、-(不确定,默认值);新增多语言、暗黑模式、宽屏模式定义;client 节点下增加uni-app、uni-app-x两个子节点分别维护兼容性数据。使用旧版 HBuilderX 发布时,插件市场会自动转换为新版规范;为获得准确兼容性设置,建议升级到 HBuilderX 4.71+ 发布。完整配置示例见 uni_modules 文档。
摇树配置(treeShaking):true表示项目代码中使用到该模块时才打包;false表示即使未使用也包含,默认值为true。可全局配置布尔值,也可按平台分别配置。
uni_modules.config.json 与 .npmignore
uni_modules.config.json位于项目根目录,用于配置插件更新后的触发脚本(如 postupdate、preupload、postupload,可通过process.env.UNI_MODULES_ID获取被更新的插件 ID)以及插件 uniCloud 所属的服务空间。当项目同时关联阿里云与腾讯云两个服务空间时,可通过该文件手动指定归属;仅关联一个服务空间时无需配置。
.npmignore用于发布时忽略目录或文件,典型内容:
.hbuilderx unpackage node_modules package-lock.json注意:项目根目录的.npmignore对发布项目、插件模板生效;uni_modules/插件Id/.npmignore对发布插件生效。
pages_init.json 页面注册
pages_init.json(HBuilderX 3.5.0+)解决插件页面注册问题。当 uni_modules 插件根目录存在该文件时,导入工程会弹出合并页面路由的 pages.json 修改界面,点击确认即完成页面注册:
{ "pages": [{ "path": "uni_modules/uni-feedback-admin/pages/uni-feedback-admin/add", "style": { "navigationBarTitleText": "新增" } } ] }注意:pages_init.json最终不会导入工程;暂不支持注释(包括条件编译);HBuilderX 低于 3.5 时仍需手动编辑 pages.json 注册页面。
HBuilderX 中的日常操作
- 下载:插件详情页点击"使用 HBuilderX 导入插件",选择目标 uni-app 项目即可;支持 easycom 组件直接使用,其他资源按目录结构引入,如
import {test} from '@/uni_modules/xx-yy/js_sdk/test.js'; - 安装依赖:导入时 HBuilderX 自动安装所有三方依赖,也可在插件目录右键手动执行"安装插件三方依赖";
- 更新:插件目录右键"从插件市场更新",并可对比新旧代码确认更新内容;
- 卸载:直接删除插件目录即可。
四、uts 插件:用一门语言封装全部原生能力
uts 语言与 uts 插件
uts(uni type script)是统一、强类型的脚本语言,可编译为不同平台语言:web 平台编译为 JavaScript,Android 平台编译为 Kotlin,iOS 平台编译为 Swift(HX 3.6.7+),harmonyOS 平台编译为 ArkTS(HX 4.22+)。它采用与 ts 基本一致的语法规范,支持绝大部分 ES6 API。uts 语言既可用于开发独立 App(uni-app x),也可用于开发插件。
uts 插件利用 uts 语法操作原生 API(手机 OS API 或三方 SDK),封装成 uni_modules 插件供前端调用:
- uni-app 中由 js 调用 uts 插件(HBuilderX 3.6 支持 vue3 编译器,3.6.8 支持 vue2);
- uni-app x 中由 uts 调用 uts 插件(HBuilderX 3.9 支持)。
一个 uts 插件可同时支持 uni-app 与 uni-app x,并分目录编写所有平台代码,同时支持 App、web、小程序。uts 插件分两类:
- API 插件:扩展 API 能力,在 script 里调用,即便涉及 UI 也多为全屏窗口或弹出窗口;
- 组件插件:扩展界面组件,在 template 里调用,内嵌在页面中。
仓库中 src/uni_modules/uni-getbatteryinfo 即为官方电量插件的完整示例(uni-app x 版本),其utssdk目录下按平台拆分实现。
uts 插件目录结构
├─static // 静态资源 ├─utssdk │ ├─app-android //Android平台目录 │ │ ├─assets //Android原生assets资源目录,可选 │ │ ├─libs //Android原生库目录(jar/aar/so),可选 │ │ ├─res //Android原生res资源目录,可选 │ │ ├─AndroidManifest.xml //Android原生应用清单文件,可选 │ │ ├─config.json //Android原生配置文件 │ │ ├─hybrid.kt //Android混编的kt文件 │ │ └─index.uts //Android原生插件能力实现 │ ├─app-ios //iOS平台目录 │ │ ├─Frameworks //三方 framework/xcframework 依赖库,可选 │ │ ├─Libs //三方 .a 依赖库,可选 │ │ ├─Resources //合并到应用Main Bundle的资源,可选 │ │ ├─EmbedResources //合并到动态库Framework Bundle的资源(HBuilderX5.08+),可选 │ │ ├─info.plist //合并到主 info.plist 的配置,可选 │ │ ├─UTS.entitlements //合并到主工程 entitlements 的配置,可选 │ │ ├─config.json //iOS原生配置文件 │ │ ├─hybrid.swift //iOS混编的swift文件 │ │ ├─interceptor.js //js调用插件代码的拦截器 │ │ └─index.uts //iOS原生插件能力实现 │ ├─web //web平台目录 │ │ ├─package.json //web平台插件依赖配置 │ │ └─index.uts │ ├─mp-weixin / mp-alipay / mp-baidu ... //各小程序平台目录,可选 │ ├─interface.uts //声明插件对外暴露的API,必需 │ ├─unierror.uts //定义插件对外暴露的错误信息,可选 │ └─index.uts //跨平台插件入口,可选 └─package.json //插件清单文件,必需入口规则:根目录index.uts是程序主入口;分平台目录存在index.uts时优先使用分平台实现,否则回退到根目录。代码组织有三种方式:根目录 index.uts 写条件编译(简单业务一个文件搞定);根目录 index.uts 写条件编译并 import 分平台文件;不写根目录 index.uts,直接在分平台目录写实现(仅做单端插件时更简单)。
interface.uts与index.uts是声明与实现的关系,在 interface.uts 中声明的类型,HBuilderX 会自动识别并给出语法提示。
平台原生配置
Android(app-android 目录):
| 目录/文件 | 用途 |
|---|---|
| assets | 原生 assets 资源目录,建议只放插件内置资源 |
| libs | 三方 jar/aar/so 库目录(本地调试不支持直接使用 so,需封装为 AAR 或分别集成 so 与 jar) |
| res | 原生 res 资源目录 |
| AndroidManifest.xml | 原生应用清单文件 |
| config.json | 原生配置文件 |
| index.uts | 主入口,interface.uts 声明能力在 Android 下的实现 |
config.json支持配置abis(NDK so 库支持的 CPU 类型:armeabi-v7a、arm64-v8a、x86、x86_64)、dependencies(仓储依赖,字符串项按implementation方式、JSON 对象项按 source 字段作为 gradle 源码合并进 build.gradle)、minSdkVersion(uni-app 最低 19/Android 4.4.2,uni-app x 最低 21/Android 5.0)以及project(gradle 插件白名单:com.google.gms.google-services、com.huawei.agconnect、com.hihonor.mcs.asplugin等)。完整配置示例见 uts-plugin.md。
iOS(app-ios 目录):
| 目录/文件 | 用途 |
|---|---|
| Frameworks | 三方 framework/xcframework 依赖库(支持静态库与动态库) |
| Libs | 三方 .a 依赖库(HBuilderX 3.7.2+) |
| Resources | 合并到应用 Main Bundle 的资源 |
| EmbedResources | 合并到动态库 Framework Bundle 的资源(HBuilderX 5.08+) |
| Info.plist | 合并到原生工程 Info.plist 的配置 |
| PrivacyInfo.xcprivacy | iOS 隐私清单文件 |
| UTS.entitlements | 合并到原生工程 entitlements 的配置 |
| config.json | 原生配置文件 |
| index.uts | 主入口实现 |
iOSconfig.json支持frameworks(依赖系统库)、deploymentTarget(最低 iOS 版本,默认 12.0)、identifier(插件 Bundle Identifier)、validArchitectures(CPU 架构,默认 arm64)、dependencies-pods(依赖 pod 库,HBuilderX 3.8.5+)与dependencies-pod-resources(pod 资源存放位置,HBuilderX 5.25+,uni-app 默认 "all",uni-app x 默认 "framework")。iOS Extension 支持详见文档中"iOS Extension"章节。
鸿蒙(app-harmony 目录):主要包含 index.uts,为主入口、interface.uts 声明能力在 harmony 平台下的实现。
开发一个 API 插件示例
以官方文档的uts-api为例,流程为:在uni_modules目录右键新建 uni_modules 插件 → 编写 interface.uts → 编写 unierror.uts → 在分平台 index.uts 实现。
interface.uts统一定义对外暴露的 API 类型、参数类型、返回值类型与错误码类型:
export type MyApiOptions = { paramA : boolean success ?: (res : MyApiResult) => void fail ?: (res : MyApiFail) => void complete ?: (res : any) => void } export type MyApiResult = { fieldA : number, fieldB : boolean, fieldC : string } // 错误码遵循uni错误规范,建议以90开头 export type MyApiErrorCode = 9010001 | 9010002; export interface MyApiFail extends IUniError { errCode : MyApiErrorCode }; export type MyApi = (options : MyApiOptions) => void export type MyApiSync = (paramA : boolean) => MyApiResultunierror.uts实现错误主题、错误信息映射与错误对象:
import { MyApiErrorCode, MyApiFail } from "./interface.uts" export const UniErrorSubject = 'uts-api'; export const UTSApiUniErrors : Map<MyApiErrorCode, string> = new Map([ [9010001, 'custom error mseeage1'], [9010002, 'custom error mseeage2'], ]); export class MyApiFailImpl extends UniError implements MyApiFail { override errCode: MyApiErrorCode constructor(errCode : MyApiErrorCode) { super(); this.errSubject = UniErrorSubject; this.errCode = errCode; this.errMsg = UTSApiUniErrors.get(errCode) ?? ""; } }随后在app-android/index.uts等平台目录实现业务逻辑(异步方法 myApi 与同步方法 myApiSync),前端在 uvue 中按如下方式使用:
import { myApi, myApiSync, MyApiOptions } from "@/uni_modules/uts-api"; let options = { paramA: false, complete: (res : any) => { console.log(res) } } as MyApiOptions; myApi(options); console.log(myApiSync(true))注意:import uts 插件只能到插件根目录,不能引入内部文件;uvue 中禁止直接导入 utssdk 目录下的 uts 文件。
获取电量插件完整示例
文档以获取电量为完整案例。Android 平台实现:
import Context from "android.content.Context"; import BatteryManager from "android.os.BatteryManager"; import { UTSAndroid } from "io.dcloud.uts"; export function getBatteryCapacity(): string { const context = UTSAndroid.getAppContext(); if (context != null) { const manager = context.getSystemService( Context.BATTERY_SERVICE ) as BatteryManager; const currentLevel: number = manager.getIntProperty( BatteryManager.BATTERY_PROPERTY_CAPACITY ); return '' + currentLevel + '%'; } return "0%"; }iOS 平台通过UIDevice实现:
import { UIDevice } from "UIKit"; export function getBatteryLevel():number { UIDevice.current.isBatteryMonitoringEnabled = true let level = Number(UIDevice.current.batteryLevel * 100) return level }鸿蒙平台通过@ohos.batteryInfo实现。前端调用(显性引用):
import { getBatteryCapacity } from "@/uni_modules/uts-getbatteryinfo"; console.log(getBatteryCapacity())亦支持泛型引用(import * as UTSHello from "@/uni_modules/uts-osapi")。该电量插件在仓库中的 uni-app x 版本可参考 src/uni_modules/uni-getbatteryinfo。
应用生命周期监听与数据交互
- iOS:自定义 class 遵循
UTSiOSHookProxy协议即可监听应用生命周期(需 export 才会参与编译,自动注册),可监听启动、远程/本地通知、url scheme 唤起、前后台切换、Universal Link 等回调。协议定义见 UTSiOSHookProxy。 - Android:实现
UTSAndroidHookProxy接口的onCreate(application)可在 Application 初始化时执行三方 SDK 初始化。注意:初始化早于 uni,不支持调用 uni api;不支持调用 UTSAndroid 的 getAppContext/getAppActivity;一个插件只允许实现一个该接口的 class;建议判断隐私合规同意后再初始化。接口定义见 UTSAndroidHookProxy。 - 鸿蒙:暂不支持此能力。
UTS 与 uni-app 环境数据交互:UTS 向 uni-app 传值支持 TS 基本数据类型与 UTSJSONObject;uni-app 向 UTS 传值支持基本类型、type 类型与 UTSJSONObject(声明为 any 时 Object 也会被转换为 UTSJSONObject)。复杂参数(含对象数组)目前需将成员声明为 any 数组,再通过new UTSJSONObject(item)包装访问。UTSJSONObject 的完整用法见 contenteditable="false">【免费下载链接】uni-appA cross-platform framework using Vue.js项目地址: https://gitcode.com/gh_mirrors/un/uni-app
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考