[互联网]第三方内容开发最佳实践.ppt

上传人:音乐台 文档编号:1998593 上传时间:2019-01-29 格式:PPT 页数:75 大小:2.44MB
返回 下载 相关 举报
[互联网]第三方内容开发最佳实践.ppt_第1页
第1页 / 共75页
[互联网]第三方内容开发最佳实践.ppt_第2页
第2页 / 共75页
[互联网]第三方内容开发最佳实践.ppt_第3页
第3页 / 共75页
亲,该文档总共75页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述

《[互联网]第三方内容开发最佳实践.ppt》由会员分享,可在线阅读,更多相关《[互联网]第三方内容开发最佳实践.ppt(75页珍藏版)》请在三一文库上搜索。

1、第三方内容开 发最佳实践 张立理 otakustay 权一 _Franky 2012.6 2.0 2.5 3.0 3.5 4.0 5.0 6.0 beta dev nightly XP+SP1 XP+SP2 KB2497640 Flash Quirks !important iframe iframe 第三方代码 Google Analytics var _gaq = _gaq | ; _gaq.push(_setAccount, UA-XXXXX-Y); _gaq.push(_trackPageview); (function() var ga = document.createElemen

2、t(script); ga.type = text/javascript; ga.async = true; ga.src = (https: = document.location.protocol ? https:/ssl : http:/www) + .google- var s = document.getElementsByTagName(script)0; s.parentNode.insertBefore(ga, s); )(); 第三方代码 Baidu ADM 第三方代码 Baidu ADM 第三方功能使用过程 / 引入第三方脚本 / 调用API 静态脚本资源 内容检索 日志上

3、报 引入脚本 脚本 类型 同步 异步 脚本 位置 脚本 URL http:/ https:/ 引入脚本 同步 使用document.write var protocol = (https: = document.location.protocol) ? https:/ : http:/; document.write(); 不要使用/ https协议 file:/协议下本地调试会出现问题 严格加上charset属性 无法保证目标页面的编码 将转义为 不需要使用 引入脚本 异步引入 创建元素 var script = document.createElement(script); script.

4、type = text/javascript; script.async = true; script.src = src; / 插入元素 确保这段脚本可以异步执行 不需要type属性 默认为text/javascript 不需要async属性 编程创建的元素必定是异步的 引入脚本 插入元素 错误方法 document.body.appendChild(script); 在元素解析过程中,不存在元素 IE6“终止操作”错误 document.head.appendChild(script); IE6的标签BUG 引入脚本 插入元素 第一个元素前 var firstScript = docume

5、nt.getElementsByTagName(script)0; firstScript.parentNode.insertBefore(script, firstScript); 优点 无if分支判断 不会导致浏览器崩溃 缺点 是否确定文档中已经有至少一个元素 无法控制元素插入位置,有问题时找该元素较为麻烦 部分浏览器parentNode会是导致错误 引入脚本 插入元素 元素第一个子元素 var container = document.getElementsByTagName(head)0; if (!head) / 补救; else container.insertBefore(scr

6、ipt, container.firstChild); 优点 插入位置固定,易于查找 缺点 需要if分支判断是否存在 多数浏览器会补全 例外:Firefox 4.0b1 / iPhone 3.0 / Chrome 5.0等 引入脚本 插入元素 防御性补救措施 setTimeout(function() if (!document.body) setTimeout(arguments.callee, 0); else document.body.insertBefore(script, document.body.firstChild); , 1); 优点 未发现不支持的情况,用于处理前几种方案

7、的盲区 缺点 需要补全才可加载脚本,导致脚本加载时间滞后 引入脚本 不要随意删除元素 如果删除正在执行的元素,会导致IE崩溃 过多元素导致内存占用 定时使用JSONP时容易出现 使用setTimeout来控制元素的删除 var scripts = document.getElementsByTagName(script); var currentScript = scriptsscripts.length - 1; setTimeout(function() currentScript.parentNode.removeChild(currentScript); , 1); 嵌入内容 嵌入方式

8、 直接嵌入 常见问题 z-index Quirks模型 常用方法 document.write Flash 嵌入内容 使用元素 优点 用于隔离样式 避免全局环境变量污染 缺点 与主页面交互较为麻烦 IE下权限问题 需要重置样式 width / height / vspace / hspace / scrolling / frameborder / allowtransparency / display / border / vertical-align / margin 嵌入内容 直接插入元素 选择元素作为容器 语义正确性,第三方内容为“插入的内容” 是透明元素,不会导致内容模型错误 IE下,

9、元素内放置元素会导致崩溃 关注样式重置 !important 使用.style.cssText可添加!important声明 float margin / padding / border overflow / position / display / visibility text-align 嵌入内容 其它元素样式重置 | text-decoration color / decoration display / border list-style http:/ 嵌入内容 其它问题 尽量使用insertBefore而不是appendChild IE的“终止操作”问题 z-index相互覆盖问

10、题 最大值2147483647 同值情况下,DOM中靠后的在上方 在DOM中越靠后则越上方 通过DOMContentLoaded或onload插入 但内容展现的延迟越长 从当前元素向上查找至的直接子代, 在其前面插入 嵌入内容 兼容Quirks模式 检测文档模式 patMode 盒模型 border-box VS content-box 水平居中 margin: 0 auto无效,使用text-align: center代替 页面尺寸 body VS documentElement document.write 问题性 VS 必要性 内联+外部脚本时序问题 外部脚本时序问题 IE假死问题 do

11、cument.write Its evil 不可异步执行 导致HTML解析过程回溯 Its inevitable 展现内容与脚本执行位置相关 没有API获取当前执行的元素 第三方内容脚本存在调用 Google Adsense / Baidu Cpro 使用创建内容时常用 Tokenizer Tree Construct Script DOM Tree document.write IE下时序问题 内联 VS 外部脚本 使用document.write输出标签 内联脚本永远优先执行 / hello.js中定义了hello函数。IE下,hello函数未定义,抛出ReferenceError doc

12、ument.write( + hello();) 不会阻断当前脚本继续执行 / 该js中包含了hello函数的定义 document.write(); / 在IE下,此时hello.js文件未加载完毕,hello函数未定义,抛出ReferenceError hello(); document.write IE下时序问题 嵌套输出外部脚本 document.write(); / ReferenceError try alert(hello); catch (ex) / 会加载2次read.js / 形成尝试为2的嵌套document.write / 才可以读取到hello document.wr

13、ite(); ex.js document.write(); define.js var hello = world; read.js if (windowhello) alert(hello); else document.write(); ex.jsdefine.jshello read.jshelloread.js document.write 导致IE6假死问题 function destroyIE(iframe) var doc = iframe.contentWindow.document; doc.write(); doc.write(alert(“hello“);); 使用do

14、cument.write 一个外部脚本+一个内部脚本 IE权限问题 onload事件问题 IE收藏夹问题 DOM移动重加载问题 缓存问题 javascript:伪协议问题 IE下权限问题 document.domain = ; var iframe = document.createElement(iframe); iframe.src = about:blank; document.body.appendChild(iframe); iframe.contentWindow.document.write(test); / IE下报错 使用跨域策略文件 document.domain = ;

15、iframe.src = /domain-policy.htm; DOM1注册onload无法移除问题 function loadFrame(iframe) iframe.onload = null; / 无法移除onload事件 var doc = iframe.contentWindow.document; doc.open(text/html, replace); doc.write(html); / 导致再次触发loadFrame doc.close(); 无法移除DOM1的onload处理函数无效 不要使用DOM1的方式注册onload,使用脚本注册 通过标记变量来控制 if (th

16、is.getAttribute(data-rendered) return; this.setAttribute(data-rendered, rendered); IE6收藏夹问题 页面为 /frame DOC_baidu_clb_slot_iframe_1234567 BASEURL=http:/ ORIGURL=/frame 从收藏夹打开,加载的是BASEURL,忽略ORIGURL 判断当前的src属性,不符合预期则重新加载一 次 function renderThirdPartyFrame(iframe, content) if (iframe.getAttribute(src, 2)

17、 != getFrameUrl() / IE会补全src iframe.src = getFrameUrl(); return; / 原renderThirdPartyFrame函数内容 元素移动重加载问题 在加载完毕后,移动该元素在DOM中的位置 影响统计数值 通过标识属性避免多次加载的影响 浏览器结果 IE6-8不重新加载 IE9重新加载 Firefox重新加载 Chrome重新加载 Opera重新加载 缓存BUG var list = http:/, http:/ ; var src = listMath.random()*2 | 0; document.write(); documen

18、t.write(当前iframe的src为: + src); 刷新时src改变但内容不变 createElement创建加入DOM后设置src无此问题 如果src符合#+$则无此问题 解决方法 使符合上述条件之一 Firefox4开始修正,但极端情况下依旧存在问题 var ifm = document.getElementById(ifm); window.onload = function () / Firefox4-10刷新时会加载2次 ifm.src = /; ; 使用javascript:伪协议导致IE下不强制渲染 var text = abc; var script = var d

19、= document; d.open(text/html, replace); d.write(parent.text); d.close(); var html = ; document.write(html); 将包含以上脚本的页面添加到收藏夹,从收藏夹打开 视觉上看不到abc字母 DevTool查看iframe中不存在TextNode iframe上右键-属性,得到的地址为about:blank 强制触发paint / 刷新UI Update Queue script中添加d.offsetWidth; 更多伪协议问题 当parent页存在 base标签,且target为_blank时,会

20、导致IE系 弹窗(并可能会被浏览器拦截) 不恰当的写入方式,造成parent页的document.readyState永远 处在inneractive状态 parent页面的onload事件,永远不会被触发 IE8-下,iframe.onload,被认定跨域,注册无效问题 iframe.src=“about:blank“导致IE全系后退按钮bug parent页后退按钮失效,可以无限按后退,并导致iframe内部的资源 无限重载 不恰当地使用伪协议写入文档流,IE会永远卡在loading状态(不 停的转啊转) FLASH Flash 覆盖 移除 引入 http:/ FLASH 引入Flash

21、分浏览器使用不同标签 使用特性检测 var useObjectForFlash = (classid in document.createElement(object) 方案在Chrome下有BUG IE8下不支持setAttribute IE8-混用attribute和property,用property代替即可 使用innerHTML输出元素 不支持appendChild(IE) Flash的容器元素必须事先在DOM中 先创建Flash后加入DOM会导致停止在第一帧(IE6-8) allowScriptAccess=“never“ FLASH 移除Flash 先隐藏,setTimeout后

22、移除 Opera+部分版本FlashPlayer下直接移除会留下残影 var element = document.getEleemntById(someFlash); element.style.display = none; / 先隐藏起来 / 利用setTimeout,让DOM有一次重绘的时间 setTimeout(function() element.parentNode.removeChild(element); , 1); 隐藏Flash 使用left / top移出屏幕外 移动DOM位置、修改display / visibility会导致Flash重新加 载 FLASH 盖住Fl

23、ash wmode window / opaque / transparent opaque下使用z-index可覆盖 window下使用iframe覆盖 要求浏览器强制重绘,解决渲染问题 http:/www.w3help.org/zh-cn/causes/RX8012 http:/ 日志上报 上报方式 使用 URL长度控制 mimeType设置 常见问题 PVID生成策略 退出时上报问题 预加载问题 日志上报 var log = (function() var fix = ; return function(url) var image = new Image(); fix.push(ima

24、ge); image.onload = image.onerror = image.onabort = function() image = image.onload = image.onerror = image.onabort = null; for (var i = 0; i 回收问题 请求过程中,如果对象被GC回收,导致请求中断 将放入DOM 会触发layout过程 将image放在window下 会影响forin 使用闭包保留引用 IE事件问题 如果有本地缓存,则设置src和onload事件同步触发 此后设置onload事件已经错过触发时机 必须先设置onload事件再设置src属性

25、 日志上报 缓存问题 url必须加上随机数 IE及Opera部分版本实现HTTP Cache有误 mimeType问题 服务器端设置为image/gif,返回1x1的透明像素 Chrome控制台警告 的onload触发 日志上报 URL长度问题 浏览器限制 IE6-7:2065 IE8:4083 IE9:65536 Opera:4050-190,000 Chrome:8182-20,000,000 服务器限制 nginx:large_client_header_buffers 8K Apache:LimitRequestLine 8190 代理服务器? 日志上报 PVID生成 Math.ran

26、dom以时间为种子,高并发状态下易重复 (Math.random() * 2147483648) | 0).toString(36) 引入更多随机因子 location.href / cookie / userAgent / language 当前时间 history.length / plugins.length / mimeTypes.length / flashVersion mouse x / y 日志上报 退出时上报 同步ajax 跨域环境下不可用 异步 使用while循环产生约1/4s的延迟 缩短日志长度 得到TCP包即认为上报成功,不统计完成HTTP请求 实测极限成功率约为85%

27、 有效利用localStorage存放,下一PV时重新发送 需要把时间等因子一同写入参数 日志上报 现象 被浏览器预加载 响应的mimeType错误 会被加载2次 解决 doc.write() doc.write() 细节问题 第三方 Cookie Gzip问 题 点击监 控方案 特性检 测 第三方COOKIE P3P - Platform for Privacy Preferences Project 影响Cookie的写入,对读取无影响 简洁策略 CP=. 尽可能避免通过javascript读写第三方Cookie IE6存在BUG 注意默认不允许第三方Cookie的浏览器(Safari)

28、Safari3无解 Safari4+使用POST实现Cookie写入 GZIP问题 IE6加载资源有gzip的资源不解析、执行 不缓存gzip资源时,使用max-age=0代替no-cache 一个gzip资源在多个中使用时,在主页面先行完成加 载,使用缓存 IE6对于gzip资源不使用ETag,注意使用Last-Modified IE6对于gzip资源会在Modified-Since后加上;length=xxx字 符串,实现Web Server时注意匹配 针对IE6放弃gzip Nginx:gzip_disable “MSIE 1-6. “; http:/ 点击监控问题 针对图片、文字 使用

29、作为容器 针对Flash 使用覆盖Flash对象 必须有背景色(非transparent)或背景图片 使用背景色,则设置透明度为0(opacity + filter) 保证容器有固定宽高,并且overflow:hidden position: absolute; top: 0; left: 0; width: 100%; height: 9999px; background-color: #fff; opacity: 0; filter: alpha(opacity=0); 或 background-image: url(about:blank); 使用clickTAG(需Flash制作配合)

30、 特性检测 优先使用特性检测代替UA检测 特性检测的基本思路 制造差异环境 获取状态值 判断并得到特性 常见特性 是否支持position: fixed iframe是否存在权限问题 Flash对象使用或者 是否支持border-radius 特性检测 例:是否支持position: fixed var outer = doc.createElement(div); var inner = doc.createElement(div); var result = false; outer.style.position = absolute; outer.style.top = 200px; i

31、nner.style.position = fixed; inner.style.top = 100px; outer.appendChild(inner); document.body.insertBefore(outer, document.body.firstChild); if (inner.getBoundingClientRect doc.body.removeChild(outer); return result; document outer inner (not support) inner (support) 上边距重叠 其他细节 window.open问题 不同浏览器参数

32、不同 http:/ Chrome下,如果设置了screenX和screenY,会使left和top一 起失效 补全问题 建立空写入内容时,如果内容仅包含,则会 补全但没有 但脚本可能依赖,因此必须将内容写入中 document.write(); document.write(content); 开发相关 开发、规范 调试、测试 上线、部署 开发相关 开发准则、规范 变量一行一个var关键字 大量使用防御性编程 浏览器 != IE+Firefox+Chrome+Opera+Safari 自动补上全局try / catch 回发catch的Error,带上Referrer以方便复现问题 不写任何侵

33、入性代码 不污染内置对象及其prototype 尽量少的全局变量 尽量不使用Cookie userData + localStorage基本可以满足本地存储需求 开发相关 IIFE书写 Imediately Invoked Function Expression 使用(function() ()的形式,避免使用void / ! / 等 方式 语义明确,不加入额外运算 括号(分组)运算符在语法树中不会留下 有利于基于AST的工具分析语法 if (condition) var x = 3; console.log(x); if (condition) (function() var x = 3;

34、console.log(x); (); node fix.js in.js out.js 开发相关 统一全局函数调用方式 alert VS window.alert 推荐alert window.alert递归栈溢出限制低 alert性能略高于window.alert alert; / 是否有这一行,IE6-8中结果不同 var hijack = window.alert; window.alert = function() hijack(hijack); ; alert(origin); windowglobal code copy on read 开发相关 调试及测试 调试信息控制 使用注

35、释方式 /* #DEBUG# code #DEBUG# */ 调试时保留全部,白盒测试时去除#DEBUG#段但保留内部 console相关代码,生产环境全部去除 使用函数变换方式 enableDebug(someFunction, options); options: enter / leave / time / count 测试、上线时去除所有enableDebug调用 如果需要在函数体中部添加调试相关逻辑,则说明函数需要 进一步拆分 对设计和编码有指导意义 开发相关 开发过程中版本控制 开发时:拆分为多个文件独立开发 调试、测试时:生成合并未压缩版本 生产环境:使用合并压缩版本 生产环境规

36、范 javascript中不含有任何非ASCII字符 自动增加IIFE、添加try / catch块 注意合并后文件过大可能导致移动浏览器不缓存 开发相关 稳定 安全 性能 需要 努力 相当 困难 基本 不能 快醒 醒吧 上线部署 清除先期缓存 http:/ 用户不会替你修改版本号! Self Updating Script 自更新的脚本 用户引用的脚本地址永远相同(没有版本号) 需要有较长的客户端缓存(max-age / Expires) 新版本部署后可以及时更新客户端的脚本 上线部署 清除先期缓存 利用location.reload(true /* false */) var re = t

37、rue; var ifm = document.createElement(iframe); ifm.src=about:blank; document.body.appendChild(ifm); var doc = ifm.contentWindow.document; doc.open(); doc.write(eval(“ + if(parent.re)parent.re = false; location.reload(true /* false */); elsedocument.write(“); + “); doc.close(); 会引起系列问题 可使用实体页(服务器真实存在

38、的页面)清理缓存 会产生额外请求 可使用dataURI代替 ifm.src = data:text/html;charset=utf-8, + html; 上线部署 加载资源但不执行 IE、Opera、Safari4-、Chrome7- 使用元素 Chrome8+,Safari5+、Firefox 使用元素 上线部署 location.reload(true) 相当于CTRL+F5 Chrome忽略Expires,保留Last-Modified与ETag 其他浏览器取消所有缓存有关头,或添加Cache-Control:no-cache头 location.reload(false) 相当于F5

39、 高版本浏览器忽略Expires,保留Last-Modified与ETag 上线部署 location.reload参数选择 Safari4-及Opera12-永远带Cache-Control: no- cache Chrome6-永远带Cache-Control: max-age=0 Safari5以false为参数会带有Cache-Control: max- age=0和Pragma: no-cache,导致某些服务器不响应304 考虑线上CDN、反向代理、负载均衡的策略 建议CDN等设施严格遵守HTTP/1.1 优先识别Cache-Control头 存在Cache-Control头的情况

40、下忽略Pragma头 前端设施实现正确的前提下,使用true作为参数 http:/ 上线部署 做好向后兼容 用户永远不会配合你更新自己的代码 下,m.js / s.js / o.js是同一个文件 addSlot / enableAllSlots都是空函数 singleFillSlot / fillSlot是同一个函数 线上入口.js文件有缓存期 .js文件上线后不可能立刻生效 后端逻辑升级时特别注意是否可兼容缓存的部分逻辑 可选择前端上线 缓存失效 后端上线的步骤 使用灰度上线(抽样小流量)机制 上线部署 做好线上监控 统计用户环境 Quirks模式比率 发现新的逻辑分支 从URL提取域名的正

41、则表达式覆盖是否全面 利于问题的排查 API函数是否有被拦截 实时检测DOM发现问题 仅在问题存在时发送日志 尽可能打消用户对隐私窥探等的顾虑 问题排查 文件代 理 性能 排查 自动 化 问题排查 代理线上文件 正向代理 Fiddler (Windows) Charles (MAC / Linux) WireShark (底层拦截) 性能问题排查 dynaTrace 支持IE和Firefox Firebug(Console-Profile) / Developer Tool(Profiles) 问题排查 性能问题排查 - dynaTrace 问题排查 性能问题排查 - dynaTrace 问题排查 排查过程自动化 phantomjs 成熟、社区庞大 新版取消xvfb依赖,不支持Flash等插件 berserkJS 中文文档、技术支持近在眼前 新生事物,难免存在问题 Selenium 多浏览器支持 无法脱离浏览器独立执行,依赖GUI DONE THANKS

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 其他


经营许可证编号:宁ICP备18001539号-1