uni-app 玩转条件编译:自定义平台的条件编译实战详解
一. 条件编译支持的场景
uni-app 的条件编译能支持以下几种场景,具体如图所示:
1. API 的条件编译
简言之,同一功能实现,可能有不同的逻辑处理,比如:在 js 文件中,或者在 Vue 文件中的 script 代码中有不同的逻辑处理方式,使用方式如下:
// #ifdef %PLATFORM%
该平台特有的API实现;
// #endif
2. 组件的条件编译
在 template 模版中,可能会在不同的平台展示不同的组件,或者是展示效果不同,或者是在某一平台不需要展示,使用方式如下:
<!-- #ifdef %PLATFORM% -->
该平台特有的组件
<!-- #endif -->
3. 样式的条件编译
在不同的平台下有差异性的样式处理,使用方式如下:
/* #ifdef %PLATFORM% */
该平台特有的样式
/* #endif */
4. pages.json 的条件编译
不同平台下的特有功能,以及小程序平台的分包,都可以通过 pages.json
的条件编译来更好地实现。这样,就不会在其它平台产生多余的资源,进而减小包体积。
例如:在 pages.json
中配置 pages 页面路由,在 H5 平台下编译 “测试 1” 页面,在微信小程序页面下编译 “测试 2” 页面
"pages": [
// #ifdef H5
{
"path": "pages/test1",
"style": {
"navigationBarTitleText": "测试1"
}
},
// #endif
// #ifdef MP-WEIXIN
{
"path": "pages/test2",
"style": {
"navigationBarTitleText": "测试2"
}
},
// #endif
]
特别注意:json 的条件编译,一定要注意最后","分隔符的所属问题,不能有多余的逗号,可能会出现异常情况,导致编译失败!
5. static 目录的条件编译
在不同平台,引用的静态资源可能也存在差异,通过 static 的条件编译可以解决此问题,static 目录下新建不同平台的专有目录,目录名称均为小写,专有目录下的静态资源只有在特定平台才会编译进去。
如以下目录结构,a.png 只有在微信小程序平台才会编译进去,b.png 在所有平台都会被编译,合理的利用 static 目录的条件编译能够大大的减小包体积,在微信小程序的分包实践中尤为重要!
┌─static
│ ├─mp-weixin
│ │ └─a.png
│ └─b.png
├─main.js
├─App.vue
├─manifest.json
└─pages.json
二. 注意事项
关于条件编译,有以下几个注意事项需要在编程的过程中重点关注一下:
-
条件编译 APP-PLUS 包含 APP-NVUE 和 APP-VUE ;
-
对于未定义平台名称,可能是名称写错了,也可能是低版本 HBuilderX 没有这个平台,此时的条件编译,
#ifdef
中的代码不会生效,而#ifndef
中的代码会生效; -
使用条件编译请保证编译前和编译后文件的语法正确性,即要保障无论条件编译是否生效都能通过语法校验。比如:json 文件中不能有多余的逗号,js 中不能重复导入;
-
Android 和 iOS 平台不支持通过条件编译来区分,如果需要区分 Android、iOS 平台,请通过调用
uni.getSystemInfo
来获取平台信息。支持ifios
、ifAndroid
代码块,可方便编写判断。
三. 自定义条件编译平台
1. 背景(我为什么要进行自定义平台)
在开发 Web 时,可能有时候需要将同一套代码编译发布到不同的站点,比如多个不同的微信 h5 站,这些站点可能有不同的差异性处理。在开发小程序时,也经常有扩展小程序平台,比如同一套代码,我需要发布到多个小程序,可能这些小程序之间少许有些差异。因此,uni-app 通过在 package.json
文件中增加 uni-app 扩展节点,可实现自定义条件编译平台。
在我之前开发的实际项目中,同一套代码需要部署多个平台,大概有 10 个平台,而且这几个平台可能有 90% 以上的代码是相同的,因此我就没有必要重新开发一套代码了。这多个平台的含义是:在微信小程序有多个平台,在 H5 网站有多个平台,可能在 APP 中也有多个平台,在这些平台之间,可能有或多或少的差异,比如:
-
功能的差异性,页面展示不同,tabbar 数量等
-
请求 API 的差异性,对应的后端服务 API 不同
-
全局变量的差异性,主题配色变量,默认语言等
因此,以上这些差异就会要求在代码中处理不同平台之间的差异性,以下是我的实际项目中的自定义平台:
除此之外,还有两个 APP 平台,但是目前 uni-app 不支持自定义 APP 的基准平台!
如何增加 uni-app 扩展节点,总结一下有以下几个步骤可以快速完成一个全新平台的编译:
-
声明配置,添加新平台
-
在代码中使用新平台条件编译
-
编译到新平台
2. 第一步: 声明配置,添加新平台
在 package.json 中添加 uni-app 节点,添加以下配置,使新定义的平台生效:
"uni-app": {
"scripts": {
"custom-h5": {
"title": "自定义H5平台",
"browser": "chrome",
"env": {
"UNI_PLATFORM": "h5"
},
"define": {
"CUSTOM-H5": true
}
},
"custom-mp": {
"title": "自定义小程序平台",
"env": {
"UNI_PLATFORM": "mp-weixin"
},
"define": {
"CUSTOM-MP": true
}
}
}
}
参数说明:
正确的结构就是如上所示,下面说一下这几个参数的具体含义
-
title:自定义扩展名称, 在 HBuilderX 中会显示在 运行/发行 菜单中
-
browser:运行到的目标浏览器,仅当 UNI_PLATFORM 为 h5 时有效
- env:环境变量
-
UNI_PLATFORM:基准平台
-
MY_TEST:其他自定义环境变量
-
- define:自定义条件编译
-
CUSTOM-H5:自定义条件编译常量,建议为大写
-
注意事项:
-
只能扩展 web 和小程序平台,不能扩展 app 平台。并且扩展小程序平台时只能基于指定的基准平台扩展子平台,不能扩展基准平台。也就是说 UNI_PLATFORM 仅支持填写 uni-app 默认支持的基准平台,目前仅限如下枚举值:
h5
、mp-weixin
、mp-alipay
、mp-baidu
、mp-toutiao
、mp-qq
。 -
browser
仅在UNI_PLATFORM
为 h5 时有效,目前仅限如下枚举值:chrome、firefox、ie、edge、safari、hbuilderx。 -
package.json
文件中不允许出现注释,否则扩展配置无效。
3. 第二步:在代码中使用条件编译
接下来,可以在代码里使用自定义的条件编译,为这个新平台编写专用代码:
// 新的自定义微信小程序平台
// #ifdef CUSTOM-MP
/**
* 微信小程序 代码
*/
// #endif
// 新的自定义H5平台
// #ifdef CUSTOM-H5
/**
* H5 代码
*/
// #endif
4. 第三步:编译到新平台
运行时可以执行面向新平台的编译运行,发行时可以执行面向新平台的编译发行。如下图所示,我们点击运行和发行,已经都有了我们刚才已经自定义好的平台名称。
四. 总结
关于你是否需要自定义平台,关键在于项目里复用的代码多还是个性的代码多,如果都是复用的代码多,并且对应的服务端是一致的,所以仍然可以自定义平台多端部署,而个性的代码放到不同平台的目录下,进行差异化维护。
五. 资源文档
-
uni-app 组件使用手册
-
uni-app API 使用手册
-
uni-app 条件编译处理多端差异
-
package.json 扩展 uni-app 属性
-
vue.config.js 说明