阻塞
script标签与加载css的link标签一样,可能会阻塞页面的渲染,这取决于script标签的位置
当script标签放在head中时,浏览器检测到该标签,会暂停下载和解析脚本的操作。此时浏览器将页面的渲染放到次要位置,加载该script脚本内容在首要位置。因此阻塞渲染。
放到body末尾
既然如此,想必大家都想了,先让html内容加载完成,在加载script脚本就可以解决问题。的确这是一个不错的办法,可以减少首屏绘制时间。
Async
现代浏览器支持一种改变外部脚本加载行为的方法:在script标签中使用async属性。
不适用async:
下载脚本 --> 脚本下载完成 --> 浏览器等待其他脚本下载 --> 顺序执行脚本
使用async之后:
下载脚本 --> 脚本下载完成 --> 执行脚本
不需要等待其他脚本的加载,即可执行。且不会在下载时阻塞渲染。
不过这里存在脚本相互依赖导致的问题:
<script src='js/jquery.min.js' async></script>
<script src='js/myShell.js' async></script>
当myShell.js依赖了jquery.min.js,同时使用async ,会出现报错。
这是因为当mySehll.js比jquery.min.js更早完成下载,更早完成执行时,会发现找不到 $ (来自jquery库的定义的全局变量)
因此当你的多脚本之间保证没有相互依赖,那么可以使用async来提升页面首屏时间
或者使用 如下命令来把存在依赖的脚本合并位一个脚本:
// 类Unix
cat jquery.min.js myShell.js > scripts.js
// windows
type jquery.min.js myShell.js > scripts.js
然后引入合成之后的脚本,并使用async。
Alameda
Alameda是异步模块定义(AMD)模块加载器,他能确保脚本异步加载,同时遵循其依赖关系。
<script src="js/alameda.min.js" data-main="js/myShell" async></script>
// data-main默认后缀.js
还需要在在myShell.js中定义配置:
requirejs.config({
paths:{
jquery : "jquery.min"
}
});
require(["jquery"],function($){
// 可以使用$的代码 myShell.js
})
这样我们就可以通过使用Alameda引入存在依赖关系的脚本了。
Alameda是RequireJS的升级版,他需要现代浏览器特有的功能才能工作, 比如Promise。他们共享了完全兼容的API,因此你可以根据需求选择使用其中一个(浏览器的支持程度)