所以这里我们只谈以应用为主的网站。为了满足尽快显示该有的元素,先将脚本模块化:负责页面显示的脚本按Level依次穿插到body中,或者某些小脚本必须提前加载那就干脆把它放到head里。这里不免要说网络请求的问题,如果模块太多,每个小脚本都请求一次,这样很不划算,要知道网络I/O是特耗时的。有时在脚本大小很小的时候,可以将这些小脚本合并为一个文件以减少HTTP请求的次数。最后把允许等待的脚本放到body尾。也可以利用ajax异步请求脚本字符串并用eval()执行或者用DOM API 动态创建script标签,随时请求需要的脚本。
好像挺完美。madei!?我们刚才只讨论了脚本的加载,那它们究竟何时执行?lt’s a serious question !
先来说说为什么会有前两种观点。将Script标签放到哪里并不绝对,两种方式都没有错,要说错就错在乱放上。
最原始的head法是为脚本优先而生的。众所周知,放在head标签里的东西无一例外优先于body加载。 但缺点是太大的文件会增加页面的加载时间(也就是用户等待时问),这多影响人的心情啊!
因此有了在body末尾放脚本一说。对于页面内容优先的网页来说,这的确大大减少了等待时间,不过对于富客户端的Web2.0 app来说,这种选择也是种煎熬:丑陋的框框早早摆在那里,然后等着美化页面和提供交互能力的脚本慢吞吞能加载。特别是对于那些完美主义者们,如果你当真把这种页面给他们看,那就别奢望他们会用你的app了。
那该怎么办?下面就来说说第三类方法:
首先确认你的网站类型:信息资讯?社交网络?游戏?博客、首页?实用工具app、云计算服务平台(网盘、聊天室、在线翻译、云办工、项目管理协作等重量级应用)
不同目地的网站逻辑复杂度亦不同,对交互能力的要求也千差万别。拿云办工为例,它提供在线编辑文档、实时同步备份数据,外加一大堆其它功能。这是一个本地桌面应用的Web版,也就说它对交互能力的要求极高,且基本上90%的交互逻辑都在浏览器中,这就完全依赖脚本了。这种应用级网站的脚本加载异常重要,没了脚本的支持活不了。而像提供资讯那种以信息传播为目的网站却对交互能力要求不高:没了脚本我照样能跑。
所以这里我们只谈以应用为主的网站。为了满足尽快显示该有的元素,先将脚本模块化:负责页面显示的脚本按Level依次穿插到body中,或者某些小脚本必须提前加载那就干脆把它放到head里。这里不免要说网络请求的问题,如果模块太多,每个小脚本都请求一次,这样很不划算,要知道网络I/O是特耗时的。有时在脚本大小很小的时候,可以将这些小脚本合并为一个文件以减少HTTP请求的次数。最后把允许等待的脚本放到body尾。也可以利用ajax异步请求脚本字符串并用eval()执行或者用DOM API 动态创建script标签,随时请求需要的脚本。
好像挺完美。madei!?我们刚才只讨论了脚本的加载,那它们究竟何时执行?lt’s a serious question !
跑起脚本
刚才的方法中我们提到“将脚本模块化并依次插入到各元素之间”。不过在老式浏览器中并不会产生多大改变:脚本加载后并不会马上执行,而是继续加载DOM向下完善整个文档树直到最后一个元素加载完毕。
所幸HTML5中为script标签提供了
async
和defer
属性。大多数现代浏览器都支持这两个标签。指定了
defer
属性的标签会进行异步加载:在加载脚本的同时无阻塞地加载body内的其它元素,等到之前指定了aSync属性的标签全部加载完毕后脚本开始执行。而async
属性比defer
更无限制:异步无阻塞加载并立那执行脚本。一旦带有该属性的标签加载完毕便立即运行,不管其它元素和脚本是否加载完。这点很像Node中的异步无阻塞模型。OK!现在有了这两个强大的功能,就可以完美地实现我们的目地啦!