写点什么

建信小程序开发工具链原理浅析

  • 2020-12-06
  • 本文字数:4663 字

    阅读完需:约 15 分钟

建信小程序开发工具链原理浅析

《初识建信小程序引擎》一文中我们了解到,建信小程序是一种新的连接用户与服务的开发方式,可以在建信应用内被便捷的获取和传播,同时具备良好的用户体验。一般的开发工具,都会有一个供用户使用的开发工具链。那么,建信小程序的开发工具链的原理又是怎样的呢?本文将会对以上内容进行介绍。


注:本文基于 @jump-mp/cli 的版本为 1.2.6


开发工具链


@jump-mp/cli 的安装和使用方法详见建信小程序开发文档。


在终端运行


`$ jump -h`
复制代码


可以看到 @jump-mp/cli 中提供如下功能:


1. `Usage: jump  [options]`2. 3. `Options:`4. `  **-v, --version**                     output the version number`5. `  **-h, --help**                        display help for command`6. 7. `Commands:`8. `  **init**                              initialize template for jump project`9. `  **build [options]**                   build project to be used in android or ios`10. `  **update**                            update project dependencies to the latest version`11. `  **add [options] **       add npm source for miniproject`12. `  **construct**                         construct installed npm source for miniproject`13. `  **help [command]**                    display help for command`

复制代码


  • init:初始化方法,用于初始化小程序项目和页面、组件;

  • build:用于对建信小程序进行编译打包;

  • update:用于更新建信小程序使用的依赖版本;

  • add:用于添加小程序依赖;

  • construct:用于构建小程序添加的依赖。


脚手架原理


在上一节中,已经介绍了 @jump-mp/cli 的基本功能。本节将对脚手架 @jump-mp/cli 的整体架构和技术选型进行介绍。


现有脚手架技术分析


目前较常用的前端开发脚手架工具有 yoemanvue-cli 等。


yeoman 搭建项目需要提供 yoeman-generatoryoeman-generator 本质上就是有 i 个具备完整文件结构的项目样板,用户需要手动地把这些 generator 下载到本地,然后 yoeman 就会根据这些 generator 自动生成各种不同的项目。


vue-cli 提供了相当丰富的选项和设定功能,但是其本质也是从远程仓库把不同的模版拉取到本地,而并非是“本地生成“的黑科技。


综上,目前脚手架的思路大都是建立不同的样板项目,然后脚手架根据用户指令引用样板项目生成实际项目。样板项目可以内置在脚手架中,也可以部署在远程仓库。


技术选型及架构


为了更好地实现模版定制和功能开发,大前端团队自研了建信小程序脚手架 @jump-mp/cli。脚手架主要使用了以下技术:


  • node.js:整个脚手架工具的根本组成部分。

  • commander: 用于组织和处理命令行的输入。

  • webpack:用于对一些需要编译的文件进行处理。


脚手架的整体架构如下图:



在创建小程序、页面和组件时,小程序的项目、页面和组件的模版(template)都存放在依赖 jump-mp/cli-template 中。每当用户需要创建时,就通过 cli 的命令向 jump-mp/cli-template 中拉取相应的模版并下载到本地。


对于编译、构建等功能,会在后面的小节进行介绍。


最终整个 @jump-mp/cli 的脚手架文件结构如下。


├── bin│   └── index.js├── command│   ├── add.js│   ├── build.js│   ├── create.js│   ├── translate.js│   └── update.js├── node_modules│   └── @jump-mp│       ├── build│       └── cli-template│           ├── component│           ├── page│           └── project└── package.json
复制代码


其中 bin/index.s为入口文件,主要用 commander 来构建命令行。commander 的工作流程如下:



编译器原理


在完成小程序的开发后,需要在项目根目录下运行 jump build [option] 来对小程序进行编译打包。下面将介绍建信小程序打包过程中的编译原理。


小程序引擎


《初识建信小程序引擎》一文中我们了解到,为了提升小程序的运行性能、用户体验,建信小程序采用了双线程模式,将运行环境分为视图层(view 层)和逻辑层(service 层)。其中视图层负责页面展示,逻辑层负责小程序业务逻辑。视图层和逻辑层分别由 2 个线程管理:


  • 视图层的界面使用了 WebView 进行渲染,视图层使用 Vuejs 作为 MVVM 框架;

  • 逻辑层采用 JsCore 线程运行 JavaScript 脚本。


同时,视图层线程和逻辑层线程通信会经由建信客户端(Native 层)做中转,逻辑层发送网络请求也经由 Native 层转发,Native 层也会渲染一些原生的组件、被小程序调用一些原生的 API。


综上,编译器的主要功能是将小程序代码进行编译,将 view 层、service 层、native 层三个部分各自需要的代码进行提取、转换、整合,最终打包成一个可以在建信客户端运行的小程序。


技术选型


编译器主要使用了以下技术:


  • node.js:整个脚手架工具的根本组成部分。

  • gulp:基于流的自动化构建工具。

  • babel相关:用于构建 js 代码的 ast 树、修改 js 代码、编译 js 代码。

  • vue-template-compiler:用于构建 html 代码的 ast 树,修改 html 代码、编译 html 代码。

  • postcss:用于修改、编译 css 代码。

  • webpack:用于对一些需要编译的文件进行处理。


编译器原理


编译器在工作的过程中,会经历预处理、编译、打包三个步骤,具体流程如下:



下面将详细描述编译原理和流程。


(1)mxml—>使用 vue 框架的 html


对于页面/组件的 mxml 页面,编译器做了如下处理:



  • 首先,mxml 会被解析为一颗 ast 抽象语法树

  • 然后,编译器会遍历该 ast 语法树,将组件名转为小程序内置组件名(例:button->mp-button),将建信小程序语法标签转为 vue 语法标签(例:mp:if->v-if)。

  • 最后,遍历该 ast 抽象语法树,将 ast 转为使用 vue 框架html 代码。

  • (2)mcss—>css


  • mcss 转为 css 主要做了设备视图分辨率适配,将 rpx 单位转为 vw


(3)使用 vue 框架的 html—>使用 vue 框架的 page.view.js


在生成了 html 中间态文件“使用 vue 框架的 html” 后,还需要生成一个符合 vue 框架要求的 js 文件,然后将其组合到一个 html 文件(及 page.html)中,该文件才可在使用了 vue 引擎的视图层中被加载,因此我们需要一个这样的 html 文件。举例说明:


jump 小程序:


  • mxml

  • <view>
      <view>{{title}}</view>
      <button bindtap="clickMe">请点击换标题</button>
    </view>
    
  • js

  • Page({
      data: {
        title: 'Hello World',
      },
      //事件处理函数
      clickMe: function() {
          this.setData({
            title: '你好,世界'
          })
      }
    })
    
    
  • 那么转换之后的 vue 页面应该是:


<template>  <mp-view>    <mp-view>{{title}}</mp-view>    <mp-button @click="clickMe">请点击换标题</mp-button>  <mp-view><template><script>export default {  data(){    return {      title: '',    }  }}</script>

复制代码


这里 data 中的变量名不是通过解析 page.js 得到的,因为开发者在编写 page.js 时是没有要求固定格式的,因此无法通过抽象代码树解析的方式拿到 data 的参数,所以这里 data 的变量名是通过解析 html 表达式拿到的。


而没有将 data 中的数据值和 method 方法写到 html 页面中,是因为这部分应由 service 逻辑层处理,view 层只需声明变量名即可。


最终再通过 vue 生成的 html 页面应为:


<html>  <head>......</head>  <body>  ......    <script>      new Vue({        data() {          return {            title:""          }        },        el: "#app",        template:"<template><mp-view><mp-view>{{title}}</mp-view><mp-button @click="clickMe">请点击换标题</mp-button> <mp-view><template>"      });    </script>  </body></html>

复制代码


如要生成上述页面,首先我们需要拿到data中的变量名,使用的方法是,通过解析 html 中的表达式来获得变量名。


然后则是构建 html 页面中的 js 代码,这里使用 babel 去构建一个 js ast 抽象语法树,然后向树中插入 data template 的参数和值。


由于考虑到随着页面功能的增多以及版本的迭代,直接构建目标态代码,在未来版本发生迭代时很可能会导致编译逻辑会跟随修改。为了解决这一问题,我们需要区分出目标态代码的不变部分和可变部分。把不变部分抽象为源对象,把可变部分交由 runtime 运行时框架处理。这样只需要在 rumtime 层做版本迭代而不需要编译器修改。


为了提高加载速度,我们在编译阶段做了预处理,把原本在运行时处理的渲染模版提前展开为真实的虚拟节点树。


所以本步骤整体的工作流程如下图:



最终生成的 page.view.js 应为:


1. `let app = window.$$makeVueComponent({`2. `  data() {`3. `      return {`4. `          title: ""`5. `      };`6. `  },`7. `  el: "#app",`8. `  render: function anonymous() {`9. `    with(this){return _c('mp-view',[_c('mp-view',[_c('mp-view',[_v(_s(title))]),_v(" "),_c('mp-button',{on:{"click":function($event){return __eventHandlerProxy__('clickMe',$event)}}},[_v("请点击换标题")])],1)],1)}`10. `  },`11. `  staticRenderFns: []`12. `  });`13. `new Vue(app);`
复制代码


(4)页面(page)中引入的组件(component)的处理


由于视图 view 层在加载页面时只会去加载该页面的 html,因此需要在编译页面时将页面中引入的组件(component)也编译进 html 中。这里的编译流程如下:



编译器会先读取所编译的 page json 文件,如果 json 文件中引入了组件,则将编译后的组件的 js 加入到 page html 中。然后再去读取改组件的 json 文件,查看改组件是否引入了其他组件,一直递归循环,直至所有组件都被编译进 html 文件为止。对于每个页面重复引入的组件,则只编入一次。


(5)page.js 的编译


在处理需要在 service 逻辑层运行的 page.js 时,我们不会去改变文件的代码,只是对 page.js webpack 做编译打包,然后汇总到 app-service.js 文件中。


构建 npm 依赖


建信小程序支持引入第三方 npm 依赖。这里不再对 npm 的功能进行介绍,可以参考官方 npm 文档。


使用方法


建信小程序引入 npm 依赖,需要添加依赖构建依赖两个步骤。


其中,构建依赖的目的是,将安装在 node_modules 下的依赖进行编译构建,然后生成到项目根目录下的 npm_miniprogram 文件夹下,以供小程序在开发过程中进行引入。


构建原理


在使用 npm 依赖时需要构建依赖,是因为在小程序编译时,无法在未指定路径的情况下将 require node_modules 下的依赖编译进去,所以需要构建这个步骤,将依赖进行预编译,然后统一到一个目录下。


npm 依赖的构建原理如下图所示:



  • 首先会读取项目根目录下的package.json, 如果 devDependencies/dependencies 不为空,则小程序中有使用 npm 依赖,需要构建。

  • node_modules 中找到小程序引入的依赖,查看该依赖是否指明小程序的引入入口(miniprogram_dist 目录),如果有则直接将其复制到 miniprogram_npm 路径下,如果没有则使用 webpack main 入口进行编译,编译结果保存到 miniprogram_npm 路径。

  • 对构建完成的 npm 依赖 重复第一步的步骤,直到所有依赖及依赖的依赖构建完成。


总结


本文主要对建信小程序的开发工具链 @jump-mp/cli 进行了介绍,并对其脚手架开发编译器npm 构建等功能的原理进行了介绍。


欢迎大家试用和使用建信小程序进行开发应用(开发文档详见文末链接),您有任何意见和想法都可以与我们联系,进行相关技术交流。


建信小程序开发文档:http://docs.ccbft.cloud:8888/jump-mp/


本文转载自:金科优源汇(ID:jkyyh2020)

原文链接:建信小程序开发工具链原理浅析


2020-12-06 14:005210

评论

发布
暂无评论
发现更多内容

计算机网络知识,一文搞定

霍格沃兹测试开发学社

自动化测试之模拟器控制

霍格沃兹测试开发学社

IPP swap孵化器丨LP质押挖矿丨算力分红丨系统开发解决方案

V\TG【ch3nguang】

DeFi去中心化系统开发

智定义、易调整,火山引擎DataLeap助力企业轻松实现全流程值班管理

字节跳动数据平台

大数据 数据中台 数据治理 数据安全 企业号 8 月 PK 榜

Excelize 开源基础库 2.8.0 版本正式发布

xuri

开源 Excel Go 语言 Excelize 开源软件供应链

生成式AI驱动的数据中心网络变革

百度开发者中心

AIGC #人工智能 ChatGPT 生成式AI 文心一言

四层负载均衡的NAT模型与DR模型推导 | 京东物流技术团队

京东科技开发者

负载均衡 企业号 8 月 PK 榜 四层负载均衡 NAT模型 DR模型

R语言之处理大型数据集的策略

timerring

R 语言

企业新道路怎么走?火山引擎AB测试助力决策选择

字节跳动数据平台

大数据 ab测试 对比试验 企业号 8 月 PK 榜 数字化增长

WinRAR<6.23 远程代码执行漏洞【Poc公开】(CVE-2023-38831) [有POC]

墨菲安全

网络安全 漏洞分析 WinRAR

推荐三款适合运维小白的网络监测工具

小魏写代码

@Configuration 注解的 Full 模式和 Lite 模式!

江南一点雨

Java spring

生成式AI:开启全新产业机遇

百度开发者中心

智能客服 AIGC #人工智能 文心一言

DEFI应用开发技术|DApp借贷理财挖矿系统源码逻辑

V\TG【ch3nguang】

DeFi去中心化系统开发 质押挖矿

ios ipa包上传需要什么工具

雪奈椰子

ios打包

生成式AI:开启智能科技新纪元

百度开发者中心

#人工智能 生成式AI 文心一言

DBeaverEE for Mac(数据库管理工具) v23.2.0激活版

mac

数据库管理工具 苹果mac Windows软件 DBeaverEE

带你上手基于Pytorch和Transformers的中文NLP训练框架

华为云开发者联盟

人工智能 华为云 大模型 华为云开发者联盟 企业号 8 月 PK 榜

代码质量,众包项目的关键成功因素

知者如C

代码质量

活动回顾|阿里云 Serverless 技术实践营 Serverless +AI 专场

Serverless Devs

阿里云 Serverless 云原生

生成式AI改变业务流程:自动化、优化、高效

百度开发者中心

AIGC #人工智能 ChatGPT 文心一言

区块链量化合约交易所开发,永续合约交易所源码部署示例

V\TG【ch3nguang】

永续合约系统开发 量化合约

网络直播源码UDP协议搭建:为平台注入一份力量

山东布谷科技

软件开发 udp 流媒体技术 网络直播源码 用户数据报协议

生成式AI:游戏产业的未来发展驱动力

百度开发者中心

游戏 #人工智能 生成式AI 文心一言

Docker 搭建Web服务器nginx

霍格沃兹测试开发学社

从原理聊JVM(五):JVM的编译过程和优化手段 | 京东云技术团队

京东科技开发者

Java JVM jvm调优 企业号 8 月 PK 榜 JVM编译过程

解锁安全高效办公——私有化部署的WorkPlus即时通讯软件

WorkPlus

dapp/defi/lp发行代币流动性质押系统项目开发

V\TG【ch3nguang】

代币 DAPP系统开发 质押挖矿

如何有效进行RLHF的数据标注?

Baihai IDP

AI 强化学习 数据标注 RLHF 大语言模型

【VLDB 2023】基于预测的云资源弹性伸缩框架MagicScaler,实现“高QoS,低成本”双丰收

阿里云大数据AI技术

#人工智能

IPQ5018 vs IPQ4019-IPQ4029 is safer, lower power consumption and faster-Difference wifi5 and wifi6?

wifi6-yiyi

wifi6 wifi5

建信小程序开发工具链原理浅析_语言 & 开发_金科优源汇_InfoQ精选文章