nanachi h5转译方案原理解析

方案初探

nanachi

nanachi是Qunar开发的多端小程序转译框架。使用React语法开发,实现一处编写、多端运行,极大地提升了咱们的开发效率。目前Qunar已经使用该框架成功上线各大小程序、快应用平台,nanachi成为公司小程序开发标准技术框架。html

nanachi官网: rubylouvre.github.io/nanachi/ind…前端

运行方式

npm install nanachi-cli -g # 全局安装nanachi转译器
nanachi init your_project_name # 初始化模板项目
cd your_project_name && npm install
nanachi watch # 编译项目,默认编译微信,其余平台须要传入对应参数,如watch:ali、watch:bu、watch:h5...
复制代码

编译分为build和watch模式,watch模式会自动监听代码变化从新构建。webpack

H5编译的watch模式会在本地启动webpack-dev-server,方便实时调试。git

H5方案意义

相较传统H5方案优点

用nanachi的方式编写React SPA应用,与传统浏览器开发相比,有如下优点:github

  1. 编写一次,多端运行,适配成本极低。
  2. 丰富的组件库,兼容微信的组件实现方式。
  3. 封装了浏览器端的小程序API(如:提示框、打电话、震动、本地存储、网络请求…),功能上与原生体验接近,开发方便。
  4. 不须要关心路由跳转问题,节约开发成本。
  5. 封装好了基础的Webpack打包配置,无特殊需求可实现零配置打包;同时暴露Webpack配置接口,可自由定制。

让nanachi适用于更多场景开发

若是已使用nanachi开发了小程序应用,H5方案适用于如下场景web

  1. 能够快速上线一套与小程序业务逻辑一致的touch端应用,抢占浏览器流量入口。
  2. 小程序平台目前层出不穷,能够经过转出的touch端应用套Webview壳快速抢占某个新小程序平台入口,待nanachi官方支持该平台时,也可快速迁移至原生小程序应用。
  3. 小程序开发须要打开IDE,等待原生代码编译。能够先经过H5方案实现基本样式、功能,最后阶段编译成原生代码适配各平台差别功能,提升开发效率。

技术细节、难点解析

编译时方案

H5方案代码编译过程分为三个阶段:shell

React SPA应用源码编译出Webpack产物的过程大多数前端开发都很熟悉了,这里咱们着重介绍从源码到生成中间产物的过程。

小程序中存在不少标签,在浏览器端没有对应的原生实现,咱们首先要对这些标签进行转译。npm

对一些基础标签,会进行直接的标签替换:小程序

对一些复杂的组件,咱们实现了一套组件库,schnee-ui,用来抹平浏览器和微信原生标签的差别。微信小程序

schnee-ui官网: qunarcorp.github.io/schnee-ui/i… 编译时咱们会自动导入组件依赖:

开发太小程序的同窗知道,小程序分为App、Page、Component三级结构,对于页面(Page)组件,咱们对代码进行以下处理:

dynamicPage是咱们内部实现的高阶组件,负责每一个页面的生命周期钩子调用、标题栏、tab栏的渲染、下拉刷新功能的实现、过场动画等等。

对于App组件,代码处理以下:

在App中挂载PageWrapper组件,这是咱们整个应用的容器,主要职责是渲染页面栈。

运行时方案

抹平API、组件(包括原生titleBar、tabBar)

咱们在浏览器端实现了一套和微信小程序兼容的API,而且同时支持Callback和Promise的方式接收回调信息。

组件的设计方面,咱们也保持和微信小程序写法彻底一致。除了一些基础的按钮、选择器、switch开关等,还包括了一些通用的复杂业务组件,好比城市选择器、轮播图、日历等。

实现了浏览器端没有的标题栏和tab栏:

统一辈子命周期

React方案里缺乏一些小程序端的生命周期,咱们会在浏览器端模拟实现,在特定的时机触发对应的钩子:

页面堆栈管理

小程序的页面堆栈行为是各平台管理的,到浏览器端咱们就须要本身维护一套页面管理方案,同时要和微信端保持一致。 咱们会在内部定义一个__currentPages数组,用来存储页面的React实例,并实现本身的路由方法,管理这些实例。

同时模拟了小程序的最大页面数概念,对微信来讲目前能保持最多10个页面。咱们每次调用navigateTo方法时会检查当前页面栈长度是否达到最大值,达到则先推出数组的第一个元素,再存入新页面实例。

技术难点

路由管理

路由管理的实现过程主要遇到两方面的问题:

  1. 如何更新地址栏

    须要在调用路由方法时同时改变地址栏,对navigateTo咱们调用history.pushState,redirectTo调用history.replaceState方法,实现地址栏的更新

  2. 如何保证调用API返回与浏览器原生返回事件行为一致

    咱们知道浏览器原生返回操做会触发popstate事件,因此能够监听这个事件而后调用咱们内部的API方法,达到行为一致。设计方案以下:

样式做用域

小程序的样式是自然具备局部做用域的,到浏览器端样式会变为全局样式,必然出现样式污染问题,解决方案有如下几种:

  1. 业务自定义命名空间,缺点:工做量大、可靠性低,最早被排除掉。
  2. Css Module方案,传统touch端开发的流行局部样式解决方案,缺点:业务须要修改代码适配,成本高。
  3. Web Component方案,也是微信小程序的局部样式解决方案,优势:无适配问题,业务无感知;缺点:浏览器端有兼容性问题。
  4. 编译时为标签添加特定hash属性(参考VUE scoped样式方案):优势:业务无感知,无兼容性问题。

咱们采起的是最后一种方案,计算样式文件和它对应的js文件共同父级目录的MD5值,做为关联二者的惟一hash,分别添加到jsx标签和style文件的标签选择器上,实现局部样式效果。

总结

nanachi做为多端转译框架,已经成为Qunar小程序的开发标准,其跨端特性极大地提升了开发效率。对H5端的支持也让咱们能够快速上线与小程序功能一致的touch应用。相较传统React开发,咱们维护了与微信高度一致的组件和API,开发者不用再去引入各类第三方组件库来实现一些复杂功能;同时路由行为也由框架层维护,进一步减轻开发负担;最后能够实现零配置打包上线,也支持业务自定义各类Webpack配置,简单灵活。

最后欢迎你们试用nanachi,帮咱们提issue、PR,咱们会第一时间解决或提供支持。

项目地址: github.com/RubyLouvre/…

相关文章
相关标签/搜索