微信小程序差不多已经推出了两年半的时间,对于还没有入坑或刚准备动手的开发同学,本文档将尝试在几分钟内让你快速的了解其基本开发生态,虽嫌蜻蜓点水零零碎碎,但应该可对接下来的开发做出合理的抉择。
秉持干湿分离的原则,本文将组织成以下结构:
I. 优点
II. 资源和生态
III. 小程序和云开发点滴
IV. 小程序和开发者工具的基本原理
V. 《组队点餐宝》云开发 DEMO 小程序
VI. 扩展阅读和参考资料
复制代码
大部分内容非常初级,大佬请轻拍或绕行,另外...
I. 优点
- 轻量,目前最大 4M,没有手动安装过程,点开即用
- 使用体验:
HTML5
<微信小程序
<RN/Weex
<原生
- 开发难度:
微信小程序
<HTML5
<RN/Weex
<原生
- 开发体验接近 Vue 和 React,兼容问题少,人力成本和开发时间优势明显
- 推广和上线相比原生应用更简单
- 和微信服务号、模板消息等互相打通
- 易用且安全的微信数据开放
- 附近小程序等功能,不用开发就能获得实体店商业推广
- 云开发将开发门槛降至最低,一个前端人员就能快速完成整个开发过程
II. 资源和生态
微信公众平台 mp.weixin.qq.com
2.1 - 文档
2.2 - 官方社区
2.3 - 开发者工具
在原有的公众号网页调试工具的基础上,集成了公众号网页调试和小程序调试两种开发模式
- 使用公众号网页调试,开发者可以调试微信网页授权和微信JS-SDK 详情
- 使用小程序调试,开发者可以完成小程序的 API 和页面的开发调试、代码查看和编辑、小程序预览和发布等功能
相关概念:公众号网页
许多复杂的业务场景,需要通过网页形式来提供服务,这时需要用到:
- 通过网页授权获取用户的 OpenID 和基本信息等
- 开发者在网页上通过微信 JS-SDK 工具包,在网页上实现录制和播放微信语音、监听微信分享、上传手机本地图片、拍照等许多能力
相关概念:微信小游戏
- 一种特殊类型的小程序,没有小程序 WXML 等,更接近传统 H5 游戏
- 主要编程对象是 Canvas 画布,所有东西都是通过绘制到可见画布来展示的
- Cocos、Egret、Laya 等游戏引擎都适配了小游戏开发
扩展杂谈:Egret 白鹭引擎
- 创始人原来是 Adobe 中国的 flash 布道师,很大程度上复制了原有的成功思路和生态
- 提供了完整的 2D/3D 开发引擎、完善的开发调试工具等产品
堪称 ActionScript3 复刻版的 API 设计:
2.4 - 市场上的同类小程序
2.5 - 第三方开发框架
微信小程序必须在官方的开发者工具图形界面中开发、调试、上传,这限制了预处理样式、转译图片等前端开发常用能力,也无法使用 npm 引入第三方包或使用常见的开发框架
一种最简单的思路是开发一些用 npm scripts 执行 node.js 脚本,完成上述官方工具中不方便的工作,此时一般的目录结构是在“官方规范代码”外面包裹一层,如:
├ mock/
├ assets/
├ dist/ # 这里存放开发者工具中的标准代码
│ ├ ...
│ └ pages/index/
│ ├ index.js
│ ├ index.json
│ ├ index.wxml
│ └ index.wxss # 由外部 less/sass 实时生成,不手动编辑
├ # 也包含了转换后的外部路径或编码后的图片
├ styles/
├ nodemon.json
├ package.json
└ dev.js # 一些 watch、转译等工作
复制代码
这种方式虽然“简陋”,但由于基本上还是用的原生开发,所以不用担心官方升级后(还是相当频繁的)不匹配等问题。
不过毕竟 bigger 略低,能力提升很有限,更多平时前端项目中积累的代码也无法直接复用;
借助 AST 转译的能力,市面上更多成熟的解决方案提供了更好的选择:
Taro
一套遵循 React 语法规范的多端统一开发框架
- 京东“凹凸实验室”出品,长期保持更新维护
- 一键生成 微信小程序、H5、ReactNative、百度小程序、字节跳动小程序、支付宝小程序
- 采用 React 语法标准,支持 JSX 书写,让代码更具表现性
- 支持 TypeScript
- 支持使用 npm/yarn 安装管理第三方依赖
- 支持使用 ES7/ES8 甚至更新的 ES 规范,可自行配置
- 支持使用 CSS 预编译器,例如 Sass 等
- 支持使用 Redux/MobX 进行状态管理
- 小程序 API 优化,异步 API Promise 化等等
- 配套的开发工具 Taro CLI 让开发流程自动化
WePy
腾讯开发的“让小程序支持组件化开发的框架”
- 开发风格接近于 Vue.js,支持 Props、自定义事件、Mixin、computed、slot 等
- 支持使用第三方 npm 资源
- 通过 polyfill 让小程序完美支持 Promise
- 可使用 Generator Fu-nction / Class / Async Function 等特性
- 支持 Less/Sass/Styus,wx-ml/Pug,Babel/Typescript
- 支持多种插件处理,如文件压缩,图片压缩,内容替换等,扩展简单
mpVue
美团出品的“一个使用 Vue.js 开发小程序的前端框架”
- 彻底的组件化开发能力:提高代码复用性
- 完整的
Vue.js
开发体验 - 方便的
Vuex
数据管理方案:方便构建复杂应用 - 快捷的
webpack
构建机制:自定义构建策略、开发阶段 hotReload - 支持使用 npm 外部依赖
- 使用
Vue.js
命令行工具vue-cli
快速初始化项目 - H5 代码转换编译成小程序目标代码的能力
2.6 - 适用于小程序的组件库等
WeUI
视觉规范
几种具体技术的实现版本
应用在小程序中
wxParse
微信小程序富文本解析组件,支持 HTML 及 Markdown 转 WXML 可视化
小程序发布之初并不支持直接内嵌 h5 页面,这让很多跃跃欲试直接用既有公众号页面拓展入口的商家和开发者怨声载道。
不到一年后,开始支持 <web-view>
组件,但也特别声明了个人类型与海外类型的小程序暂不支持使用。
这使得一些嵌入网页和构建富文本的工作变得困难,也让 wxParse
组件至今仍然富有意义。
miniprogram-simulate
新出现的小程序自定义组件测试工具集
由于小程序有独特的运行环境,所以对于小程序自定义组件的单元测试一直没有比较优雅的解决方案;
此工具集就是为了解决这一痛点,将原本小程序自定义组件双线程分离运行的机制调整成单线程模拟运行,利用 dom 环境进行渲染,借此来完成整个自定义组件树的搭建。
运行此工具集需要依赖 js 运行环境和 dom 环境,因此可以采用 jsdom + nodejs(如 jest),也可以采用真实浏览器环境(如 karma)
const path = require('path')
const expect = require('chai').expect
describe('component', () => {
it ('should run successfully', () => {
// 直接使用全局的 simulate
const id = simulate.load(path.resolve(__dirname, '../src/component/index'))
const comp = simulate.render(id, {prop: 'index.test.properties'})
comp.attach(document.body) // 挂载在 body 下面
expect(
simulate.match(
comp.dom,
'<wx-view class="main--index">index.test.properties</wx-view>'
)
).to.equal(true)
})
})
复制代码
III. 小程序和云开发点滴
登录态和几种术语
AppID
每个小程序对应一个,在开发阶段开始前从开放平台申请
- 注册成功之后,点击 “开发”—“开发设置” 可以看到 AppID
- 需要在开发者工具中填入 AppID,才能开始编辑项目
- 当场景为由从另一个小程序或公众号打开时,能在小程序的 wx.onShow 回调中获得来源的 AppID
- 用 iOS 或 Android 的 OpenSDK 开发原生 APP,并涉及到打开小程序时,需要配置 AppID
- AppId 是公开信息,泄露 AppId 不会带来安全风险
AppSecret
- AppSecret 是开发者的隐私数据不应该泄露
code
由小程序端调用 wx.login(),从微信服务器获取的一个带有时效性的凭证
- 有效期为 5 分钟
- 由开发者服务器发送 code 等到微信服务器,换取 openid、session_key、unionid 等
openid
也就是用户 id,可以用这个 id 来区分不同的微信用户
unionid
用户在微信开放平台的唯一标识符
- 同一个微信开放平台帐号下的移动应用、网站应用和公众帐号(包括小程序),用户的unionid是唯一的
- 在满足不同条件的前提下,可以通过 wx.login() 或 wx.getUserInfo() 获得
session_key
微信服务器给开发者服务器颁发的身份凭证,开发者可以用 session_key 请求微信服务器其他接口来获取一些其他信息
- 如果每次都通过小程序前端 wx.login() 生成 code 去微信服务器请求信息,整体耗时严重
- 对于一个比较可信的服务端,session_key 相当于给开发者端颁发一个时效性更长的会话密钥
- session_key 也存在过期时间
SessionID
开发者服务器和开发者的小程序之间的会话密钥,一般称为 SessionID
- 用户登录成功之后,由开发者服务器需要生成,并保存对应的用户身份信息
- 把 SessionId 返回给小程序,在后续发起的请求中携带上 SessionId
- 这样就不需要每次都重新获取 code,省去了很多通信消耗
OpenSDK
开发者的第三方 APP 需要唤起小程序等操作时,需要集成对应版本的开发工具包
JS-SDK
微信公众平台面向网页开发者提供的基于微信内的网页开发工具包
wx-server-sdk
云开发时,在“云函数”中引用的 npm 包,
wx-server-sdk
与小程序端的云 API 以同样的风格提供了数据库、存储和云函数的 API
云开发简述
开发者可以使用云开发开发微信小程序、小游戏,无需搭建服务器,即可使用云端能力
云开发弱化了后端和运维概念,无需搭建服务器,使用平台提供的 API 进行核心业务开发,即可实现快速上线和迭代。
目前提供三大基础能力支持:
- 云函数:在云端运行的代码,微信私有协议天然鉴权,开发者只需编写自身业务逻辑代码
- 数据库:一个既可在小程序前端操作,也能在云函数中读写的 JSON 数据库
- 存储:在小程序前端直接上传/下载云端文件,在云开发控制台可视化管理
在云开发中简化登录态的获取
不同于之前章节中获取登录态的复杂,云开发时极度的简化了这一过程。
比如有一个云函数 test
:
// cloudfunction/test/index.js
const cloud = require('wx-server-sdk')
exports.main = (event, context) => {
// 这里获取到的 openId、 appId 和 unionId 是可信的
const {OPENID, APPID, UNIONID} = cloud.getWXContext()
return {
OPENID,
APPID,
UNIONID,
}
}
复制代码
上传并部署该云函数后,可在小程序中测试调用:
wx.cloud.callFunction({
name: 'test',
complete: res => {
console.log('callFunction test result: ', res)
}
})
复制代码
会在调试器看到输出的 res
为如下结构的对象:
{
"APPID": "xxx",
"OPENID": "yyy",
"UNIONID": "zzz" // 仅在满足 unionId 获取条件时返回
}
复制代码
部分资源配额
分类 | 配额种类 | 额度 |
---|---|---|
存储 | 容量 | 5 GB |
云函数 | 调用次数 | 20 万次 / 月 |
数据库 | 容量 | 2 GB |
IV. 小程序和开发者工具的基本原理
小程序实现原理
运行环境 | 逻辑层 | 渲染层 |
---|---|---|
iOS | JavaScriptCore | WKWebView |
安卓 | X5 JSCore | X5浏览器 |
小程序开发者工具 | NWJS | Chrome WebView |
不太一样的 JS 方言
小程序中的 JavaScript 同浏览器或 NodeJS 中的 JavaScript 都是不相同的:
- 小程序缺少相关的 DOM API 和 BOM API,这导致了 jQuery 等无法运行
- JSCore 的环境同 NodeJS 环境也是不尽相同,所以一些 NPM 的包也无法运行
JSCore
JSCore 是 WebKit 默认内嵌的单线程 JS 引擎,进行词法分析、语法分析以及解释执行等工作
- 词法分析阶段,将源代码分解成 Token 序列
- 对 Token 序列进行语法分析,并生成对应的一棵抽象语法树(AST)
- ByteCode Generator 根据 AST 生成 JSCore 的字节码,完成语法分析
- 用 LLInt 和 JIT 解释执行字节码
双线程模式
- 在传统网页开发中, JS 引擎与 GUI 渲染引擎两个线程是互斥的,所以 JS 执行脚本时间过长会引起页面渲染加载阻塞导致其渲染的不连贯
- 在小程序中,逻辑层和渲染层是分开的,逻辑层运行在 JSCore 中,渲染层用 webview 实现
- 渲染层和逻辑层的通信会经由 Native 中转
- 逻辑层发送网络请求也经由 Native 转发
- 在渲染层,宿主环境会把 WXML 转化成对应的表示树状结构的 JS 对象
- 在逻辑层发生数据变更的时候,通过宿主环境提供的 setData 方法把数据从逻辑层传递到渲染层,形成新的结构 JS 数据对象
- 再经过对比新旧结构 JS 对象的前后差异,把差异应用在原来的 Dom 树上
- 一类事件是“用户在渲染层的行为反馈”,比如点击
- 另一类事件是“组件的部分状态反馈”,比如播放进度变化
- 以上两类渲染层事件抽象后,经过 Native 转发给逻辑层
开发者工具实现原理
- 基于 NW.js,一种 Chromium + Node.js 实现的跨平台桌面打包技术
- 用系统 API 来实现底层模块,使用 React、Redux 等前端技术框架来搭建用户交互层
- 引用了 monaco-editor 等插件实现编辑器功能
- 用 webview 实现预览窗口部分
- 用 webview + chrome 原生调试工具实现调试器
结合官网的介绍,并基于开源的 github.com/cytle/wecha… 项目,一窥相关实现:
预览窗口
预览窗口视图在微信开发者工具上 WebView 是一个 chrome 中的 <webview />
标签。与<iframe />
标签不同的是,<webview/>
标签是采用独立的线程运行的。
- 移动端的 JsCore 是一个单纯的脚本解析器,为此开发者工具做了一个很巧妙的工作,将浏览器的 BOM 对象局部变量化,从而使得在开发阶段就能发现问题。
- 用于模拟小程序逻辑层的
<webview/>
加载的链接是
http://127.0.0.1:9973/appservice/appservice
复制代码
预览窗口逻辑
编辑窗口
编辑器视图 编辑器逻辑 编辑器逻辑 编辑器逻辑调试窗口
调试器逻辑- nw.js 对
<webview/>
提供打开 Chrome Devtools 调试界面的接口,使得开发者工具具备对小程序的逻辑层和渲染层进行调试的能力 - 同时为了方便调试小程序,开发者工具在 Chrome Devtools 的基础上进行扩展和定制
- 通过在 devtoolsWebView 中注入脚本的方式将 Chrome Devtools 的 Element 面板隐藏,同时提供了 Chrome Devtools 插件 WXML 面板
V. 《组队点餐宝》云开发 DEMO 小程序
午饭吃什么?每到此时总是和同事同学意见不统一?来试试这个小程序~
当然选好地方后也可以看看源码,对云函数、云数据库的用法有个直观印象:
VI. 扩展阅读和参考资料
--End--
搜索 fewelife 关注公众号
转载请注明出处