1 部署微信小程序示例源码
通过开始 | 微信开放文档指引,申请微信小程序账号、安装开发者工具,就可以在开放文档的帮助下,进行微信小程序开发了。在了解微信小程序的运行的基础逻辑和框架后,就可以学习微信小程序实例源码了 。该源码的git地址为:https://github.com/wechat-miniprogram/miniprogram-demo。根据超级完整的 Git的下载、安装、配置与使用 以及命令_git下载-CSDN博客的相关内容,安装git工具下载微信小程序实例源码。由于该源码是通过npm安装的,因此要在机器上部署npm环境。通过安装Node.js来部署npm环境,安装方法见Node.js安装与配置(详细步骤)_nodejs安装及环境配置-CSDN博客。至此便可以按照示例跑不起来的几个问题,搞了几个小时,终于成功启动 · Issue #125 · wechat-miniprogram/miniprogram-demo · GitHub
的相关提示,完成微信小程序实例源码在机器上的部署了。
2 微信小程序示例源码的安装逻辑
在miniprogram-demo目录下运行npm run init --legacy-peer-deps时,npm执行miniprogram-demo目录下的package.json文件中的scripts字段中的init字段对应的语句。
"scripts": {
"init": "npm run sync && cd cloudfunctions/ && npm i --production && cd ../miniprogram/ && npm i --production",
"lint": "eslint .",
"wxss:transform-vars": "gulp transform-css-vars",
"sync": "git submodule update --init --recursive",
"pull": "git submodule foreach --recursive git pull origin",
"gco": "git submodule foreach --recursive git checkout"
}
由于nmp运行时要建立Shell,所以执行的语句遵循Shell规则。需要说明,&&表示顺序执行(详见npm scripts(npm 脚本)-CSDN博客),所以Shell执行的语句是这样的。
npm run sync
cd cloudfunctions/
npm i --production
cd ../miniprogram/
npm i --production
2.1 运行sync字段对应的语句
git submodule update --init --recursive
下载.gitmodules文件url指定的包(git submodule的用法详见git:git modules_.gitmodules-CSDN博客和git创建本地仓库的三种方法-CSDN博客),这里下载和更新在miniprogram/packageSkylineExamples目录下的examples目录包。
[submodule "miniprogram/packageSkylineExamples"]
path = miniprogram/packageSkylineExamples
url = https://github.com/wechat-miniprogram/awesome-skyline.git
2.2 运行cd cloudfunctions/
将当前目录定位到cloudfunctions目录。
2.3 运行npm i --production
下载dependencies对象中指定的所有包。这里的包其包名为jest,版本为>=26.6.3,<27.0.0。(参数production的含义见npm install production 参数 devDependencies_npm install --production-CSDN博客,npm安装包版本内容见npm安装依赖(dependency)版本号及更新规则 - 知乎,npm i的工作原理见npm安装包原理_npm安装的原理-CSDN博客)
"dependencies": {
"jest": "^26.6.3"
}
由于该目录下无package.json文件,于是寻找其父目录,在父目录及项目的根目录下找到package.json文件,因此在该目录下创建目录node_modules,将jest包及其依赖的包安装在该目录下。(寻找package.json文件的顺序见)
2.4 运行cd ../miniprogram/
将当前目录定位到miniprogram目录。
2.5 运行npm i --production
下载dependencies对象中指定的所有包。安装下图中的4个包及其依赖包。
"dependencies": {
"miniprogram-barrage": "^1.1.0",
"miniprogram-recycle-view": "^0.1.5",
"wxml-to-canvas": "^1.1.1",
"threejs-miniprogram": "0.0.3"
}
2.6 构建npm环境
小程序有自己的一套npm运用机制,所以在小程序开发工具中,需要构建npm环境。详见npm 支持 | 微信开放文档,注意该文档中指出的miniprogramRoot在文件project.config.json中进行配置。如果此时在目录miniprogram下生成了目录miniprogram_npm,表示已完成了npm环境的构建。
至此,微信小程序示例源码安装结束,可以运行了。
3 分析微信小程序实例源码
3.1 微信小程序实例源码的包结构
3.1.1 cloudfunctions
目录cloudfunctions是云函数的主目录,目录miniprogram是小程序的主目录,分别在文件project.config.json中的对象cloudfunctionRoot、miniprogramRoot指定。
3.1.2 test
目录test下只有1个文件index.spec.js,写了一段自动化测试小程序的代码。详细介绍见小程序自动化测试的示例代码_小程序上线代码测试-CSDN博客。
3.1.3 .eslintrc.js和.eslintignore
文件.eslintrc.js和.eslintignore是代码检测工具ESLint的部分,ESLint的介绍及用法见ESLint 简介-CSDN博客。
3.1.4 .gitignore
文件.gitignore配置在git时不提交的文件,其用法见gitignore简单入门教程_gitignore怎么用-CSDN博客。
3.1.5 .gitmodules
文件.gitmodules配置git子库,在前面做过说明。文件gulpfile.js是运用gulp工具从计算CSS变量值、删除:root选择文档的根元素等方面优化该文件中gulp.src函数变量指定的wxss文件,关于gulp的用法见gulp 使用教程及步骤_lgulp使用教程-CSDN博客、gulp-postcss的用法见gulp-postcss_PostCSS快速入门指南:Gulp设置-CSDN博客、postcss-css-variables的用法见推荐一款神奇的工具:PostCSS CSS 变量-CSDN博客、gulp-rename的用法见Gulp学习--rename重命名-CSDN博客、gulp-replace的用法见使用`gulp-replace`: 强大的Gulp插件,让文本替换变得更简单-CSDN博客、gulp-if的用法见gulp:条件语句插件——gulp-if_gulp if-CSDN博客、gulp-ignore的用法见npm 包 gulp-ignore 使用教程-JavaScript中文网-JavaScript教程资源分享门户。
3.1.6 package.json
文件package.json是项目的npm配置文件,package-lock.json锁定该配置文件中模块的版本号(可参考package-lock.json的作用-CSDN博客理解),目录node_modules中包含上述通过npm安装的包集合。
3.1.7 project.config.json和project.private.config.json
文件project.config.json和project.private.config.json是微信小程序的配置文件,其介绍见项目配置文件 | 微信开放文档。
3.1.8 sitemap.json
文件sitemap.json配置了允许通过微信搜索小程序,其介绍见sitemap 配置 | 微信开放文档。
3.2 小程序的主目录miniprogram
微信小程序在文件app.json中进行全局配置,按照页面、分包、自定义组件等多种方式组织项目文件。页面在小程序启动时加载,目录page包含了各页面的配置信息,其子目录进一步对应各界面的配置。分包需要时才加载,以单个目录的形式存放在主目录miniprogram下。自定义组件一般放在主目录miniprogram下的component目录下。页面、分包、自定义组件目录中一般都包括index.wxml、index.wxss、index.json、index.js4个重要文件。微信小程序的逻辑和视图层相分离,index.wxml可理解成html,index.wxss可理解成css,index.json为页面属性的配置文件,这三个文件都属于视图层,index.js为页面逻辑,属于逻辑层。
3.2.1 app.json
3.2.1.1 pages
page对象为一个包含5个元素的数组,数组各元素的值为各页面的目录位置。小程序根据该位置信息加载页面。
3.2.1.2 usingComponents
usingComponents对象为自定义组件,key值为组件名mp-navigation-bar,value值为组件的位置/component/navigation-bar/navigation-bar。
3.2.1.3 subpackages
subpackages对象配置小程序所有的分包信息,为一个对象数组。各元素的root值为分包的根目录,pages值为一个数组,配置该分包的页面路径。这里有7个分包:packageComponent、packageAPI、packageCloud、packageExtend、packageSkyline、packageSkylineExamples、packageXRFrame。各分包配置了页面路径,由于页面较多,在此举例分包packageSkyline,它包括7张页面,其页面路径如下图所示。
3.2.1.4 preloadRule
preloadRuled对象配置小程序在什么页面开始加载分包,对象中的key值为页面路径,value值包含packages和network,前者为分包名,后者指出在什么网络下(值为all表示不限制网络,为wifi表示wifi网络)加载。
小程序实例配置了位于如下4个页面时加载分包:在page/component/index页面时,加载分包packageComponent;在page/API/index页面时,加载分包packageAPI;在page/cloud/index页面时,加载分包packageCloud;在page/extend/index页面时,加载分包packageExtend。以上加载都不限制网络。
3.2.1.5 window
window对象的键值对设置小程序的状态栏、导航条、标题、窗口背景色。小程序实例配有4个key值:navigationBarTextStyle、navigationBarTitleText、navigationBarBackgroundColor、backgroundColor,以此表示导航栏标题、状态栏的颜色,导航栏标题,导航栏背景颜色,窗口的背景色。除key值navigationBarTitleText对应的value值为无符号的字符外,其余3个key值对应的value值均以@符号开头。
"window": {
"navigationBarTextStyle": "@navigationBarTextStyle",
"navigationBarTitleText": "演示",
"navigationBarBackgroundColor": "@navigationBarBackgroundColor",
"backgroundColor": "@backgroundColor"
},
@用于配置手机在处于明亮和深暗两种模式下,小程序窗口展示的不同状态。要启用此功能,需要在app.json中将darkmode值设置为true和设置themeLocation值用来指示配置文件的位置。小程序实例配置样式的文件名为demo.theme.json。
"themeLocation": "demo.theme.json",
"darkmode": true,
demo.theme.json有light和dark两个key值,且在key中定义了一些变量,用来表示小程序在明亮和深暗两种模式下的样式。这些变量可在文件app.json中以@+变量的形式使用。回到window对象的配置,navigationBarTextStyle的值在明亮模式时为black,在深暗模式时为white;navigationBarBackgroundColor的值在明亮模式时为#F7F7F7,在深暗模式时为#1F1F1F;backgroundColor的值在明亮模式时为#F7F7F7,在深暗模式时为#1F1F1F。
{
"light": {
"navigationBarTextStyle": "black",
"navigationBarBackgroundColor": "#F7F7F7",
"backgroundColor": "#F7F7F7",
"tabBarColor": "#7A7E83",
"tabBarSelectedColor": "#3cc51f",
"tabBarBorderStyle": "black",
"tabBarBackgroundColor": "#F7F7F7",
"iconPathComponent": "image/icon_component.png",
"selectedIconPathComponent": "image/icon_component_HL.png",
"iconPathAPI": "image/icon_API.png",
"selectedIconPathAPI": "image/icon_API_HL.png",
"iconPathCloud": "image/icon_cloud.png",
"selectedIconPathCloud": "image/icon_cloud_HL.png",
"backgroundTextStyle": "dark"
},
"dark": {
"navigationBarTextStyle": "white",
"navigationBarBackgroundColor": "#1F1F1F",
"backgroundColor": "#1F1F1F",
"tabBarColor": "#FFFFFF",
"tabBarSelectedColor": "#51A937",
"tabBarBorderStyle": "white",
"tabBarBackgroundColor": "#1F1F1F",
"iconPathComponent": "image/icon_component_dark.png",
"selectedIconPathComponent": "image/icon_component_HL.png",
"iconPathAPI": "image/icon_API_dark.png",
"selectedIconPathAPI": "image/icon_API_HL.png",
"iconPathCloud": "image/icon_cloud_dark.png",
"selectedIconPathCloud": "image/icon_cloud_HL.png",
"backgroundTextStyle": "light"
}
}
3.2.1.6 tabBar
如果小程序是一个多 tab 应用,则要通过tabBar对象配置小程序的tab页面。小程序实例配置了color、selectedColor、borderStyle、backgroundColor、list共5个键值对,依次表示tab 上文字的默认颜色、tab 上文字被选中时的颜色、tabBar上边框的颜色、tab 的背景色、tab 的列表。前4个键的值都以@开头,如上所述在demo.theme.json中进行配置。list 为对象数组,元素个数在 2到5个之间。每个对象有4个键值对,分别为:pagePath、text、iconPath、selectedIconPath,依次表示页面路径、tab 上按钮文字、图片路径、选中时的图片路径。小程序实例有4个tabBar,在其上显示的文字依次为组件、交互动画、接口、云开发,路径依次为page/component/index、page/animation/index、page/API/index、page/cloud/index,图片路径在明亮和深暗模式下不同,在demo.theme.json中配置。
"tabBar": {
"color": "@tabBarColor",
"selectedColor": "@tabBarSelectedColor",
"borderStyle": "@tabBarBorderStyle",
"backgroundColor": "@tabBarBackgroundColor",
"list": [
{
"pagePath": "page/component/index",
"iconPath": "@iconPathComponent",
"selectedIconPath": "@selectedIconPathComponent",
"text": "组件"
},
{
"pagePath": "page/animation/index",
"iconPath": "@iconPathComponent",
"selectedIconPath": "@selectedIconPathComponent",
"text": "交互动画"
},
{
"pagePath": "page/API/index",
"iconPath": "@iconPathAPI",
"selectedIconPath": "@selectedIconPathAPI",
"text": "接口"
},
{
"pagePath": "page/cloud/index",
"iconPath": "@iconPathCloud",
"selectedIconPath": "@selectedIconPathCloud",
"text": "云开发"
}
]
},
3.2.1.7 networkTimeout
"networkTimeout": {
"request": 10000,
"connectSocket": 10000,
"uploadFile": 10000,
"downloadFile": 10000
},
networkTimeout键值对配置各类网络请求的超时时间,单位均为毫秒。小程序实例将请求超时request、连接超时connectSocket、上传文件超时uploadFile、下载文件超时downloadFile均设置为10s。
3.2.1.8 workers
"workers": "workers",
workers键值对配置异步处理的任务。异步处理的任务可以放置于 Worker 中运行,待运行结束后,再把结果返回到小程序主线程。Worker 运行于一个单独的全局上下文与线程中,不能直接调用主线程的方法。workers的值表示异步任务代码放置的目录,在该目录下的所有 JS 代码最终将被打包成一个 JS 文件。小程序实例的Worker任务位于workers目录下。
3.2.1.9 其他键值对
"debug": false,
"style": "v2",
"permission": {
"scope.userLocation": {
"desc": "你的位置信息将用于小程序位置接口的效果展示"
}
},
"cloud": true,
"sitemapLocation": "sitemap.json",
"themeLocation": "demo.theme.json",
"darkmode": true,
"resizable": true,
"useExtendedLib": {
"weui": "latest"
},
"frameset": true,
"requiredBackgroundModes": [
"audio",
"location"
],
"requiredPrivateInfos": [
"getLocation",
"chooseLocation",
"chooseAddress"
],
"embeddedAppIdList": [
"wxfdcee92a299bcaf1"
],
"lazyCodeLoading": "requiredComponents",
"__lazyCodeLoadingChunk": true,
"rendererOptions": {
"skyline": {
"defaultDisplayBlock": true,
"defaultContentBox": true,
"disableABTest": true,
"sdkVersionBegin": "3.0.0",
"sdkVersionEnd": "15.255.255"
}
},
"renderer": "skyline",
"componentFramework": "glass-easel",
"appBar": {}
debug键值对配置在开发者工具的控制台面板是否以 info
的形式显示调试信息。小程序实例不配置调试信息。sytle键值对配置是否启用新版的组件样式,如果值为v2,则启用新版组件样式。小程序实例启用新版组件样式。permission键值对配置小程序接口权限,其中属性scope.userLocation配置获取位置的权限,desc对象描述获取权限时界面弹出的信息。cloud键值对配置小程序是否为云开发模式,实例为云开发模式。sitemapLocation键值对指明sitemap.json的位置,默认为 位置在 app.json 同级目录下名字的文件。
sitemap.json文件配置是否允许通过微信搜索小程序。json文件中的rules 配置项指定了索引规则,实例中对象action配置是否允许索引("allow"为允许、"disallow"为不允许),page配置允许或者不允许索引的页面,为*表示所有页面。
{
"desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",
"rules": [{
"action": "allow",
"page": "*"
}]
}
themeLocation、darkmode在上文已经描述。resizable键值对配置小程序是否支持用户任意改变窗口大小,小程序实例允许用户改变窗口大小。useExtendedLib键值对配置需要引用的扩展库,包括kbone和weui,配置后相当于引入了对应扩展库相关的最新版本的 npm 包。kbone中文名称为多端开发框架,它是在小程序中模拟浏览器的环境,weui为微信组件库,它是一套基于样式库weui-wxss开发的小程序扩展组件库,UI组件同微信客户端的一样。小程序实例用的是这个组件库。
requiredBackgroundModes键值对配置后台运行的能力,类型为数组。小程序实例后台可以运行audio(音乐播放)和location(定位)。requiredPrivateInfos键值对配置需要使用的地理位置相关接口,类型为数组。小程序实例需要使用的包括:getLocation(获取精确地理位置)、chooseLocation(打开地图选择位置)、chooseAddress(获取用户地址信息)。embeddedAppIdList键值对配置小程序可以以半屏的形式打开其他小程序,实例配置为可以打开腾讯公益小程序。
lazyCodeLoading值为requiredComponents,配置小程序为按需注入页面资源。如果启用按需注入后,小程序仅注入当前访问页面所需的自定义组件和页面代码。未访问的页面、当前页面未声明的自定义组件不会被加载和初始化,对应代码文件将不被执行。页面 JSON 配置中定义的所有组件和 app.json 中usingComponents配置的全局自定义组件,都会被视为页面的依赖并进行注入和加载。
renderer键值对配置小程序是采用WebView架构还是Skyline架构。前者就是传统的Web页面渲染,它的JS 逻辑、DOM 树创建、CSS 解析、样式计算、Layout、Paint (Composite) 都在同一线程运行,这样过多的 JS 逻辑可能阻塞渲染,导致界面卡顿。后者创建了一条渲染线程来负责 Layout, Composite 和 Paint 等渲染任务,而在另一个线程中负责 JS 逻辑、DOM 树的运行,这种架构便是小程序采用的双线程模型的架构。小程序实例配置为Skyline架构。
rendererOptions键值对配置小程序如何用skyline组件进行渲染。由于Skyline组件中的wxs代码运行在 JS 线程,事件产生在 UI 线程,交互动画会有较大的异步延迟,为了提升小程序交互体验的效果,小程序增加了一批手势组件,避免将监听touch事件传递到 JS 线程中。skyline渲染页面元素的布局方式默认为 flex 布局和border-box模型,小程序实例通过设置defaultDisplayBlock、defaultContentBox将页面元素的布局方式切换为block布局和content-box盒模型。skyline组件默认以AB测试发布,若经过充分测试后,可配置disableABTest进行灰度方式发布。小程序实例便是如此,sdkVersionBegin和sdkVersionEnd分别表示发布的最低版本和最终版本,最终版本填最大值,否则之后的新版本会不生效。一篇文章理解AB测试和灰度发布-腾讯云开发者社区-腾讯云对AB测试和灰度发布进行了讲解。
componentFramework键值对配置小程序的组件架构。小程序实例采用的是glass-easel架构,这是一个新的组件框架,是对旧版组件框架exparser的一个重写,拥有比旧版组件框架更好的性能和更多的特性。
3.2.2 自定义组件mp-navigation-bar
3.2.3 Page元素
小程序实例有4个Page元素,分别是:组件、交互动画、接口、云开发。
3.2.2.1 组件页面page/component/index
在component目录下包括1个目录resources和4个文件:index.js,index.json,index.wxml,index.wxss。
3.2.2.1.1 index.wxml
如前所述,这是页面的配置文件,可理解成web开发的html文件。该配置包含两个组件:mp-navigation-bar和scroll-view。前者在app.json中进行了配置,后者为小程序内置组件。