作者:张振东,已获得作者授权转载。
一、项目背景
1.1 为什么要引入小程序?
业务希望通过消息通知下发的方式,及时通知用户优化部分环节的体验。
技术方案选型:
- H5页面:无法使用微信、抖音等宿主APP的消息通知下发能力,主动由服务端通知用户 ❌
- APP:支持消息通知下发功能,但是用户需要额外下载安装,提高用户使用成本 ❌
- 小程序:支持消息通知下发功能,轻量 ✅
1.2 小程序的优势
从用户视角:
- 触手可及,在常用APP内直接操作,不需要来回切换APP,提高操作频率和效率
- 用完即走,无需下载安装,不需要花时间熟悉其他的APP,降低使用心智
从企业视角:
- 基于用户基数非常大的APP(抖音、微信、支付宝、QQ),实现最小成本的用户挖掘
- 借助小程序拉起小程序、小程序拉起APP的功能,实现用户引流
- 相对于审批限制很多的应用市场(APP Store),小程序的使用更加简单方便,版本更新迭代的审核也更快
1.3 目标
- 提高用户签到效率,减少排队时长
- 完善应用生态,实现移动化跨平台小程序,支持一套代码编译发布到多个平台(抖音、微信、支付宝、QQ)
- 沉淀相关物料和工具
二、产品设计
2.1 产品交互链路
三、技术方案
3.1 技术链路图
3.2 前置准备工作
3.2.1 抖音开放平台
线上环境 - 线上appId
沙盒环境(普通沙盒环境、继承测试环境)- 沙盒appId(用于boe和ppe测试)
- 安装抖音开发者工具
点击链接,选择对应的设备版本进行下载即可安装
3.2.2 配置沙盒环境
开发、联调、测试阶段主要在沙盒环境进行(可以模拟支付场景),需要进行专门的配置
如果业务入驻审批时间过长影响到项目节奏,可以由开发人员注册账号后新建沙盒环境提前进入开发阶段
创建沙盒
点击“新增沙盒”按钮后会出现配置弹框
沙盒类型:小程序
沙盒应用名称
能力范围:沙盒通用能力(如果没有创建正式小程序的话,选择沙盒通用能力)
正式小程序能力映射(和正式环境的配置保持一致,如果已创建正式小程序建议选择这个配置)
配置服务端域名白名单
小程序对应的业务后端接口需要提前配置到白名单内,否则会访问受限
添加域名白名单时,域名类型选择“request合法域名”,域名url填写后端接口域名(不需要输入http前缀)
服务端配置前端请求域名
考虑到接口安全性问题,后端需要配置前端网关到域名白名单,配置相关秘钥信息(用于和抖音后端服务交互)
沙盒环境的网关域名:open-sandbox.douyin.com
测试账号白名单
需要将登陆账号添加到“测试账号”白名单才能够在沙盒APP使用小程序
点击“绑定测试账号”,然后使用抖音沙盒APP扫码即可完成绑定,完成沙盒环境配置
3.3 项目搭建
3.3.1 框架选择-Taro
小程序跨平台框架 | 框架介绍 |
uni-app | 使用Vue.js开发所有前端应用的框架,开发者编写一套代码,可发布到iOS、Android、Web(响应式)、以及各种小程序。 |
Chameleon | 支持小程序、RN、Weex和H5等多种平台,采用与 Vue 一致的组件化方案、单文件组织方式、生命周期,同时数据响应能力对齐 Vue,数据管理能力对齐 Vuex。 |
Rax | 支持小程序、Web、Node.js和快应用等多种平台,使用rax开发小程序,可以一次编码多端投放,使用 Rax DSL 配合 Web 应用的工程配置及各种基础库,Rax 是一个基于 React 写法的跨容器的 js 框架。 |
Taro | Taro是一款多端统一开发框架,不仅提供了React小程序开发的完整解决方案,同时也支持vue、angular和原生小程序的开发方式,支持在不同的小程序平台上运行。框架生态完善,公司内部有很多相关实践文档参考和沉淀的组件库auxo-taro。 |
小程序跨平台解决方案,支持使用 React/Vue/Nerv 等框架来开发各种APP小程序
3.3.2 项目初始化
- 安装Taro脚手架工具(推荐使用yarn进行安装)
1 # 使用 npm 安装 CLI
2 $ npm install -g @tarojs/cli
3
4 # OR 使用 yarn 安装 CLI
5 $ yarn global add @tarojs/cli
6
7 # OR 安装了 cnpm,使用 cnpm 安装 CLI
8 $ cnpm install -g @tarojs/cli
- 使用taro init进行项目搭建,按照实际需要选择项目基础配置即可
3.3.3 选择组件库
选择组件库的两个重要参考维度:组件丰富度、高阶组件能力
组件丰富度:要求组件的种类多,可以覆盖大部分使用场景
高阶组件能力:复杂组件能否满足复杂场景的使用要求,比如表单组件、下拉加载组件、轮播组件等
序号 | 组件库名称 | 主要信息 | 示例截图 |
1 | Taro 团队官方出品,数量少,功能不齐全,且文档不够丰富。 | ||
2 | 京东出品,包含49个组件,支持React。但表单组件API过于简单,无法实现表单校验,缺少高阶组件。 | ||
3 | 京东出品,包含 50+组件,京东风格痕迹较重。并且对 react 的支持度较差。 | ||
4 | auxo推出的作为电商 C 端小程序组件库,基于Taro实现一套代码多端运行,但是组件数量少,高阶组件严重不足,没有表单组件、下拉加载组件 | ||
5 | 基于Vant开发,包含 60+组件,支持React,组件数量足够多,且风格比较中立,高阶组件能力完善 |
临时选择的组件库是Taroify,满足业务开发需要,且方便根据UI样式二次封装组件库
3.3.4 项目配置
推荐几个非常实用的Taro项目配置,尽可能让大家像开发浏览器页面一样开发小程序,降低学习成本,提高开发效率
@tarojs/plugin-html插件
支持在Taro项目中使用HTML标签进行组件开发,可以保留开发浏览器页面的习惯,使用<div>来替代<view>。不过需要注意这个插件会把<span>标签也最终渲染成<view>,原因是小程序里的<Text>标签只能内部嵌套<Text>,如果把<span>标签替换成<Text>则<span>的内部就只能嵌套<span>、<i>、<b>这些行内元素,影响开发体验
1 {
2 plugins: [
3 '@tarojs/plugin-html'
4 ],
5 }
mini.postcss.cssModules.enable
该属性值默认是false,如果想使用css的module功能,则需要手动将值设置成true,然后css类的名字就会根据设置的generateScopedName自动生成,默认是[name]__[local]___[hash:base64:5],后面5位是基于base64生成的随机hash值
1 {
2 mini: {
3 postcss: {
4 cssModules: {
5 enable: true, // 默认为 false,如需使用 css modules 功能,则设为 true
6 config: {
7 namingPattern: 'module', // 转换模式,取值为 global/module
8 generateScopedName: '[name]__[local]___[hash:base64:5]'
9 }
10 }
11 }
12 }
13 }
designWidth
designWidth用来设置设计稿的尺寸,常见的值有750、640、375等,Taro默认会对所有单位进行转换(行内样式需要使用Taro.pxTransform()才能转换)。但是如果遇到比较复杂的情况,比如项目的设计稿是375px,而引入的组件库的标准尺寸是750px时就需要进行特殊配置,上面提到的“Taroify”组件库的设计稿尺寸就是750px
1 {
2 designWidth: (input) => {
3 // 第三方组件库的设计尺寸是750px
4 if (input.file?.replace(/\\+/g, '/').indexOf('@taroify') > -1) {
5 return 750;
6 }
7 // 项目设计稿的标准尺寸375px
8 return 375;
9 },
10
11 // px->rpx的单位换算规则
12 deviceRatio: {
13 640: 2.34 / 2,
14 750: 1,
15 828: 1.81 / 2,
16 375: 2 / 1
17 },
18 }
@tarojs/plugin-http
小程序有一套自己的原生网络请求体系,可以通过Taro.request(option)进行使用,但是为了符合之前的开发习惯,可以通过@tarojs/plugin-http这个插件对axios实例进行封装,方便把之前在浏览器开发项目中封装好的axios配置直接拿过来用,配置请求拦截器、响应拦截器等等
1 {
2 plugins: ['@tarojs/plugin-http'],
3 }
不过由于真实的执行环境还是在小程序,就会受到部分限制:
- 暂不支持上传,且插件默认会将全局 FormData、Blob对象替换成undefined(仅针对小程序环境)
另外由于这个插件比较新,对Taro的版本有要求
- 需搭配 taro 主包 3.6.0 及其以上版本使用
- webpack4 用户需升级插件版本为 3.6.6 及其以上
3.4 注意事项
3.4.1 数据安全
如何上送用户身份信息(利用抖音的openId去识别用户身份)
Token: 前端调用taro.login()获取的用户临时登陆凭证
OpenId: 后端根据前端上送的token调用抖音开发平台接口获取到的用户openId,该openId在小程序appId下保证唯一
3.4.2 引入lodash作为公共utils
现状:Taro项目中引入lodash后直接使用会报错
原因:
Webpack5 处理node.global的实现:
1 /* webpack/runtime/global */
2 !function() {
3 __webpack_require__.g = (function() {
4 if (typeof globalThis === 'object') return globalThis;
5 try {
6 return this || new Function('return this')();
7 } catch (e) {
8 if (typeof window === 'object') return window;
9 }
10 })();
11 }();
- 抖音小程序环境不支持globalThis变量
- Webpack 5的webpack/runtime/global实现,相对于Webpack4的webpack/buildin/global,变成了严格模式,导致严格模式下此处的this是undefined
- 小程序的JS环境里,new Function('return this')这种构造函数写法,return的this是空对象(在浏览器引擎或者正常Node环境,都正常return全局对象);微信小程序、字节小程序都存在这个问题
解决方案
- 在Webpack5 配置里关闭默认的global实现,node.global = false
- 使用ProvidePlugin注入自定义global兼容实现,参考webpack4内的实现即可:
代码实现:
1 // webpack4GlobalRuntime.js
2 // 来源是webpack@4/buildin/global.js
3 var g;
4
5 // This works in non-strict mode
6 g = (function() {
7 return this;
8 })();
9
10 try {
11 // This works if eval is allowed (see CSP)
12 g = g || new Function("return this")();
13 } catch (e) {
14 // This works if the window reference is available
15 if (typeof window === "object") g = window;
16 }
17
18 // g can still be undefined, but nothing to do about it...
19 // We return undefined, instead of nothing here, so it's
20// easier to handle this case. if(!global) { ...}
21
22 module.exports = g;
四、价值收益
- 定量效果
- 通过引入抖音小程序解决方案,用户的提前预约率提升了 10%+,排队时长大幅下降。
- 定性效果
- 用户等待的负向反馈明显减少,近几周时间未收到此类投诉。