专栏首页携程技术干货 | 携程玩乐团队前端多端开发实践

干货 | 携程玩乐团队前端多端开发实践

作者简介

Neo,携程前端开发工程师,负责玩乐前端架构相关开发工作。

一、前言

本文将介绍在具体业务实践中,携程玩乐团队一套代码多端复用的一些实践与经验,希望能给面对同样问题的同学提供些思路和参考。

1.1 背景

在多端开发实践之前,玩乐的前端开发存在如下一些问题:

1)技术栈架构繁杂且陈旧

到2019年2月,整个玩乐前端系统随着不同需求的叠加积累以及其他原因,造成了不同业务线的基础架构,技术栈不一致。当时的页面技术栈包括:.net页面、imvc页面、nextjs页面、jquey页面等,这些不同技术栈的应用从写法、结构、思想等方面都有不少出入。在公司全面推行React技术栈的背景下,诸如 JQuery、.net的前端技术架构显得十分陈旧,各个技术栈之间形成了天然的技术壁垒,不利于代码维护和人员培养。

2)统一产品需求,需要多端多渠道实现

改造前业务团队是按照端和渠道来进行具体的需求划分,如下图所示:

这就意味着前端需要支持国内、海外包括 PC、H5、Hybrid、RN七个(海外版没有Hybrid页面)端的需求代码实现,如果按照改造前的模式,将会有同学为了这个需求更改6个仓库的代码。可以预见,如果这种模式不更正,前端开发将是在来回切换仓库中度过的。

3)发布困难,监控麻烦

正是由于技术架构不统一,所以改造前的应用从打包到发布,其间的流程、打包技术存在很大差异,发布变成了一件手动且不可预期的工作。改造前的页面只是接入了一些公司日志框架,对于一些业务性能指标、细颗粒度的指标并未记录,这也导致了排查问题流程长,效率低下,开发人员只关注完成代码并不知道页面性能等问题。

1.2 举措

针对前端系统存在的问题,我们进行了一些调研和不同框架之间的横向比对。遗憾的是目前并没有一套架构设计可以同时运行在多端,所以我们开始了对多端架构的持续开发与改造的过程,重点措施如下:

1)架构升级

对代码结构和业务逻辑实现做合理划分,在不同层级架构上做合理的事,并且对代码做测试,引入新的日志系统,接入新的打包发布流程。

2)面向组件化的开发策略

尽可能多的将需求逻辑抽象成各个组件,再将这些组件拼接成页面。基于这个角度,我们将组件划分成基础组件和业务组件两个部分。

3)支持PC/H5/RN同时预览

作为多端开发的实践,为了确保开发效率,需要满足一处修改多端同时可见。

二、架构简介

为了能让RN和非RN的代码同时运行,如果按照改造前的做法会出现如下一些问题:

1)由于是一套代码,在发布的时候会出现不断改代码配置然后再去发布的问题;

2)代码逻辑划分不明确,会出现一类逻辑,到处都有的问题;

3)非RN打包中会出现RN的某块代码,从而造成打包代码体积过大和其他不可预知的问题;

针对以上几点,我们对前端架构做了升级,具体措施如下。

为了确保一次修改多端发布,我们按功能模块将仓库划分为四个层级,如下图所示:

1)基础、组件类库

这个仓库提供了页面加载所需要的一些基础服务,比如 React.Component的二次封装、页面信息生成、AJAX,fetch服务,定位服务等;以及一些与业务场景无关的组件,比如:多语言组件、弹框组件、价格组件等。

2)业务组件类库和SSR仓库

业务组件类库为业务开发需要关注的仓库,所有的业务开发调试都是基于这个仓库的。SSR仓库提供几部分功能,包括SEO,SSR会读取业务组件仓管内不同页面的生命周期,从而在不同的页面内生成不同的SEO内容,以下为页面生命周期函数的逻辑,其中data为服务端渲染的数据:

路由生成,这部分通过配置文件完成,具体配置文件内容如下:

  • IS_TRIP、IS_CTRIP、IS_ONLINE、IS_H5用于指定页面属性,为false则渲染的时候不会生成该配置的页面;
  • PATH:用于指定页面路由;
  • CHILDREN:用于指定页面的子页面,用于SPA应用;
  • ALIA:非必传,默认为页面文件名称,用于获取多语言服务;

配合SSR仓库,业务组件类库可以实现本地服务端渲染开发。

3)工程化仓库

这个仓库的提供的服务主要包括:

● init 安装所有依赖,可以支持多版本的RN依赖

● watch 热更新

● dev 能同时运行crn、h5、online

● ares 集成ares平台打包静态资源

● precommit 提交前自动化review代码规范

● publish 自动化发布nodejs资源

4)发布仓库

发布所依赖的仓库必定包含所有发布所用到的资源,包括代码和配置,之前的一贯做法是把前后端所涉及到的代码和配置都统一放到一个仓库内进行发布,但是在多端统一的背景下并不适用。这种场景下代码应当只有一套,变化的只有配置文件,结果就是开发仓库只有一个,而发布仓库有多个,发布仓库被架空,里面只发布配置,下图为一个发布仓库的目录结构:

其中 app.config.js 为应用配置信息,app.js为入口文件,package.json为发布所依赖资源,其配置也很简单,如下图所示:

经过如上的仓库拆分,我们能够让开发者只专注于业务组件的开发,其余的基础服务功能都能做到在一次开发,稳定使用的同时完成多端的同时开发和发布。

三、具体措施

由于是面向组件化的开发策略,下面简单介绍下组件多端开发的一些细节与实现:

3.1 服务和API封装

这部分主要针对目前所要接入的第三方组件,包括多语言组件、头尾组件、locale组件等。在定制API和上下文参数的时候,我们尽量向上扩展API。

比方说,我们的代码内都不允许直接取中文,所有取文案的地方都是使用封装的translate组件去拿对应文案。这样的好处是,在使用、解释层面ctrip和trip保持了统一,另一方面也为以后ctrip可能存在文案走配置服务做了铺垫,其他服务和组件API的封装也遵循这个原则。

3.2 代码职责划分

我们遵循约定大于配置的原则,以单个页面为例,以下为页面的一些约定配置:

  • fetch:这一层负责页面的网络请求获取,在做SSR渲染的时候,代码会以这个文件入口获取页面所需要的数据,并以props的形式传到页面内;
  • view:这一层用来描述不同平台的视图展示,不通入口文件的UI结构基本一致,不包括任何的非UI展示逻辑;
  • fomat:重新组装从restful下发的数据,经过这一层验证和转换后,后续逻辑都是即拿即用;
  • action:这一层是多端统一开发的关键,所有的页面非UI展示逻辑都需要写在这里;
  • style:这一层配合view层决定了页面具体的展示样子,但和正常开发不同,这部分的模块不需要手动引入,具体做法后面会介绍。

经过以上的约定划分,我们的开发模式变成了开发人员拿到需求,先研究三端的view层代码结构,确定出View的大致结构,然后先按H5的逻辑开发一套action和与之匹配的H5View。然后再在此基础上做加法,去书写RN的view,PC的view绝大多数情况下可以通过结构和样式抹平差异,只需要在pc.scss去书写差异化的css即可。

3.3 动态引入样式

由于PC和H5页面大多数情况下只需要通过样式就可以做到多端实践,所以在多数情况下并没有index.pc.tsx和index.h5.tsx,只有一个公用的index.tsx,所以我们不能手动去引入平台样式。

我们做了这样的处理,一是对单位做换算,.scss书写的主单位还是px,由于某些原因我们在H5上的展示单位是rem,所以在打包的after-emit阶段,通过插件把px换算成rem;二是在打包的buildModule阶段,动态的将页面依赖的css放进css依赖树,从而实现动态打包效果。如下为实现代码:

3.4 运行时注入依赖

在做前后端同构的时候,以fetch模块为例,假设只是简单的判断前端用前端的ajax模块,服务端用服务端的request模块,逻辑看起来没问题。但是事实上如果在打包逻辑上没有做比较复杂的改进,那么是不可能打包成功的。

所以通常的做法,是在逻辑中先声明一个为空的变量,在运行时初始化这个变量,那么在代码执行到该处逻辑变的有意义,而打包由于是静态检测所以并不会把任何不需要的代码打进包内。这里在处理RN模块和正常的H5模块的时候也采用类似的技术:

1)我们会在有RN模块的场景下声明一个rn-polyfill.ts,大致内容如下:

2)在index.rn.ts中对变量赋值:

3)在我们的初始化RN页面(比如index.ios.js)中引入 index.rn.ts。

这样的话,我们就实现了模块打包的分离。

四、结语

由于篇幅原因,其他模块(测试、日志监控等)的介绍这里就不进行了。

先介绍下改进后的效果,组内成员除开业务逻辑整理,可以做到无缝替换开发;和之前开发模式对比,同一个需求多端完成时间,节省了近四成。目前框架功能依旧在不断地迭代和更新,近期希望能消除view和style层需要同时书写的情况,从而让开发迭代更加效率和速度。

本文分享自微信公众号 - 携程技术中心(ctriptech),作者:Neo

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-04-30

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 干货 | 如何一步步打造基于React的移动端SPA框架

    作者简介 喻珍祥,携程港澳研发高级经理,2004年接触互联网开发,见证前端开发从美工到全栈开发的全过程。2014年加入携程,主要负责永安旅游APP移动前端架构和...

    携程技术
  • 干货 | 携程 Trip.com App 首页动态化探索

    通过梳理场景和边界使得目标清晰。我们需要一个跨平台支持动态性并且高性能 UI 渲染框架。

    携程技术
  • 干货 | 携程火车票Rematch框架实践

    本文主要介绍携程火车票模块在进行新业务开发和老代码重构时,使用rematch状态管理框架的实践经验总结,包括在过程中暴露出来的一系列问题以及相应的解决方案。

    携程技术
  • Fabric远程自动化

    运行结果: Hello world! Done. fab -f test.py hello (非默认fabfile.py需要指定)

    以谁为师
  • 智能爬虫框架

    爬虫应用的广泛,例如搜索引擎、采集数据、广告过滤、数据分析等。当我们对少数网站内容进行爬取时写多个爬虫还是有可能的,但是对于需要爬取多个网站内容的项目来说是不可...

    喵叔
  • Nginx的优化配置

    Nginx相关的内容有点延迟,趁着今天有空就给大家整理完,本篇文章来给大家把Nginx我们在工作中常用的配置来给大家分享下,希望能对大家有所帮助。

    用户4919348
  • 小程序开发总结03 - 数据传递与缓存

    和H5不同,元素上绑定事件只能传入事件名,不能直接传参,需用通过dataset传参

    CS逍遥剑仙
  • 机器学习的第一步:先学会这6种常用算法

    【IT168 资讯】机器学习领域不乏算法,但众多的算法中什么是最重要的?哪种是最适合您使用的?哪些又是互补的?使用选定资源的最佳顺序是什么?今天笔者就带大家一起...

    企鹅号小编
  • Java|Lexer分析报告

    rules是一个数组,数组里面是单个对象,然后利用utils的some方法将rules数组里的每一项的regex放进去判断是否满足条件。

    算法与编程之美
  • Vue 项目里戳中你痛点的问题及解决办法(下)

    作者:愣锤 https://juejin.im/post/5b174de8f265da6e410e0b4e

    Nealyang

扫码关注云+社区

领取腾讯云代金券