写点什么

基于 TypeScript 的 Weex 优化实践

  • 2020-08-02
  • 本文字数:4274 字

    阅读完需:约 14 分钟

基于 TypeScript 的 Weex 优化实践

一、背景

Weex 作为一种成熟的跨平台程序框架被运用到许多产品中,有赞也不例外。有赞零售移动端团队从 2018 年就开始使用 Weex 构建页面,据不完全统计,有赞零售移动端有超过 300 个页面使用到了 Weex 开发!显然,这是一个巨大的开发工程,同时我们也发现基于 JavaScript 的 Weex 开发给我们带来了诸多痛点:


  • 缺少类型约束,编程时代码提示全凭记忆,要拓展新功能也束手束脚。

  • 手误写错某个变量名,只能在联调、测试阶段才能发现。

  • 面对复杂业务逻辑,代码层面可控性、扩展性较差。

  • 总会遇到 xxxisundefined 的空指针问题。


这些问题我们都在 TypeScript 找到了答案。

二、什么是 TypeScript

TypeScript 是微软开源的编程语言,它建立在 JavaScript 的基础上,是 JavaScript 的超集,可以编译成 JavaScript。它有以下特点:


1.始于 JavaScript,归于 JavaScript


TypeScript 从今天数以百万计的 JavaScript 开发者所熟悉的语法和语义中拓生而来,所使用的是通用的 JavaScript 代码,包括流行的 JavaScript 库,从 JavaScript 代码中调用 TypeScript 代码轻而易举。TypeScript 可以编译出纯净、 简洁的 JavaScript 代码,并能运行在任何支持 ES3 及以上的 JavaScript 引擎中。


2.强大的工具构建


类型允许 JavaScript 开发者在开发 JavaScript 应用程序时使用高效的开发工具和常用操作,比如静态检查和代码重构。类型是可选的,类型推断让一些类型的注释与你的代码的静态验证有很大的不同。类型让你能自主定义软件组件之间的接口和洞察现有 JavaScript 库的行为.


3.进阶的 JavaScript


TypeScript 提供最新的和不断发展的 JavaScript 特性,包括那些来自 ES2015 和未来提案中的特性,比如异步功能和装饰器,以帮助建立健壮的组件。

三、为什么要使用 TypeScript

1. 降低维护成本,提升健壮性、稳定性

1)代码即文档,好的接口、函数定义可直接代替文档,代码可读性更高。


2)静态类型检查,提早发现问题代码。

2. 提高开发效率

1)对代码重构和补全提示友好。


2)多人协作降低沟通成本,不再需要频繁阅读文档或细究实现细节。


3)类型可选,让你在不编写额外代码的情况下获得很多功能。


4)有很多先进的高级特性可以使用。

3. 成熟度高

1)编辑器或 IDE 集成度高。


2)社区庞大,周边工具丰富。


3)最受欢迎的编程语言排行榜中已跃升至第 10 名,话题度高。


4)多个团队全面使用 TypeScript 重构代码(Vue、React 、Angular),甚至连 Facebook 自家的产品(Jest、Yarn 等等)都在从 Flow 向 TypeScript 迁移。


4. 接入成本低

1)几乎没有接入成本,对当前工程改造小。


2)可以和 JavaScript 混合开发、编译成 JavaScript 在各端运行。


3)支持多种工具链。

5. 学习成本低

几乎没有学习成本,移动端各自开发的语言本身就有类型系统,并且 Swift、kotlin 也有可选类型,语法也和 TypeScript 类似。

四、如何使用 TypeScript 进行 Weex 开发

随着 Vue2.x 对 TypeScript 的支持,Weex 也能快速接入 TypeScript。同时 Vue3.0 将使用 TypeScript 重写,重写后的 Vue3.0 更能发挥 TypeScript 的特点。

1.接入 TypeScript

虽然市面上关于 Weex 支持 TypeScript 的资料比较少,但关于 Vue 如何接入 TypeScript 的文章铺天盖地,这里做个简单总结:


  • 添加 TypeScript 依赖,根据所需升级相关依赖或者有影响的包(当使用第三方库时,我们需要引用它的声明文件,才能获得对应的代码补全、接口提示等功能)。

  • ts-loader 可选,如果之前的项目工程对 Babel 依赖比较重,可以保留 babel-loader(Babel>=7)。Babel 已和 TypeScript 官方展开了合作,解决了部分之前不能被正常编译的问题。或者通过使用两个编译器,搭配 ts-loaderbabel-loader 来接入 TypeScript。

  • 添加 tsconfig.json ,并加入相关你需要的自定义配置。

  • 官方对 ESLint 做了支持,提供了解析 TypeScript 代码的编译器,可以把语法树转成 ESLint 所期望对 ESTree,使用 @typescript-eslint 即可。

  • 添加必要的声明文件,Weex 目前还没有官方的声明文件,大家可按需添加。

2.声明文件

Weex 官方目前没有对 TypeScript 提供优秀的支持,需要自行添加声明文件。


比如:


const platform = weex.config.env.platform
复制代码


在 TypeScript 中,编译器并不知道 Weex 是什么东西。这时我们需要对其声明


声明文件必需以 .d.ts 为后缀。一般来说,TypeScript 会解析项目中所有的 *.ts 文件,当然也包含以.d.ts结尾的文件。


例:weex.d.ts


declare interface IWeexGlobal {    config: {        platform: 'Android' | 'iOS' | 'Web'    }}declare const weex: IWeexGlobal
复制代码


Typescript 默认不能识别 .vue 文件,导致在引用时,会提示加载错误。所以需要自己新建一个 .d.ts 声明文件文件添加以下内容。这是为了告诉 Typescript 以 .vue 结尾的导入的任何东西都与 Vue 构造函数本身具有相同的形状。注意引用 vue 组件时需要补全 .vue


例:vue.d.ts


declare module '*.vue' {    import Vue from 'vue'    export default Vue}
复制代码


关于声明文件详细内容,具体可参考官方文档。

3.类组件

要让 TypeScript 正确推断 Vue 组件选项中的类型,需要使用类组件。在 Vue 2.x 中,通常使用基于 Vue Class Component 装饰器来用使用类组件。


Vue Class Component 对 Vue 组件进行了一层封装,让 Vue 组件语法在结合了 TypeScript 语法之后更加扁平化,代码可读性更高。


使用组类组件有以下差异:


  • @Component 修饰符注明了此类为一个 Vue 组件

  • 初始数据可以直接声明为实例的 property

  • 计算属性可以直接使用 getter / setter

  • 组件方法也可以直接声明为实例的方法

  • 所有 Vue 生命周期也可以直接声明为实例方法,但是你不能在实例本身上调用它们。声明自定义方法时,应避免使用这些保留名称

  • 其他接口描述对象可以传递给装饰器函数或者 Vue.extend



其他接口描述对象在类组件的使用:



TypeScript 的类组件和 JavaScript 的接口描述组件导出有些差异:


  • 类组件导出的是 Vue 类

  • 接口描述组件导出的是 ComponentOptions接口


所以在入口文件对 Vue 进行初始化上也会有些区别:


4.装饰器

TypeScript 支持装饰器这一特性,Javascript 里的装饰器目前处在建议征集的第二阶段。若要使用装饰器特性,需要在 tsconfig.json 里启用 experimentalDecorators 编译器选项。装饰器的好处如下:


1)使语法更加扁平化。


2)对业务代码无侵入。


3)解耦业务逻辑、辅助功能逻辑。


除了上节提到的 @ComponentVue Property DecoratorVuex Class 提供了更多的装饰器用于使用。装饰器可以用于修饰类、方法和属性等。

Vue Property Decorator

  • @Prop

  • @PropSync

  • @Model

  • @Watch

  • @Provide

  • @Inject

  • @ProvideReactive

  • @InjectReactive

  • @Emit

  • @Ref

  • @Component (由 vue-class-component 提供)


对常用对 @Prop@Watch 举个例:



关于其他装饰器如何使用,具体参考官方文档。

Vuex Class

  • @State

  • @Getter

  • @Action

  • @Mutation


关于如何使用,具体参考官方文档。

开发工具

1) Visual Studio CodeWeb Storm 都能做到开箱即用,不需要装配额外的插件。


2)对 ZWeex ToolKit 扩展能力,目前已经支持了创建 TypeScript 的页面

五、落地 TypeScript 提升系统稳定性

我们来对之前遇到的问题做个拆解,看看 TypeScript 是如何帮我们解决痛点。

1.减少 Bug

1)类型错误

TypeScript 的类型保护、联合类型、类型推导等特性,可以避免发生低级类型错误问题。比如在开发中约定函数的参数是 number 数字类型,如果使用时不慎使用了 string 类型的参数,那么 IDE 会有 error 警告并会在编译时报错。



2)空指针

TypeScript 会进行严格非空检查可以帮助我们避免空指针问题。


比如函数的参数定义是允许出现空指针的情况,那么在使用这些不安全的参数时,IDE 和编译器都会提醒你这块儿地方注意了,如果没有处理边界会给予提示。




添加了判断空指针进行处理异常边界之后,可以通过编译。


3)原生 module 类型约束

有赞零售使用有近 20 个原生 module,在之前开发过程中因为没有类型约束出现过不少写错 module/方法/参数名、使用错参数类型的情况。使用 TypeScript 的类型声明可以解决这些问题。


举个例子,有以下几个原生 module,我们对其类型声明


declare interface IWeexNativeModules {    foo: {        fun(a: number, b?: string): void    }
foo1: { oops(): void }
foo2: { oops(): void }}
复制代码


使用时,IDE 会有代码补全提示。如果写错 IDE 和编译器同样报错提示。



调用方法和参数时也会有类型约束。



通过使用 TypeScript 有效的避免了类型问题,减少 Bug 量。一篇伦敦大学和微软研究院联合署名的论文中提到:


通过对 Github 上开源项目的公开 Bug 统计发现:15% 的 Bug 都可以通过 TypeScript 来规避。

2.增强架构设计

TypeScript 比 JavaScript 多了接口、抽象类、范型、访问权限等,可以方便的落地架构设计。


面向接口(协议)编程在移动端应用是非常广泛的,使用 TypeScript 之后也可以进行一些架构设计。


之前我们在使用 Weex 进行开发时,往往会把所有逻辑代码往组件内部塞,使得组件后续维护起来非常麻烦。我们引入了和原生一样的规范:增加 Model、Service 层,通过工具自动生成相应目录结构,在开发中得到了非常好的约束。


效果

我们在 Q2 完成了 TypeScript 的迁移,开发效率显著提升、系统稳定性明显提高。


在对供应链单据页模版化的项目中,使用 TypeScript 进行了大范围的重构。我们发现联调期间的沟通显著减少,不需要频繁查阅接口文档,代码可读性更高了,节省了很多 debug 成本。在测试环节仅出现 个位数 的 Bug,发布线上之后也没问题发生。

六、平滑迁移 TypeScript

迁移工程不需要一蹴而就,你可以先用 JSDoc 注释现有的 JavaScript,然后迁移几个文件交由 TypeScript 检查,随着时间的推移,当你的代码库准备好了之后,代码库迁移到 TypeScript 自然就水到渠成了。

参考链接


本文转载自公众号有赞 coder(ID:youzan_coder)。


原文链接


https://mp.weixin.qq.com/s?__biz=MzAxOTY5MDMxNA==&mid=2455761139&idx=1&sn=a4cde112969fb5d3737ca4032bf12a53&chksm=8c6876d6bb1fffc05cb047840c618cb30e105442bd35bd06a765a045dc9698cc9a0f769e943c&scene=27#wechat_redirect


2020-08-02 14:042313

评论 2 条评论

发布
用户头像
巨大反馈
2020-08-02 16:45
回复
坚实的时刻
2020-08-02 16:45
回复
没有更多了
发现更多内容

十一、云原生网络微隔离

穿过生命散发芬芳

5月月更 微隔离

IoT技术的最后决战!百万大奖究竟花落谁家?

华为云开发者联盟

IoT 华为云 iotda NSBD-IOT

Java Core「4」java.util.concurrent 包简介

Samson

学习笔记 5月月更 Java core

没有店面店铺可以做自助洗车吗?

共享电单车厂家

自助洗车加盟 自助洗车店面

百度智能小程序巡检调度方案演进之路

百度Geek说

企业的文档管理策略

小炮

文档管理

末流985,秋招斩获多家大厂offer 经验分享

大数据梦想家

面经分享 大数据开发

数据行业中的建模是什么?

清林情报分析师

数据分析 行业分析 数据建模 业务思维 模型思维

云原生时代,热门监控工具对比与使用场景分析

云智慧AIOps社区

云原生 监控 Grafana Prometheus 监控宝

聚焦无障碍阅读,福昕捐出2000套福昕高级PDF编辑器

联营汇聚

Kube-OVN v1.10.0:新增Windows节点支持,用户自定义子网ACL等10+硬核功能

York

云原生 网络 cni

「v2.4」千呼万唤的图形化编排,来了!

Jianmu

持续集成 低代码 开发工具 开源项目 节点编排

大数据学习必备 | 推荐几个牛X 的 github 项目,助你事半功倍

大数据梦想家

大数据 学习资料 Github'

Scrum实施的8个步骤

爱吃小舅的鱼

又一国际知名律师事务所选择福昕PDF

联营汇聚

Linux 使用 cp 命令强制覆盖功能

AlwaysBeta

Linux 运维

前沿聚焦:2022最受关注的六大技术热词,你都知道吗?

华为云开发者联盟

零代码 NFT 数字人 元宇宙 云边端协同

技术立根,行业立范,发展立本:中国工业互联网的2.0新征程

脑极体

避免惊群以及负载均衡的原理与具体实现

C++后台开发

nginx 负载均衡 后端开发 C++后台开发 惊群

平衡人工智能的性能要求,实现可信AI在银行业务场景的高质量应用

易观分析

人工智能

7 款最棒的开源 React UI 库测评 - 特别针对国内使用场景推荐

蒋川

JavaScript react.js 开源 UI 组件库

6月月更“粽”头戏,大家一起来参与吧!

InfoQ写作社区官方

热门活动 6月月更

PingCAP Clinic 服务:贯穿云上云下的 TiDB 集群诊断服务

PingCAP

开发一个社区网站,只要20分钟?

华为云开发者联盟

ide 敏捷开发 devcloud 网站开发

使用 awk 命令统计文本

程序员小航

后端 awk Linxu

TiDB 查询优化及调优系列(四)查询执行计划的调整及优化原理

PingCAP

为什么穷人越穷,富人越富?

大数据梦想家

程序人生

HDFS 细粒度锁优化,FusionInsight MRS有妙招

华为云开发者联盟

hdfs NameNode 元数据 FusionInsight MRS FGL

英特尔开源项目推动SYCL标准采用,打破单个厂商封闭生态系统

科技之家

eKuiper 1.5.0发布:实现无缝式工业数据采集+边缘流处理

EMQ映云科技

物联网 IoT emq 开源之夏 5月月更

深入 HTTP/3(2)|不那么 Boring 的 SSL

SOFAStack

互联网 TLS HTTP3.0 QUIC协议 HTTP API

基于 TypeScript 的 Weex 优化实践_开源_周佳敏_InfoQ精选文章