如何才能按需加载脚本?

本文提出问题,并不解决问题。

我在研究Extended Live Archive(ELA)插件的代码,发现一个问题,这个问题具有一定的共性,而且,我现在也没有什么好的解决办法,所以我把它描述一下,看看有没有高人高见。

WP插件一般目标有两个,一个是增强博客页面功能,让观众有更好体验,另一个是增强博客管理页面功能,让博客管理者有更高管理效率。无论是哪一种,我们都经常会用到脚本,比如指定样式的CSS脚本,指定行为的JS脚本。好,现在问题来了,一般来说,我们使用插件增强的功能,都是在某个特定的页面上的功能,只有少数才是全局功能,直觉上,我们希望,在这个特定的页面上引入需要的脚本,而在其他的页面上不引入这段脚本。

我这个话说得有点绕,举个具体的例子。比如,某个插件,用于显示一个漂亮的相册,这个相册有一个自己专属的相册页面,这个相册的翻页功能需要用到prototype类库,你作为一个博客的主人,肯定是希望只有用户打开相册页面时,用户才需要下载prototype,平时看你的博客,不用每个页面都去下载一下prototype。(这个类库在没有pack的情况下128k大。)

希望我说清楚,这个问题概括成一句话,就是按需加载脚本,用到时,才下载。

事实上是这样的,我说得很轻巧,但是做起来却很难。就拿我手头的这个ELA来说事,这个插件是一个AJAX应用,用来展示一个结构化的归档目录。插件通过一个template tag提供用户接口,在调用这个template tag的页面,就会有归档目录出现。这个归档目录,必须要CSS文件来指定其样式,结果,我们的难点是,不知道用户会在哪个页面上调用这个tag,所以只能草草地把这个样式表hook到wp_head,导致的结果是,所有的页面上,都会链入这么一个样式表,而真正起作用的,只有一个页面而已。

我初步想了想,几乎想不出漂亮的办法能解决这个问题。这个问题的根本就在于,程序在执行到wp_head的时候,我们还没法知道后续的部分是不是会出现那个tag,而在真的执行到这个tag的时候,头部的内容已经形成了,我们回天乏力。一个直觉的办法,就是把那个样式表,直接也塞到tag的内部,事实上,插件的作者就是这么做的,不过,他只是把用到的JS脚本这么处理了,却没有把CSS这么处理,我猜想他代码写到这里的时候,可能内心也是非常矛盾的。(因为一个优秀的页面,就应该是数据、表现、行为分离的,这么做等于破坏了这个原则了)

好,到这里,问题应该算是说完了。其实这个问题相当普遍,只要我们需要将一个脚本添加到wp_head或者admin_head(对应的还有各自的footer部分),我们就面临着这个问题,你添加的东西,真的每个页面都需要么?如果是大多数页面需要,那还不是很浪费,最浪费的就是只有一个页面需要,而其他所有的页面都跟着增加负载。

WP的圈子里,有一种论调,就是插件用得越多,博客速度越慢,性能越差。我想,脚本没有能够做到按需加载,也算是造成这个论调的原因之一。

大家一起开动下脑筋吧~