集团主站
欢迎来到成都达内官方网站!达内—美国上市公司 亿元级外企IT培训企业!
成都it培训哪家好
成都it培训哪家好
全国服务监督电话:15023458194  |   联系客服   |
当前位置:主页 > 培训课程 > web前端 >

成都前端学习路线:你需要了解需要了解的前端SDK开发技巧

发布者: 成都前端培训     浏览次数:     发布时间:2018-08-08 10:01:29

作为一个SDK,我们的目标是让使用者能够减少查看文档的时间,所以我们需要提供一些类型的检查和智能提示,一般我们的做法是提供JsDoc,大部分编辑器可以提供快捷生成JsDoc的方式,...

  成都前端学习路线:你需要了解需要了解的前端SDK开发技巧

  正文从这开始~

  最近在做公司内部的一个的一个SDK的重构,这里总结一些经验分享给大家。

  类型检查和智能提示

  作为一个SDK,我们的目标是让使用者能够减少查看文档的时间,所以我们需要提供一些类型的检查和智能提示,一般我们的做法是提供JsDoc,大部分编辑器可以提供快捷生成JsDoc的方式,我们比较常用的vscode可以使用Document This 。

  成都前端学习路线

  另一种做法是使用Flow或者TypeScript,选择TypeScript的主要原因是自动生成的JsDoc比较原始,我们仍然需要在上面进行编辑,所以JsDoc维护和代码开发是脱离的,往往会出现代码更新了,JsDoc忘记更新的情况。

  除此之外开发过程中我们无法享受到类型检查等对SDK开发比较重要的特性,TypeScript可以让我们减少犯错,减少调试的时间,另一方面这次开发的SDK在提供出去的时候就会进行一次相对简单的压缩,保证引入后的体积,所以会希望压缩掉JsDoc,而TypeScript可以通过在tsconfig.json中将declaration设置为true单独的d.ts文件。

  一个带提示的SDK:

  成都前端学习路线

  最后,对于开发同学来说,就算不使用TypeScript,也强烈建议使用vscode提供//@ts-check 注解,它会通过一些类型推导来检查你的代码的正确性,可以减少很多开发过程中的bug。

  还有一个小技巧,如果你使用的库没有提供智能提示,你可以通过NPM/yarn的-D安装@types/{pkgname},这样你开发过程中就能够享受到vscode提供的智能提示,而-D安装到devDependencies中,也不会增加你在构建时的代码体积。

  接口

  既然提到了TypeScript,就提一下TypeScript的语法,基础类型没有必要赘述,而一些曾经的高级语法现在ES6也都能支持,这里提几点常用但是JavaScript开发者不太习惯使用的语法。

  很多人在开始使用TypeScript的时候,会很迷恋使用any或者默认的any,推荐在开发中打开tsconfig中的strict和noImplicitAny来保证尽量少的any使用,要知道,滥用any就等于你的类型检查并没有实质效果。

  对一些暂时不能确定内容的对象的类型,可以使用{[key: string]: any},而不要直接使用any,后期可以慢慢扩展这个接口直到完全消除any,同时TypeScript的类型支持继承,在开发过程中,可以拆解接口,利用组合继承的方式减少重复定义。

  但是接口也会带来一个小痛点,目前vscode的智能提醒不能很好的对应到接口,当你输入到对应变量的时候,虽然会高亮,但是高亮的也只是一个定义了名字的接口。没有办法直接看到接口里定义了什么。但是当你输入了接口里面定义的key的部分时,vscode会给你完整key的提示。虽然这对开发过程中有一点不够友好,但是vscode开发团队表示这是他们故意设计的,所以在API参数上可以选择将一些必要(重要)参数用基础类型直接使用,而将一些配置放入一个定义为接口的对象中。

  枚举

  你有在代码中使用过:

  const Platform = {

  ios: 0,

  android: 1

  }

  那你在TypeScript中就应该使用枚举:

  enum Platform {

  ios,

  android}

  这样在函数中你就可以为某个参数设置类型为number,然后传入Platform.ios这样,枚举可以增加代码的维护性,它可以利用智能提示保证你输入的正确,不再会出现魔数(magic number)。相对于对象,它保证了输入的类型(你定义的对象可能某一天不再只有number类型的value),不再需要额外的类型判断。

  装饰器

  对于装饰器其实很多开发者既熟悉又陌生,在redux,mobx比较流行的现在,在代码中出现装饰器的调用已经很普遍,但是大多数开发者并没有将自己代码逻辑抽成装饰器的习惯。

  比如在这个SDK的开发中,我们需要提供一些facade来兼容不同的平台(iOS, Android或者Web),而这个facade会通过插件的形式让开发者自己注册,SDK会维护一个注入后的对象,常规的使用方法是到了使用函数后判断环境再判断对象中有没有想有的插件,有就使用插件。

  实际来看,插件就是一个拦截器,我们只要阻止真正的函数运行就可以,大概的逻辑是这样的:

  export function facade(env: number) { return function( target: object, name: string, descriptor: TypedPropertyDescriptor ) { let originalMethod = descriptor.value; let method;

  return { ...descriptor, value(...args: any[]): any { let [arg] = args; let { param, success, failure, polyfill } = arg; // 这部分可以自定义 if ((method = polyfill[env])) { method.use(param, success, failure); return; } originalMethod.apply(this, args); } }; };}

  在SDK的开发过程中另一个常会遇到的就是很多参数的校验和再封装,我们也可以使用装饰器去完成:

  export function snakeParam( target: object, name: string, descriptor: TypedPropertyDescriptor) { let callback = descriptor.value!;

  return { ...descriptor, value(...args: any[]): any { let [arg, ...other] = args; arg = convertObjectName(arg, ConvertNameMode.toSnake); callback.apply(this, [arg, ...other]); } };}

  泛型

  泛形可以根据用户的输入决定输出,最简单的例子是

  function identity(arg: T): T { return arg;}

  当然它没有什么特别的意义,但是它表明了返回是根据arg的类型,在一般开发过程中,你逃不开范型的是Promise或者前面的TypedPropertyDescriptor这种内建的需要类型输入的地方,不要草率的使用any,如果你的后端返回是一个标准结构体类似:

  export interface IRes { status: number; message: string; data?: object;}

  那么你可以这样使用Promise:

  function example(): Promise { return new Promise ...}

  当然泛形有很多高级应用,例如泛形约束,泛型创建工厂函数,已经超出了本文的范围,可以去官方文档了解。

  构建

  如果你的构建工具是Webpack,在SDK的开发中,尽量使用node方式调用(即webpack.run执行),因为SDK的构建往往会应对很多不同的参数变化,node方式相比纯配置方式可以更加灵活的调整输入输出的参数,也可以考虑使用rollup,rollup的构建代码更加面向编程方式。

  需要注意的是,在Webpack3和rollup中构建中可以使用ES6模块化的方式构建,这样业务代码引入你的SDK后,可以通过解构引入的方式减少最终业务代码的体积,如果你只是提供了commonjs的包,那么构建工具的tree sharking是无法生效的,如果使用babel的话注意关闭module的编译。

  另外一种减少单个包体积的方式,可以使用lerna在一个git仓库里构建多个NPM包,比起拆仓库可以更方便的使用公共部分的代码,但是也需要注意对公共部分代码的修改不要影响到别的包。

  其实对于大多数的SDK的来说,Webpack3和rollup使用感受是差不多的,比较常用的插件都有几乎同名的对应。不过rollup有两个优势,一个是rollup的构建更细化,rollup.rollup接受inputOptions生成bundle,还可以generate生成sourcemap,write生成output,在这个过程中我们可以做一些细致的工作。

  第二点是rollup.rollup会返回一个promise,也就意味着我们可以使用async的方式来写构建代码,而webpack.run还是使用的回调函数,虽然开发者可以封装成promise,但是个人觉得还是rollup的写法还是更爽一点。

  单元测试

  上周我同事做了一个在线的分享,我发现很多同学都对单测很感兴趣也很疑惑,在前端开发中,对涉及UI的业务代码开发单测试比较困难的,但是对于SDK,单元测试肯定是准出的一个充要条件。当然其实我也很不喜欢写单测,因为单测往往比较枯燥,但是不写单测肯定会被老司机们“教育”的~_~。

  一般的单测使用mocha作为测试框架,expect作为断言库,使用nyc提供单测报告,一个大概的单测如下:

  describe('xxx api test', function() { // 注意如果要用this调用mocha,不要用箭头函数 this.timeout(6000); it('xxx', done => { SDK.file .chooseImage({ count: 10, cancel: () => { console.log('选择图片取消----'); } }) .then(res => { console.dir(res); expect(res).to.be.an('object'); expect(res).to.have.keys('ids'); expect(res.ids).to.be.an('array'); expect(res.ids).to.have.length.above(0); uploadImg(res.ids); done(); }); });});

  同样你可以用TypeScript写单测,当然在执行过程中,不需要再编译了,我们可以直接给mocha注册ts-node来直接执行,具体方式可以参考Write tests for TypeScript projects with mocha and chai — in TypeScript!。但是有一点需要提醒你,写单测的时候尽量依赖文档而不是智能提示,因为你的代码出错,可能会导致你的智能提示也是错误的,你根据错误的智能提示写的单测肯定也是。。。

  对于网络请求的模拟可以使用nock这个库,需要在it之前增加一个beforeEach方法:

  describe('proxy', () => { beforeEach(() => { nock('http://test.com') .post('/test1') .delay(200) .reply(200, { // body test1: 1, test2: 2 }, { 'server-id': 'test'// header }); }); it(...}

  最后我们用一个npm script加上nyc在mocha前面,就可以获得我们的单测报告了。

  这里我还提了几个TypeScript使用中的小tips给大家参考。

  tips: 如何在非发包情况下给内部库添加声明

  这个SDK在开发过程会依赖一个内部NPM包,为了让这个NPM支持TypeScript调用,我们有几种做法:

  给原包添加d.ts文件,然后发布.

  发布@types包,需要注意的是NPM不支持@types/@scope]/{pkgname}这种写如果是私库包,可以使用@types/scope_{pkgname}这种写法.

  这次使用的标注一个文件夹存放对应的d.ts文件,这种方式适合开发中进行,如果你觉得你写的d.ts还不够完美,或者这个d.ts文件目前只有这个SDK有需要,可以这么使用,在tsconfig.json中修改:

  "baseUrl": "./","paths": { "*": ["/type/*"]}

  tips: 如何处理resolve和reject不同类型的promise回调

  默认的reject返回的参数类型是any,不一定能满足我们的需要,这里给一个解决方案,并非最佳,作为抛砖引玉:

  interface IPromise { then( onfulfilled?: | ((value: T) => TResult1 | PromiseLike) | undefined | null, onrejected?: | ((reason: U) => TResult2 | PromiseLike) | undefined | null ): IPromise; catch( onrejected?: | ((reason: U) => TResult | PromiseLike) | undefined | null): Promise;

(责任编辑:范老师)
最新开班
  • 成都Java培训班
    免费试听名额发放中...
  • 成都C++培训班
    免费试听名额发放中...
  • 成都PHP培训班
    免费试听名额发放中...
  • 成都网络工程培训班
    免费试听名额发放中...
  • 成都Unity3D培训班
    免费试听名额发放中...
  • 成都大数据培训班
    免费试听名额发放中...
  • 成都uid培训班
    免费试听名额发放中...
  • 成都会计培训班
    免费试听名额发放中...
  • 成都Python培训班
    免费试听名额发放中...
  • 成都嵌入式培训班
    免费试听名额发放中...
  • 成都web培训班
    免费试听名额发放中...
  • 成都软件测试培训班
    免费试听名额发放中...
在线留言
提交

校区地址:绵阳市涪城区临园路东段68号富临大都会7栋3单元9层12号

联系电话:15023458194

公交路线:富乐路口凯德广场(10路;29路;3路;15路;11路;15a路;71路)

校区地址:成都市锦江区东大街紫东楼段35号明宇金融广场19楼1903室

联系电话:15023458194

公交路线:芷泉街(18路;21路;43路;48路;104路;152路;335路 ) 地铁路线:东门大桥站(地铁2号线)

校区地址:成都市高新区奥克斯广场蜀锦路209号一楼商铺

联系电话:15023458194

公交路线:益州大道锦城大道口(18路;21路;43路;48路;104路;152路;335路 ) 地铁路线:孵化园(地铁1号线)

校区地址:成都锦江区东大街芷泉街229号东方广场C座3楼303

联系电话:15023458194

公交路线:芷泉街(188路;115路;515路;236路;505路;501路;84路 ) 地铁路线:东门大桥站(地铁2号线)

校区地址:成都市武侯区佳灵路3号红牌楼广场2号写字楼11楼1115号

联系电话:15023458194

公交路线:红牌楼东(11路;92路;100路;111路;139路;g28路;快速公交K1/K2) 地铁路线:红牌楼站(地铁3号线)

校区地址:成都市锦江区红星路二段70号四川日报大厦502-2

联系电话:15023458194

公交路线:市二医院站(6路;49路;102路;5路;37路;g92路;) 地铁路线:地铁市二医院(地铁3号线)

校区地址:成都市锦江区东大街紫东段35号明宇广场2306

联系电话:15023458194

公交路线:芷泉街(18路;21路;43路;48路;104路;152路;335路 ) 地铁路线:东门大桥站(地铁2号线)

校区地址:四川省成都市武侯区高新科技孵化园9号园区E座7楼

联系电话:15023458194

公交路线:益州大道锦城大道口(18路;21路;43路;48路;104路;152路;335路 ) 地铁路线:孵化园(地铁1号线)

校区地址:成都市成华区建设路10号万科钻石广场B座5楼

联系电话:15023458194

公交路线:建设路中(6路;14路;42路;72路;76路;1010路;)

校区地址:成都市高新区奥克斯广场B座1708

联系电话:15023458194

公交路线:益州大道锦城大道口(18路;21路;43路;48路;104路;152路;335路 ) 地铁路线:孵化园(地铁1号线)

了解达内动态
关注成都达内教育公众号

首页 | 关于达内 | 课程中心 | 专家师资 | 视频教程 | 学员空间 | 校企合作 | 新闻资讯 | 就业指导 | 网站地图

2016-2025 达内时代科技集团有限公司 版权所有 京ICP证8000853号-56