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

更新日期: 2018-01-15 阅读次数: 13809 分类: 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"

关于作者 🌱

我是来自山东烟台的一名开发者,有敢兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊, 查看更多联系方式