避免三方 js 文件被重复加载

更新日期: 2018-01-15 阅读次数: 5736 分类: Javascript

问题

想在 web 统一模板中引入 jquery 和 vuejs,但是部分页面之前已经引入了。 如果想引入这两个库,但是又不影响已存在的页面使用。例如,对 ajax 请求统一修改了 header 加入了 csrf token, 但是如果再次引入 jquery, 就会导致配置被重置。

思路

判断一个库是否已经引入,如果引入了,就不再引入。

实现

<script>
if (condition) {
    document.write('<script src=\"https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js\" type=\"text/javascript\"><\/script>');
}
</script>

condition 就是判断是否已经载入

if (typeof someObject != "undefined") {
   // do something
}

但是,document.write 引起了 console 报错

A Parser-blocking, cross site (i.e. different eTLD+1) script, https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js, is invoked via document.write. The network request for this script MAY be blocked by the browser in this or a future page load due to poor network connectivity. If blocked in this page load, it will be confirmed in a subsequent console message.See https://www.chromestatus.com/feature/5718547946799104 for more details.

https://stackoverflow.com/questions/39610829/a-parser-blocking-cross-origin-script-is-invoked-via-document-write-how-to-ci

Use asynchronous script loading, using <script src="..." async> or element.appendChild(),

document.write 被阻止的原因, document write 会阻塞页面 parser。

https://developers.google.com/web/updates/2016/08/removing-document-write

If your provider gives you a snippet that includes the document.write(), it might be possible for you to add an async attribute to the script element, or for you to add the script elements with DOM API's like document.appendChild() or parentNode.insertBefore() much like Google Analytics does.

<script>
var s=document.createElement('script');
s.src='someScript.js';
document.body.appendChild(s);
</script>

而 appendChild 不会,但是需要注意的是,这样引入的 js 文件相当于异步加载,无法保证执行顺序。

所以,当我需要顺序引入 jQuery, VueJS, 以及我自己的 js 文件时,这个加载顺序就非常不好保证。

最终方案

我决定修改后台架构,将已引入 js 的页面,做规范化。即,强制规范 js 的引入顺序。类似 wordpress 的实现方案。

通用 js 在 Laravel blade 模板中提前引入,自定义 js 滞后引入。不允许页面中随意引入 js。

测试 VueJS

已加载 VueJS 的页面

> typeof Vue
"function"

未加载 VueJS 的页面

> typeof Vue
"undefined"

测试 jQuery

已加载 jQuery 的页面

> typeof Vue
"function"

未加载 jQuery 的页面

> typeof Vue
"undefined"

爱评论不评论

近期节日

2019年09月18日 "九一八"事变纪念日
2019年09月20日 国际爱牙日
2019年09月21日 国际和平日
2019年09月22日 世界无车日
2019年09月23日 秋分
2019年09月23日 国际聋人节
2019年09月27日 世界旅游日
2019年10月01日 国庆节
2019年10月04日 世界动物日
2019年10月07日 重阳节
2019年10月08日 寒露
2019年10月09日 世界邮政日
查看更多节日