性能优化很常见的一个方式是提前加载文件,本文讨论如何在其他依赖未加载情况下提前加载一个.js文件。
如果使用<script>
加载一个js 文件,如果加载的js 是一个自执行文件,那么会出现错误。
// test.js
(function test() {
bluer();
console.log(1)
})();
// test.html
<body>
<script src="/test.js"></script>
</body>
使用<script>
标签会进行加载和执行,由于没有加载依赖函数bluer
,控制台会出现以下问题:
test.js:2 Uncaught ReferenceError: bluer is not defined
如果要正确加载,可以在加载js 时是一个函数
//test2.js
function test() {
bluer();
console.log(1)
}
像这样改造之后确实是可以在提前在任何阶段加载js,但是改造成本比较大。
可以使用xhr 或者 fetch 来获取js 文件,可以得到js 字符串,在需要获取的时候在使用eval
方法进行调用,以下以fetch 为例,具体调用如下:
fetch('/test.js').then(response => {
return response.text();
}).then(data => {
console.log(data);
})
但是一般来说.js 是cdn, 可能出现域名不同的情况,会有跨域问题,而且eval执行也会存在某些问题。
preload 会强制浏览器立即获取资源,并且该请求具有较高的优先级。并且是在不阻塞 document
的 onload 事件的情况下请求资源。具体是使用。rel属性常用如下:
<link rel="preload" as="script" href="test.js">
<script>
function execScript(url){
const script = document.createElement("script");
script.src = url;
document.body.appendChild(script);
}
//某个时机执行,已加载依赖bluer函数
function bluer() {
//do something;
}
setTimeout(function(){
execScript("test.js")
},1000)
</script>
当preload 方式发现不兼容(caniuse 查询)时,可以使用Image
来实现,Image
对象的src 属性可以设置资源url,通过这个方式我们可以提前拉取资源。
<script>
let img = new Image();
img.src = 'test.js'
function execScript(url){
const script = document.createElement("script");
script.src = url;
document.body.appendChild(script);
}
//某个时机执行,已加载依赖bluer函数
function bluer() {
//do something;
}
setTimeout(function(){
execScript("test.js")
},1000)
</script>
[1]https://www.w3.org/TR/preload/#x2.link-type-preload
[2]https://blog.fundebug.com/2019/04/11/understand-preload-and-prefetch/