查看原文
其他

【第625期】JavaScript SDK设计指南

levon 前端早读课 2019-07-11

前言

看到这篇的时候被惊呆了完全“标题党”。文章分享的不止是SDK的事情,涉及面的非常全 and 广,而且很多小知识点。本文来自众成翻译平台@levon带来的分享。警示下,要看此篇需要多点耐心。


正文从这开始~


介绍

本文介绍如何对开发 JavaScript 网页应用设计SDK,适用于桌面端,移动端,不同平台,不同浏览器。对于JavaScript实现的非网页应用(硬件,嵌入式,node/io js)场景则不适用,这些场景会在未来介绍。


由于我没有找到比较好的 JavaScript SDK文档,所以把我的个人经验做了整理和记录。JavaScript-SDK-设计 不仅仅介绍SDK,还包括用户和浏览器的关系。写的越多,想的越多,就开始关注不同平台,不同浏览器之间的性能和差异。


什么是SDK

SDK是软件开发工具包 的缩写,是能够让编程者开发出应用程序的软件包。一般SDK包括一个或多个API、开发工具集和说明文档。


设计哲学

SDK设计成什么样子取决于SDK用途,但是必须要原生 ,简短 ,执行迅速 ,代码干净 ,易读 ,可测试 


不应该使用Livescript,Coffeescript, Typescript这类寄生语言,这种语言的原理是把代码编译成JavaScript语言再执行。JavaScript的原生实现执行速度更快。


尽量不要使用jQuery,而应该使用轻量的类库代替。如果是DOM操作可以使用zepto.js 。如果要发HTTP ajax请求 使用window.fetch


SDK版本一旦发布,要保证可以兼容旧版本并且要能被将来的版本兼容。所以要给SDK写文档 、写注释、做单元测试和情景测试。


范围

基于文章:第三方JavaScript


哪些情况你应该设计SDK

1. 嵌入的widgets -在第三方网页上嵌入的交互应用(Disqus, Google Maps, Facebook Widget)

2. 分析和度量 -收集用户信息,了解访客和网站交互的方式 (GA, Flurry, Mixpanel)

3. 封装网络服务 -开发调用外部网站服务的客户端应用. (Facebook Graph API)

哪些情况应该使用SDK 一个建议 


SDK内容

应该使用异步语法来加载脚本。 应该改善用户体验,SDK类库不应该影响主页面的加载。


异步语法



针对现代浏览器,可以使用async



传统语法



比较

下列图标表示异步语法和同步语法的差别。

异步:



同步:



JavaScript 异步执行和延迟执行


[https://developers.google.com/speed/docs/insights/BlockingJS](https://developers.google.com/speed/docs/insights/BlockingJS_) 


应该避免代码块,或者缩小代码块的规模,特别是外部代码。渲染页面不可或缺的代码应该内联,内联代码应该简短并且执行速度要快。不是初始化必须的代码应该异步或延迟执行。


异步的问题

如果异步加载,不能像下列代码一样调用SDK



这样做会导致未知的结果,因为SDKName()执行的时候尚未被加载完成。



或者 使用[].push



其他

还有其他方式加载代码。

ES2015中的Import



使用Modular

完整代码请看LoadingJavaScript Modules



SDK版本管理

不要用类似 brand-v<timestamp>.js brand-v<datetime>.js brand-v1-v2.js的版本号,这样会导致SDK使用者不知道最新的版本是什么。


使用主版本.小版本.补丁号这种有语义的命名方式管理版本。v1.0.0 v1.5.0 v2.0.0这样的版本号让使用者容易在changelog文档中跟综和查找。


Normally, we canhave different ways to state the SDK version, it depends on your service anddesign. Using Query String path.



Using the FolderNaming.



Using hostname(subdomain).


For the furtherdevelopment, you are advised to use stable unstable alphalatest experimental version.



Changelog Document

如果SDK有升级,应该通知SDK使用者。majorminor版本甚至是修改bug都应该写Changelog Document 使用者会有一个好的体验。Keep a ChangelogGithub Repo


每个版本都应该有:



命名空间

应该最多定义一个命名空间,不要使用通用的名字定义命名空间以防止和其他类库冲突。


应该用(function () { ...})()SDK代码包起来。


jQuery, Node.js等等类库经常使用的一个方法是把创造私有命名空间的整个文件用闭包包起来,这样可以避免和其他模块冲突。


避免命名空间冲突

参考Google Analytics项目你可以通过改变ga的值来定义你的命名空间。



OpenX 的经验是提供一个参数来请求相关命名空间。



存储机制

Cookie

考虑subdomain  path 情况,使用Cookie的范围非常复杂。


对于path=/  http://github.com cookiefirst=value1http://sub.github.com 有另一个cookie:second=value2 | --- | http://github.com |http://sub.github.com ||:---------:|:------------:|:------------: | |first=value1| ✓ | ✓||second=value2| ✘ | ✓|


first=value1  http://github.com 生效, second=value2 http://github.com/path1 生效, third=value3  http://sub.github.com 生效,
| --- | http://github.com | http://github.com/path1 | 錯誤! 超連結參照不正確。 |:---------:|:------------:|:------------:|:------------:||first=value1 | ✓ | ✓ | ✓|
|second=value2 | ✘ | ✓ | ✘| |third=value3| ✘ | ✘ | ✓|


检查Cookie可写性

给定一个域(假设是当前主机名),检查cookie是否可写。



检查第三方Cookie可写性

只用客户端JavaScript无法实现,需要一个服务器做这件事情。(Example)


读写删除Cookie

//删除 cookie 代码片段。


Session

客户端JavaScript代码无法写session,请参考服务端实现。


浏览器打开页面,session一直有效,页面的重新加载和恢复,session也不会被删除。在新tab页或者窗口中打开页面会导致新的session初始化。


本地存储

存储的数据没有有效期,数据的额度可以很多(至少5M)并且不会转到服务端。


相同域的本地存储不能共享,可以在站点内部创建框架并且可以用postMessage在本地存储之间传递数据。怎么做?


检查本地存储可写行

不是每个浏览器都支持window.localStorageSDK在使用之前必须确认是否可用。



Session 存储

session存储数据(当tab页关闭,数据失效)。


检查SessionStorage可写性



事件

浏览器端有load unload on off bind 事件,这里有一些代码可以处理不同浏览器的差异。


Document Ready

在开始执行SDK功能之前要先确保整个页面加载完成。



在document已经被完全加载和解析后执行,不用等stylesheets,images和子模块完成加载。

load事件可以用来探测页面是否完全加载

JS Tip的信息


消息事件

关于iframe和窗口的跨源通信,请读API文档


发送的消息格式应该是String,如果用json做一些高级用法,就用JSON String。虽然很多浏览器支持对参数的结构化克隆算法 ,但并不是全部浏览器都支持。


方向改变

探测设备方向改变。



得到方向旋转角度。



竖屏正方向,竖屏反方向,横屏正方向,横屏反方向。(实验性的)



禁止滚屏



请求

我们的SDKAjax请求和服务器通信,虽然可以用jQuery ajax请求,但这里我们有更好的方案实现它。


Image Beacon

使用Image Beacon让浏览器通过GET 请求获取图片。


记住加上时间戳防止浏览器缓存



需要注意,GET Query字符串有长度限制,一般是2048,取决于浏览器和服务器。你应该检查请求是否超长了。



你可能在encodeURI encodeURIComponent上遇到问题,最好能理解它们。见下

图片加载成功/失败回调函数。



单一Post

用表单元素的POST方法发送键值对。



多重Post

服务一般很复杂,我们需要发送POST发送很多数据。


Iframe

如果需要在页面中生成内容,你可以用iframe把你的html嵌入进来。



iframe内部额外的margin删除



html内容放到iframe



jsonp脚本

是指你的服务器需要返回JavaScript代码以让浏览器执行,只包括JS脚本链接。



更多关于jsonp信息

1. JSONP只能在GET请求工作。

2. JSONP缺少错误处理,意味着你不能在返回码404,500等里面探测。

3. JSONP请求通常是异步的。

4. 注意CSRF攻击。

5. 跨域通讯,脚本回应端(服务端)不需要关心CORS


Navigator.sendBeacon()

先看下文档

This methodaddresses the needs of analytics and diagnostics code that typically attempt tosend data to a web server prior to the unloading of the document. Sending thedata any sooner may result in a missed opportunity to gather data. However,ensuring that the data has been sent during the unloading of a document issomething that has traditionally been difficult for developers.


通过apiPOST beacon请求,很酷。



XMLHttpRequest

XMLHttpRequest 不是好主意。我假设你不想在和浏览器斗争上浪费时间,你可以试下这些代码。

  • window.fetch - Awindow.fetch JavaScript polyfill.

  • got - Simplified HTTP/HTTPSrequests

  • microjs - list ofajax lib 4. more


Fragment 标识

#这是哈希标志。记住有哈希标志的请求,哈希标志最终不会发出去。

比如,你在页面http://github.com/awesome#huei90中。



最大连接数

检查浏览器的最大连接请求数浏览器范围



Component of URI

很重要的一点,你应该知道SDK是否需要解析本地url



解析URI

(https://developer.mozilla.org/en-US/docs/Web/API/Window/URL).这有个很简单的方法,是通过本地URL()接口,但是并不支持所有浏览器尚未标准化


那些不支持URL()接口的浏览器,尝试DOM createElement('a')方法。



调试

模拟多重网域

你不需要注册不同域名来模拟多网域,只需要编辑操作系统的hosts文件。



加上下面条目。


这时你可以访问http://publisher.net http://sdk.net页面了。


开发工具

如果需要调试SDK,使用浏览器提供的调试工具- Chrome Developer Tools Safari Developer Tools Firebug,开发工具简称DevTools


开发者可以通过DevTools访问应用和浏览器内部。使用DevTools高效跟踪布局问题,设置JavaScript断点,得到代码优化的洞察力。


Console Logs

测试预期文本输出,或者其他调试,可以用浏览器接口console.log()Console Logs。有许多方法格式化和输出你的信息,查找更多Console接口



Debugging Proxy

有时候调试代理帮你测试你的SDK。调试网络拥塞,修改cookies,报头,缓存,编辑http request/responseSSL代理,ajax调试等等。


这里有些软件你可以试一下。

  • FiddlerCore

  • Charles

  • Cellist


BrowserSync

BrowserSync通过同步多设备文件的变化和相互作用的方法让你的测试更快。非常快并且是免费的。


如果需要测试SDK在各种设备上的结果,它可以帮你很多。试一下=)


小贴士和诀窍

Piggyback

有时候不希望开发者包含所有SDK源,只需要做一个1x1像素的请求。我们只需要要求开发者包含我们链接的图片文件。



页面可见性接口

有时SDK像知道页面是否取得用户焦点。试试代码 visibly.js  visibilityjs


Document Referrer

document.referrer得到上一个页面的url。注意上一个是指浏览器上一个而不是人们认为的上一个。举个例子,加入你点击浏览器后退按钮,页面A -> 页面B -> 页面C -> (后退) 页面B,现在页面B的上一个是页面A,不是页面C


Console LogsPolyfill

这不是真的代码,只是保证调用console.log接口不会在客户端抛出异常事件。



EncodeURI orEncodeURIComponent

理解escape() encodeURI() encodeURIComponent()的区别。这里

记住encodeURI()  encodeURIComponent()之间有11个字符不同。 这些字符是# $ & + , / : ; = ? @更多讨论



你可能不需要JQuery

就像标题说的,你可能不需要jquery。如果你在寻找一些实用的代码,这些非常有帮助AJAXEFFECTSELEMENTSEVENTSUTILS


你不需要jQuery

拥抱和理解现代Web API,发现各种模版类库可以让你从jQuery调用链中释放出来,并填补之间的鸿沟。

http://blog.garstasio.com/you-dont-need-jquery/

有用的小贴士

  • SelectingElements 

  • DOMManipulation


用回调函数加载脚本

异步加载代码增加回调事件。



只能调用一次的函数

这里展示如何实现只能一次调用。

偶尔你希望一个函数只能被调用一次。经常这些函数在事件监听列表,很难管理。当然你可以简单的把它从监听列表删除,但是有时候希望完美,你只是希望函数只能被调用一次。下面的JavaScript函数让它变为可能!



Pixel RatioDensity

在做移动开发的时候,如果你被像素,比例,密度,维度这些概念困住,是这理解视频,它会帮助你。

Device pixel ratio - Mobile WebDevelopment 
Mobile devicepixels - Mobile Web Development


Get Style Value

Get inline-stylevalue


Get Real stylevalue


ref: https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle


检查元素是否在观察窗

更多资料在 这里.



检查元素可视性



得到视窗大小



关于本文

译者:levon@众成翻译平台

译文链接:

原文链接:

 


欢迎投稿到前端早读课

投稿邮箱:181422448@qq.com


    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存