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

二. 注意事项

关于条件编译,有以下几个注意事项需要在编程的过程中重点关注一下:

  1. 条件编译 APP-PLUS 包含 APP-NVUE 和 APP-VUE ;

  2. 对于未定义平台名称,可能是名称写错了,也可能是低版本 HBuilderX 没有这个平台,此时的条件编译,#ifdef 中的代码不会生效,而 #ifndef 中的代码会生效;

  3. 使用条件编译请保证编译前和编译后文件的语法正确性,即要保障无论条件编译是否生效都能通过语法校验。比如:json 文件中不能有多余的逗号,js 中不能重复导入;

  4. Android 和 iOS 平台不支持通过条件编译来区分,如果需要区分 Android、iOS 平台,请通过调用 uni.getSystemInfo 来获取平台信息。支持 ifiosifAndroid 代码块,可方便编写判断。

三. 自定义条件编译平台

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 默认支持的基准平台,目前仅限如下枚举值:h5mp-weixinmp-alipaymp-baidump-toutiaomp-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. 第三步:编译到新平台

运行时可以执行面向新平台的编译运行,发行时可以执行面向新平台的编译发行。如下图所示,我们点击运行和发行,已经都有了我们刚才已经自定义好的平台名称。

四. 总结

关于你是否需要自定义平台,关键在于项目里复用的代码多还是个性的代码多,如果都是复用的代码多,并且对应的服务端是一致的,所以仍然可以自定义平台多端部署,而个性的代码放到不同平台的目录下,进行差异化维护。

五. 资源文档

相关推荐
狗头大军之江苏分军6 小时前
iPhone 17 vs iPhone 17 Pro:到底差在哪?买前别被忽悠了
前端
小林coding6 小时前
再也不怕面试了!程序员 AI 面试练习神器终于上线了
前端·后端·面试
文心快码BaiduComate6 小时前
WAVE SUMMIT深度学习开发者大会2025举行 文心大模型X1.1发布
前端·后端·程序员
babytiger6 小时前
python 通过selenium调用chrome浏览器
前端·chrome
passer9817 小时前
基于webpack的场景解决
前端·webpack
奶昔不会射手7 小时前
css3之grid布局
前端·css·css3
举个栗子dhy7 小时前
解决在父元素上同时使用 onMouseEnter和 onMouseLeave时导致下拉菜单无法正常展开或者提前收起问题
前端·javascript·react.js
Coding_Doggy7 小时前
苍穹外卖前端Day1 | vue基础、Axios、路由vue-router、状态管理vuex、TypeScript
前端