如标题所说,不受控制的 JS,主要是说在别人服务器上的,尤其是被 GFW 的,当然了,不只限于 JS 文件,CSS,图片什么的都可以,原理大同小异。
我的博客上面的资源,几乎所有的 JS,图片,都在自己的 CDN,剩下的在 VPS,只有 Google Analytics 和 Disqus 引用的第三方 JS。
事情需要从这个博客的 Theme,Namjagbarwa 说起,首页的 card 在 layout 之前,需要保证所有外部资源加载完毕,其代码类似于这样:
$(window).load(function() {
window.sr = window.ScrollReveal().reveal(cardName, {
afterReveal: function () {
if ($postsGrid) {
$postsGrid.masonry("layout");
}
}
});
});
没加载完的时候是一片空白。但是我加入了 Disqus 的评论个数的功能,引入了 count.js
,所以就导致了没翻墙的情况下,这个资源根本无法加载成功,阻塞了 $(window).load()
。
解决办法很巧妙,既然 $(window).load()
只会在所有资源加载完毕的时候触发,那太简单了,把 Disqus 干掉不就好了么。。当然不行,干掉了还怎么显示评论个数。
JS 对资源的判定标准是,Tag 里面有 src
Attribute,我们只需要把这个 Attribute 干掉,就能保证 $(window).load()
忽略掉这个 JS。
<script type="text/javascript">
(function () {
var s = document.createElement('script'); s.async = true;
s.type = 'text/javascript';
s.setAttribute('external_src', '//' + window.disqus_shortname + '.disqus.com/count.js');
(document.getElementsByTagName('HEAD')[0] || document.getElementsByTagName('BODY')[0]).appendChild(s);
}());
</script>
我们把 count.js
的 Attribute 设置为 external_src
,就不会再阻塞 rendering,但是资源也没法加载了咋弄,这就更容易了,在 load 之后遍历一下:
$(window).load(function() {
$('[external_src]').each(function() {
var external_src = $(this).attr("external_src");
$(this).attr("src", $(this).attr("external_src")).removeAttr("external_src");
});
});
这样就完美解决了。