加载第三方JS的各样姿势
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">(点击</span><span style="color: black;">上方公众号</span><span style="color: black;">,可快速关注)</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">作者:zmmbreeze / @zhoumm </span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">zencode.in/22.加载第三方JS的<span style="color: black;">各样</span>姿势.html</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><a style="color: black;">如有好<span style="color: black;">文案</span>投稿,请点击 → <span style="color: black;">这儿</span><span style="color: black;">认识</span>详情</a></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">网页中加载JS文件是一个老问题了,<span style="color: black;">已然</span>被讨论了一遍又一遍,<span style="color: black;">这儿</span>不会再赘述<span style="color: black;">各样</span>经典的<span style="color: black;">处理</span><span style="color: black;">方法</span>。JS文件<span style="color: black;">能够</span><span style="color: black;">经过</span><span style="color: black;">源自</span>来分为两个纬度:<span style="color: black;">第1</span>方JS和第三方JS。<span style="color: black;">第1</span>方JS是网页<span style="color: black;">研发</span>者自己<span style="color: black;">运用</span>的JS代码(内容<span style="color: black;">研发</span>者可控)。而第三方JS则是其他服务<span style="color: black;">供给</span>商<span style="color: black;">供给</span>的(内容<span style="color: black;">研发</span>者不可控),<span style="color: black;">她们</span>将自己的服务包装成JS SDK供网页<span style="color: black;">研发</span>者<span style="color: black;">运用</span>。这篇<span style="color: black;">文案</span>关注的第三方JS文件的加载。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">从网站<span style="color: black;">研发</span>者的<span style="color: black;">方向</span>来看,第三方JS相比<span style="color: black;">第1</span>方JS有如下几个<span style="color: black;">区别</span>之处:</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">下载速度不可控</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">JS<span style="color: black;">位置</span>域名与网站域名<span style="color: black;">区别</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">文件内容不可控</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">不<span style="color: black;">必定</span>有强缓存(Cache-Control/Expires)</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">倘若</span>你的网站上面有<span style="color: black;">非常多</span>第三方JS代码,<span style="color: black;">那样</span>“下载速度的不可控”<span style="color: black;">特别有</span>可能导</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">致你的网站会被拖慢。<span style="color: black;">由于</span>JS在执行的时候会影响到页面的DOM和样式等<span style="color: black;">状况</span>。浏览器在解析渲染HTML的时候,<span style="color: black;">倘若</span>解析到需要下载文件的script标签,<span style="color: black;">那样</span>会停止解析接下来的HTML,<span style="color: black;">而后</span>下载外链JS文件并执行。等JS执行完毕之后才会继续解析剩下的HTML。这<span style="color: black;">便是</span><span style="color: black;">所说</span>的『HTML解析被阻止』。浏览器解析渲染页面的抽象流程图如下:</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><img src="http://mmbiz.qpic.cn/mmbiz_png/zPh0erYjkib0Y9pL1ic7vEKiaGiagGkvZcZqRLXETVu7hojGVMOFEicgbZcuM97o4bibKe3xTMamHKBVpd1Kg5ejrK4A/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" style="width: 50%; margin-bottom: 20px;"></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">第三方JS代码并不受网站<span style="color: black;">研发</span>者的<span style="color: black;">掌控</span>,<span style="color: black;">特别有</span>可能会<span style="color: black;">显现</span>加载时间长<span style="color: black;">乃至</span>加载失败的<span style="color: black;">状况</span>。<span style="color: black;">此时</span>候就会<span style="color: black;">引起</span><span style="color: black;">全部</span>页面的加载速度变慢。第三方JS代码越多这种<span style="color: black;">危害</span>越大。<span style="color: black;">根据</span>互联网守则:</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">网站加载速度越慢,用户流失越多</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">因此</span>要<span style="color: black;">思虑</span>下<span style="color: black;">怎样</span>在有<span style="color: black;">非常多</span>第三方JS的<span style="color: black;">状况</span>下,<span style="color: black;">保准</span><span style="color: black;">她们</span>不影响到网站自己的加载速度。<span style="color: black;">咱们</span><span style="color: black;">能够</span>异步加载这些第三方JS代码。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><strong style="color: blue;">异步加载</strong></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">异步加载JS的<span style="color: black;">办法</span><span style="color: black;">非常多</span>,最<span style="color: black;">平常</span>的<span style="color: black;">便是</span>动态创建一个script标签,<span style="color: black;">而后</span>设置其src和async属性,再<span style="color: black;">插进</span>到页面中。<span style="color: black;">这儿</span>有个DEMO。<span style="color: black;">实质</span>操作的代码如下:</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><script></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">function</span><span style="color: black;">loadScript</span><span style="color: black;">(</span><span style="color: black;">url</span><span style="color: black;">)</span><span style="color: black;">{</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">var</span><span style="color: black;">scrs</span><span style="color: black;"> = </span><span style="color: black;">document</span><span style="color: black;">.</span><span style="color: black;">getElementsByTagName</span><span style="color: black;">(</span><span style="color: black;">script</span><span style="color: black;">);</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">var</span><span style="color: black;">last</span><span style="color: black;"> = </span><span style="color: black;">scrs</span><span style="color: black;">[</span><span style="color: black;">scrs</span><span style="color: black;">.</span><span style="color: black;">length</span><span style="color: black;"> - </span><span style="color: black;">1</span><span style="color: black;">];</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">var</span><span style="color: black;">scr</span><span style="color: black;"> = </span><span style="color: black;">document</span><span style="color: black;">.</span><span style="color: black;">createElement</span><span style="color: black;">(</span><span style="color: black;">script</span><span style="color: black;">);</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">scr</span><span style="color: black;">.</span><span style="color: black;">src</span><span style="color: black;"> = </span><span style="color: black;">url</span><span style="color: black;">;</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">scr</span><span style="color: black;">.</span><span style="color: black;">async</span><span style="color: black;"> = </span><span style="color: black;">true</span><span style="color: black;">;</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">last</span><span style="color: black;">.</span><span style="color: black;">parentNode</span><span style="color: black;">.</span><span style="color: black;">insertBefore</span><span style="color: black;">(</span><span style="color: black;">scr</span><span style="color: black;">,</span><span style="color: black;">last</span><span style="color: black;">);</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">}</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">loadScript</span><span style="color: black;">(</span><span style="color: black;">test.js</span><span style="color: black;">);</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"></script></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">PS:为了避免IE8以前版本的bug,并且<span style="color: black;">保证</span>script能<span style="color: black;">插进</span>DOM树,<span style="color: black;">因此</span><span style="color: black;">这儿</span><span style="color: black;">无</span>直接document.body.append(src),而是调用了insertBefore<span style="color: black;">办法</span>。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">改成异步加载第三方JS代码之后,在JS的下载过程中浏览器会继续解析渲染HTML。流程图就变<span style="color: black;">成为了</span>如下:</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><img src="http://mmbiz.qpic.cn/mmbiz_png/zPh0erYjkib0Y9pL1ic7vEKiaGiagGkvZcZqkXVhUQxowH1KFFE4mhicJpwvSYKSREcjT4wHkMhUQp98K1xAC1QIiaxQ/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" style="width: 50%; margin-bottom: 20px;"></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">由于</span>loadScript的操作<span style="color: black;">亦</span>是<span style="color: black;">运用</span>JS实现的,<span style="color: black;">因此</span>在JS下载之前会有一段执行JS代码的消耗。<span style="color: black;">然则</span>这段JS代码很简单,<span style="color: black;">火速</span>就会执行完毕。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">除了动态创建script标签的<span style="color: black;">办法</span>,异步加载JS的<span style="color: black;">办法</span>还有<span style="color: black;">非常多</span>其他奇技淫巧,<span style="color: black;">这儿</span><span style="color: black;">亦</span><span style="color: black;">陈列</span>了一下:</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">先下载再执行 – <span style="color: black;">经过</span>XMLHttpReqeust对象<span style="color: black;">或</span>JSONP<span style="color: black;">办法</span>下载可执行的JS文件,<span style="color: black;">而后</span><span style="color: black;">运用</span>eval()或者script标签执行JS。第三方JS文件<span style="color: black;">通常</span>是<span style="color: black;">区别</span>域名的且JS内容不可控,<span style="color: black;">因此</span>此<span style="color: black;">办法</span>就不适用了</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">iframe中加载JS – 将你的JS文件直接放到另一个页面的HTML中,<span style="color: black;">而后</span>将此页面URL<span style="color: black;">位置</span><span style="color: black;">做为</span>iframe标签src属性。此<span style="color: black;">办法</span>需要<span style="color: black;">增多</span>一次页面请求,<span style="color: black;">况且</span><span style="color: black;">由于</span>是在iframe内部执行了,第三方JS文件本身<span style="color: black;">亦</span>需要修改,故并不是很适用</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">先缓存再执行 – 利用JS文件的强缓存,先<span style="color: black;">运用</span>new Image().src = http://url.com/sample.js之类(<span style="color: black;">或</span>Object对象)的<span style="color: black;">办法</span>下载JS文件。<span style="color: black;">而后</span>在真正需要解析执行JS的时候下载(有缓存,不必再次下载)和执行JS文件。此<span style="color: black;">办法</span><span style="color: black;">不仅</span>适用于JS文件,<span style="color: black;">一样</span><span style="color: black;">亦</span><span style="color: black;">能够</span>用于CSS文件。<span style="color: black;">这般</span><span style="color: black;">咱们</span>就<span style="color: black;">能够</span>将静态文件的下载和解析执行(<span style="color: black;">运用</span>)<span style="color: black;">掰开</span>,批量并行下载,<span style="color: black;">而后</span>在合适的机会解析执行(<span style="color: black;">运用</span>)。但此<span style="color: black;">办法</span>需要强缓存的<span style="color: black;">协同</span>,第三方JS为了在版本发布时更早的更新JS代码<span style="color: black;">通常</span>都不会设置缓存,<span style="color: black;">乃至</span>有些第三方JS的代码是服务器端动态生成的。<span style="color: black;">因此</span><span style="color: black;">亦</span>不是适用于第三方JS。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><strong style="color: blue;">浏览器预加载机制</strong></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">动态创建script标签的<span style="color: black;">办法</span><span style="color: black;">能够</span>异步加载第三方JS,但它<span style="color: black;">亦</span>有缺陷。<span style="color: black;">倘若</span>加载代码之前有外链JS文件或CSS文件需要下载,如下面的代码:</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;"><script </span><span style="color: black;">src</span><span style="color: black;">=</span><span style="color: black;">"app1.js"</span><span style="color: black;">></span><span style="color: black;"></script></span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;"><script </span><span style="color: black;">src</span><span style="color: black;">=</span><span style="color: black;">"app2.js"</span><span style="color: black;">></span><span style="color: black;"></script></span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><script></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">function</span><span style="color: black;">loadScript</span><span style="color: black;">(</span><span style="color: black;">url</span><span style="color: black;">)</span><span style="color: black;">{</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">var</span><span style="color: black;">scrs</span><span style="color: black;"> = </span><span style="color: black;">document</span><span style="color: black;">.</span><span style="color: black;">getElementsByTagName</span><span style="color: black;">(</span><span style="color: black;">script</span><span style="color: black;">);</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">var</span><span style="color: black;">last</span><span style="color: black;"> = </span><span style="color: black;">scrs</span><span style="color: black;">[</span><span style="color: black;">scrs</span><span style="color: black;">.</span><span style="color: black;">length</span><span style="color: black;"> - </span><span style="color: black;">1</span><span style="color: black;">];</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">var</span><span style="color: black;">scr</span><span style="color: black;"> = </span><span style="color: black;">document</span><span style="color: black;">.</span><span style="color: black;">createElement</span><span style="color: black;">(</span><span style="color: black;">script</span><span style="color: black;">);</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">scr</span><span style="color: black;">.</span><span style="color: black;">src</span><span style="color: black;"> = </span><span style="color: black;">url</span><span style="color: black;">;</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">scr</span><span style="color: black;">.</span><span style="color: black;">async</span><span style="color: black;"> = </span><span style="color: black;">true</span><span style="color: black;">;</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">last</span><span style="color: black;">.</span><span style="color: black;">parentNode</span><span style="color: black;">.</span><span style="color: black;">insertBefore</span><span style="color: black;">(</span><span style="color: black;">scr</span><span style="color: black;">,</span><span style="color: black;">last</span><span style="color: black;">);</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">}</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">loadScript</span><span style="color: black;">(</span><span style="color: black;">test.js</span><span style="color: black;">);</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"></script></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">那样</span>会先下载解析app1.js和app2.js再执行<span style="color: black;">咱们</span>的loadScript<span style="color: black;">办法</span>,<span style="color: black;">因此</span>第三方脚本的下载<span style="color: black;">亦</span>会被暂停。流程图如下:</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><img src="http://mmbiz.qpic.cn/mmbiz_png/zPh0erYjkib0Y9pL1ic7vEKiaGiagGkvZcZquvYfckPBIzxqWJQGoibewy3ZpsxoUdxicb5y5o9hRQMV0copmgTXDSBg/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" style="width: 50%; margin-bottom: 20px;"></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">而如今<span style="color: black;">咱们</span>页面中代码如此<span style="color: black;">繁杂</span>,触发这种case的<span style="color: black;">状况</span><span style="color: black;">非常多</span>。上面的DEMO中<span style="color: black;">实质</span>下载过程<span style="color: black;">亦</span>确实是<span style="color: black;">这般</span>,动态创建script标签方式下载的test.js需要等到其他CSS和JS文件下载执行完毕之后才<span style="color: black;">起始</span>下载。如下图:</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><img src="http://mmbiz.qpic.cn/mmbiz_png/zPh0erYjkib0Y9pL1ic7vEKiaGiagGkvZcZqpweYhFJcqQsnXYKO8ZwKVcuoOIH4NUicWv6UwkbK6rdDzrUTKM9WrSA/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" style="width: 50%; margin-bottom: 20px;"></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">虽然这对页面原有JS的执行不会有大的影响,但会影响到第三方JS代码本身的下载与执行。<span style="color: black;">怎样</span><span style="color: black;">处理</span>这个问题呢?</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">你可能<span style="color: black;">已然</span><span style="color: black;">发掘</span>上面的例子有个问题:HTML代码中g.js的位置在test.js之后却先下载了。其实这得益于浏览器的预解析机制,会先对HTML代码做静态分析找到外链的JS和CSS文件,<span style="color: black;">而后</span>并行下载下来(<span style="color: black;">然则</span>执行<span style="color: black;">次序</span>不变)。IE>=8 及其他主流浏览器基本都实现了这个功能。<span style="color: black;">因此</span>在这些支持预先载的浏览器中流程图应该是<span style="color: black;">这般</span>的:</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><img src="http://mmbiz.qpic.cn/mmbiz_png/zPh0erYjkib0Y9pL1ic7vEKiaGiagGkvZcZqTpMbmpMTouz53BMLTut76uNia5SAXzUp8FoZbe9jCgMOZHsuz2AauBA/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" style="width: 50%; margin-bottom: 20px;"></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">为了利用预加载这个特性,<span style="color: black;">咱们</span><span style="color: black;">能够</span><span style="color: black;">运用</span>如下的写法:</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;"><script </span><span style="color: black;">src</span><span style="color: black;">=</span><span style="color: black;">"app1.js"</span><span style="color: black;">></span><span style="color: black;"></script></span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;"><script </span><span style="color: black;">src</span><span style="color: black;">=</span><span style="color: black;">"app2.js"</span><span style="color: black;">></span><span style="color: black;"></script></span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;"><script </span><span style="color: black;">src</span><span style="color: black;">=</span><span style="color: black;">"./test.js"</span><span style="color: black;">async</span><span style="color: black;">></span><span style="color: black;"></script></span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">运用</span>标准的script标签写法,<span style="color: black;">保证</span>浏览器能够正确的识别这是一个外链JS文件。<span style="color: black;">同期</span>设置async标签,浏览器便会异步加载test.js文件,不会暂停掉浏览器的解析执行。流程图如下:</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><img src="http://mmbiz.qpic.cn/mmbiz_png/zPh0erYjkib0Y9pL1ic7vEKiaGiagGkvZcZqUQviaRChTzSzJbic7wLzw1JcdolUCJGSBb01fMs9exVZrK4s7ynxNZBQ/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" style="width: 50%; margin-bottom: 20px;"></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">这儿</span>有一个DEMO(http://zmmbreeze.github.io/blog/demo/load_script/async_script.html)。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">但它<span style="color: black;">亦</span>并不完美,<span style="color: black;">由于</span><span style="color: black;">有些</span>旧浏览器并不支持async属性。这会<span style="color: black;">引起</span>这个test.js文件在这些浏览器中不是异步的,并且会阻止掉页面渲染。有一个好<span style="color: black;">信息</span>是移动浏览器大多都支持async标签,<span style="color: black;">倘若</span>你的用户大都是移动浏览器的,<span style="color: black;">或</span>你的<span style="color: black;">制品</span>不支持旧浏览器,<span style="color: black;">那样</span>你<span style="color: black;">能够</span><span style="color: black;">运用</span>这种<span style="color: black;">办法</span>。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">当然<span style="color: black;">倘若</span>你不介意第三方JS代码(本身<span style="color: black;">亦</span>支持支持)被延后到页面解析完毕后执行,<span style="color: black;">那样</span>你<span style="color: black;">能够</span>再加上defer属性:</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><script src="./test.js" async defer></script></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">Firefox支持defer属性要比支持async早一点点。<span style="color: black;">况且</span>当浏览器<span style="color: black;">同期</span><span style="color: black;">运用</span>了async和defer属性之后,浏览器会忽略defer属性。<span style="color: black;">因此</span><span style="color: black;">能够</span><span style="color: black;">安心</span>的<span style="color: black;">同期</span><span style="color: black;">运用</span>async和defer属性。<span style="color: black;">针对</span>不支持async的浏览器,会自动fallback到defer。<span style="color: black;">不外</span>支持程度<span style="color: black;">亦</span>就多了一点点,Firefox的旧版占比<span style="color: black;">已然</span>很低了,基本<span style="color: black;">能够</span>忽略不计。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><strong style="color: blue;">页面onload事件</strong></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">上面<span style="color: black;">说到</span>的两种<span style="color: black;">办法</span>还有一个缺点:会影响到页面的onload事件。这对<span style="color: black;">第1</span>方JS可能<span style="color: black;">无</span>影响,<span style="color: black;">由于</span><span style="color: black;">第1</span>方JS大都是页面<span style="color: black;">重点</span><span style="color: black;">规律</span>,从业务<span style="color: black;">规律</span>上<span style="color: black;">来讲</span>它们的加载影响到页面onload事件触发不会有问题。但第三方JS则不<span style="color: black;">同样</span>,曾经<span style="color: black;">由于</span>Google被墙GA(Google Analytics简<span style="color: black;">叫作</span>)的加载就会<span style="color: black;">尤其</span>慢<span style="color: black;">乃至</span>失败。<span style="color: black;">引起</span>了<span style="color: black;">非常多</span><span style="color: black;">运用</span>了GA的页面加载<span style="color: black;">尤其</span>”慢”,页面<span style="color: black;">始终</span><span style="color: black;">处在</span>loading状态。<span style="color: black;">大众</span>先<span style="color: black;">经过</span>fiddler代理来设置test.js的加载时间为10秒,<span style="color: black;">而后</span>打开之前的DEMO,查看页面的loading<span style="color: black;">是不是</span>会被延长。下面是我打开<span style="color: black;">第1</span>个DEMO的结果:</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><img src="http://mmbiz.qpic.cn/mmbiz_gif/zPh0erYjkib0Y9pL1ic7vEKiaGiagGkvZcZqWSlibvDpkrdwvvJnrkomHrOvdqZERwJWczPrERrLib662EgSbCW4fw1w/0?wx_fmt=gif&tp=webp&wxfrom=5&wx_lazy=1" style="width: 50%; margin-bottom: 20px;"></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">能够</span>看到<span style="color: black;">由于</span>test.js的下载速度变慢,<span style="color: black;">全部</span>页面<span style="color: black;">始终</span><span style="color: black;">处在</span>loading状态。页面的load事件要等到<span style="color: black;">所有</span>加载完成之后才会触发。<span style="color: black;">倘若</span>页面中的<span style="color: black;">重点</span><span style="color: black;">规律</span>是在页面load之后再执行,<span style="color: black;">那样</span>页面很可能会在很长一段时间内不可用。<span style="color: black;">极重</span>的影响了用户的<span style="color: black;">运用</span>体验。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><strong style="color: blue;">Friendly IFrame<span style="color: black;">办法</span></strong></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">为<span style="color: black;">认识</span>决这个问题,meebo的工程师想了一个<span style="color: black;">方法</span>来<span style="color: black;">处理</span>这个问题:</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">(</span><span style="color: black;">function</span><span style="color: black;">(</span><span style="color: black;">url</span><span style="color: black;">){</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">// <span style="color: black;">第1</span>部分</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">var</span><span style="color: black;">dom</span><span style="color: black;">,</span><span style="color: black;">doc</span><span style="color: black;">,</span><span style="color: black;">where</span><span style="color: black;">,</span><span style="color: black;">iframe</span><span style="color: black;"> = </span><span style="color: black;">document</span><span style="color: black;">.</span><span style="color: black;">createElement</span><span style="color: black;">(</span><span style="color: black;">iframe</span><span style="color: black;">);</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">iframe</span><span style="color: black;">.</span><span style="color: black;">src</span><span style="color: black;"> = </span><span style="color: black;">"javascript:false"</span><span style="color: black;">;</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">iframe</span><span style="color: black;">.</span><span style="color: black;">title</span><span style="color: black;"> = </span><span style="color: black;">""</span><span style="color: black;">;</span><span style="color: black;">iframe</span><span style="color: black;">.</span><span style="color: black;">role</span><span style="color: black;">=</span><span style="color: black;">"presentation"</span><span style="color: black;">;</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">(</span><span style="color: black;">iframe</span><span style="color: black;">.</span><span style="color: black;">frameElement</span><span style="color: black;"> || </span><span style="color: black;">iframe</span><span style="color: black;">).</span><span style="color: black;">style</span><span style="color: black;">.</span><span style="color: black;">cssText</span><span style="color: black;"> = </span><span style="color: black;">"width: 0; height: 0; border: 0"</span><span style="color: black;">;</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">where</span><span style="color: black;"> = </span><span style="color: black;">document</span><span style="color: black;">.</span><span style="color: black;">getElementsByTagName</span><span style="color: black;">(</span><span style="color: black;">script</span><span style="color: black;">);</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">where</span><span style="color: black;"> = </span><span style="color: black;">where</span><span style="color: black;">[</span><span style="color: black;">where</span><span style="color: black;">.</span><span style="color: black;">length</span><span style="color: black;"> - </span><span style="color: black;">1</span><span style="color: black;">];</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">where</span><span style="color: black;">.</span><span style="color: black;">parentNode</span><span style="color: black;">.</span><span style="color: black;">insertBefore</span><span style="color: black;">(</span><span style="color: black;">iframe</span><span style="color: black;">,</span><span style="color: black;">where</span><span style="color: black;">);</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">// 第二部分</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">try</span><span style="color: black;">{</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">doc</span><span style="color: black;"> = </span><span style="color: black;">iframe</span><span style="color: black;">.</span><span style="color: black;">contentWindow</span><span style="color: black;">.</span><span style="color: black;">document</span><span style="color: black;">;</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">}</span><span style="color: black;">catch</span><span style="color: black;">(</span><span style="color: black;">e</span><span style="color: black;">)</span><span style="color: black;">{</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">// IE下<span style="color: black;">倘若</span>主页面修改过document.domain,<span style="color: black;">那样</span><span style="color: black;">拜访</span>用js创建的匿名iframe会<span style="color: black;">出现</span>跨域问题,必须<span style="color: black;">经过</span>js伪协议修改iframe内部的domain</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">dom</span><span style="color: black;"> = </span><span style="color: black;">document</span><span style="color: black;">.</span><span style="color: black;">domain</span><span style="color: black;">;</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">iframe</span><span style="color: black;">.</span><span style="color: black;">src</span><span style="color: black;">=</span><span style="color: black;">"javascript:var d=document.open();d.domain="</span><span style="color: black;">+</span><span style="color: black;">dom</span><span style="color: black;">+</span><span style="color: black;">";void(0);"</span><span style="color: black;">;</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">doc</span><span style="color: black;"> = </span><span style="color: black;">iframe</span><span style="color: black;">.</span><span style="color: black;">contentWindow</span><span style="color: black;">.</span><span style="color: black;">document</span><span style="color: black;">;</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">}</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">doc</span><span style="color: black;">.</span><span style="color: black;">open</span><span style="color: black;">().</span><span style="color: black;">_l</span><span style="color: black;"> = </span><span style="color: black;">function</span><span style="color: black;">()</span><span style="color: black;">{</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">var</span><span style="color: black;">js</span><span style="color: black;"> = </span><span style="color: black;">this</span><span style="color: black;">.</span><span style="color: black;">createElement</span><span style="color: black;">(</span><span style="color: black;">"script"</span><span style="color: black;">);</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">if</span><span style="color: black;">(</span><span style="color: black;">dom</span><span style="color: black;">)</span><span style="color: black;">this</span><span style="color: black;">.</span><span style="color: black;">domain</span><span style="color: black;"> = </span><span style="color: black;">dom</span><span style="color: black;">;</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">js</span><span style="color: black;">.</span><span style="color: black;">id</span><span style="color: black;"> = </span><span style="color: black;">"js-iframe-async"</span><span style="color: black;">;</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">js</span><span style="color: black;">.</span><span style="color: black;">src</span><span style="color: black;"> = </span><span style="color: black;">url</span><span style="color: black;">;</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">this</span><span style="color: black;">.</span><span style="color: black;">body</span><span style="color: black;">.</span><span style="color: black;">appendChild</span><span style="color: black;">(</span><span style="color: black;">js</span><span style="color: black;">);</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">};</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">doc</span><span style="color: black;">.</span><span style="color: black;">write</span><span style="color: black;">(</span><span style="color: black;"><body onload="document._l();"></span><span style="color: black;">);</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">doc</span><span style="color: black;">.</span><span style="color: black;">close</span><span style="color: black;">();</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">})(</span><span style="color: black;">test.js</span><span style="color: black;">);</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">以上</span>代码分为两个部分:</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">创建了一个<span style="color: black;">隐匿</span>的iframe标签,设置其src值为JS代码,<span style="color: black;">而后</span><span style="color: black;">插进</span>到主页面中</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">在iframe标签load之后加载JS脚本</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">这般</span>加载Javascript,就不会阻止浏览器的onload事件,<span style="color: black;">提高</span>普通用户的体验。还有另一个好处:第三方的Javascript代码在独立的iframe中运行,不会与主页面中的JS相互干扰。<span style="color: black;">已然</span>有了<span style="color: black;">有些</span>基于这个想法的开源实现,例如:lightning.js是一个专用于快速、安全、异步地加载第三方JS代码的库。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">这个<span style="color: black;">办法</span><span style="color: black;">亦</span>不完美,它需要创建一个iframe标签<span style="color: black;">引起</span>了开销<span style="color: black;">很强</span>。<span style="color: black;">同期</span>还需要第三方JS本身的支持。第三方JS代码运行在iframe中,<span style="color: black;">引起</span>它<span style="color: black;">没法</span>获取到页面上的信息。虽然它并非跨域<span style="color: black;">能够</span><span style="color: black;">得到</span>window.parent,<span style="color: black;">然则</span>第三方代码并<span style="color: black;">不可</span><span style="color: black;">晓得</span>自己<span style="color: black;">是不是</span>在iframe中,需要在加载第三方JS代码的时候<span style="color: black;">通告</span>它。<span style="color: black;">详细</span>的<span style="color: black;">通告</span><span style="color: black;">办法</span>千变万化,而第三方JS的内容又不受<span style="color: black;">咱们</span><span style="color: black;">掌控</span>。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">富<span style="color: black;">媒介</span><span style="color: black;">宣传</span>JS(用于展示交互<span style="color: black;">宣传</span>的JS)<span style="color: black;">通常</span>都会运行在隔离环境里面,且不需要(不<span style="color: black;">准许</span>)<span style="color: black;">拜访</span><span style="color: black;">外边</span>的window对象。<span style="color: black;">倘若</span>你需要加载的第三方JS<span style="color: black;">所有</span>是<span style="color: black;">宣传</span>时,<span style="color: black;">那样</span><span style="color: black;">运用</span>这个<span style="color: black;">方法</span>是OK的,否则并不是最为合适。幸运的是有一个叫iAB(The Interactive Advertising Bureau,简<span style="color: black;">叫作</span>iAB)的组织,<span style="color: black;">创立</span>了一套工业级标准。虽然标准<span style="color: black;">已然</span>比较旧了,<span style="color: black;">然则</span>里面<span style="color: black;">说到</span>了<span style="color: black;">经过</span>设置变量inDapIF为true来<span style="color: black;">通告</span>第三方JS:你<span style="color: black;">此刻</span>正运行在iframe中。<span style="color: black;">由于</span>iAB成员较多影响力大,<span style="color: black;">因此</span>遵循这个标准是有好处的,比起自己玩一套要好的多。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><strong style="color: blue;">总结</strong></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><img src="http://mmbiz.qpic.cn/mmbiz_png/zPh0erYjkib0Y9pL1ic7vEKiaGiagGkvZcZqqWOshGtlyNwb3I3G5Jm309L5SM7PcwR06cShVvhedZk7nLQ4pUeiaPw/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" style="width: 50%; margin-bottom: 20px;"></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">觉得本文对你有<span style="color: black;">帮忙</span>?请分享给<span style="color: black;">更加多</span>人</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;"><span style="color: black;">关注「前端大全」,<span style="color: black;">提高</span>前端技能</span></strong></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><img src="http://mmbiz.qpic.cn/mmbiz_png/zPh0erYjkib0lZCEKibSLcyLMVa3iaNzhWkSPnEBk28r5AAcL4fS03LQn1RWA5M58d7kvysRCibKpHibjs1szyRmnOQ/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" style="width: 50%; margin-bottom: 20px;"></p>
页:
[1]