MediaWiki中widget脚本的异步加载方式

2015-11-28 18:21:35

[开发运维 | Dev Ops] ,

最近玩mediawiki比较多,感觉mediawiki扩展方面做得真的不错,API方面,完善的日志功能也是非常棒。并且mediawiki本身就为维基百科服务的,于WordPress相比,不需要魔改就能够很好地使用于大型项目。学校有个用WordPress做的展示网站,用户太多编辑太混乱,权限也是非常混乱和危险,现在都有点想安利他们用mediawiki了。

MediaWiki最近的一个更新将脚本全部js脚本都异步了,应该说这也是一个设计的潮流吧。

感谢mediawiki这次的升级为我提供这个月的博客更新素材,终于有点干货了。

 

前言

大约半年多前,就有客户拿着Google Developer PageSpeed Insights要我们一个一个fix网站的上面的问题希望能够帮助SEO。mediawiki这个1.26 的升级,彻彻底底地修复第一项Eliminate render-blocking JavaScript and CSS in above-the-fold content中的Javascript部分。之前在各种工程中,我从未完整地彻底这一项修复,没想到js全部异步后,感官提速效果竟然如此明显。稍后估计我也会在这个Wordpress中实践一下尝试彻底异步javascript 还有css。

 

日文维基百科 mediawiki 1.27 版

QQ截图20151128181401

 

没有升级的网站的数据 mediawiki 1.25.3 版

20151128182017

 

 

 

问题探究

这里出现了一个问题,由于历史原因,异步加载毕竟也算是非常新潮的技术。很多插件还是老一套的设计思路,没有考虑到要针对异步这个特性优化自己的代码。基于Extemsion:Widget的小工具这次不能够使用jQuery等原本都是同步载入的脚本了。

我们有必要研究一下mediawiki这次改进的地方。打开mediawiki第一个加载的js,可以发现主要有3个大段,

var mediaWikiLoadStart = new Date().getTime();

function isCompatible(ua) {
//.........省略
}

var startUp = function() {
    mw.config = new mw.Map(true);
//.........省略
};

 

这里主要研究的应该是第三段,关于脚本的触发方式。可以发现1.26版和1.25.3版的最大区别是

    var script = document.createElement("script");
    script.src = "//bits.moegirl.org/zh/load.php?debug=false&lang=zh&modules=jquery%2Cmediawiki&only=scripts&skin=vector&version=ItzZIeye";
    script.onload = script.onreadystatechange = function() {
        if (!script.readyState || /loaded|complete/.test(script.readyState)) {
            script.onload = script.onreadystatechange = null;
            script = null;
            startUp();
        }
    };
    document.getElementsByTagName("head")[0].appendChild(script);

 

就是这一段简单的代码大幅的提升了mediawiki加载速度,从另外一方面,可以看出mediawiki的程序员还是相当有素质的,所有的函数都用mw这个变量封装起来了。在写更多代码的时候,应该思考是否使用mediawiki提供的函数进行扩展,避免重复造轮,降低长期的维护成本。

相关文档地址:https://doc.wikimedia.org/mediawiki-core/master/js/

 

 

解决问题

做到这个需要widget和远端服务器上面的js进行配合。

在Widget上可以模拟mediawiki的做法,由于这个文本出现得比原本mw的在页首的脚本肯定要晚,因此执行的时候mw这个对象一定被声明了。因此可以在远端放心地使用mw这个变量。

(function() {
    var script = document.createElement("script");
    script.src = "https://masterchan.me/test.js远程js的地址";
    script.onload = script.onreadystatechange = function() {
        if (!script.readyState || /loaded|complete/.test(script.readyState)) {
            script.onload = script.onreadystatechange = null;
            script = null;
        }
    };
    document.getElementsByTagName("head")[0].appendChild(script);
})();

实例http://zh.moegirl.org/Widget:AsyncScriptTest

 

 

值得注意的是,这个时候jQuery 可能还没有被加载,因此在远端的服务器不能够直接使用jQuery。我们可以通过mw这个对象提供的函数对自己写的内容进行封装。通过mediawiki提供的文档可以知道,mw这个对象本身就有相当多的有用的函数

mw.loader.implement("yuruyuri3hai填入名称",function($,jQuery){
	//可以放心地使用jQuery 了
	$("p").hide();
});

 

这里只是举了一个简单的例子

 

 

后续问题

可以选择相同的服务器来放脚本,但是自动部署方面,可能会把环境变得更加复杂。也可以用一个新网址用来托管脚本,但是这样被人污染的概率也增加了。这是一个增加后台复杂性的一个行为。我们可以通过git来帮助我们进行规范管理,当然,需要一个有执行力的CTO。

另外由于ref里面含有关键字,如果需要通过某个防火墙的话,需要部署两台服务器。

 

 

这篇博文发表在 开发运维 | Dev Ops 目录下,标签为 ,
如需引用,请使用链接:https://note.mc256.dev/?p=787

This article published in 开发运维 | Dev Ops with tags , .
Cite this page using this link:https://note.mc256.dev/?p=787

您的邮箱地址不会被公开,评论使用Gravatar头像。
Your email address will not be published. This blog is using Gravatar.

正在提交评论... Submitting ...
正在为您准备评论控件 Loading Comment Plugin
Copyright © 2013-2024 mc256. All Rights Reserved.
Powered by WordPress on top of a dual-stack k3s Cluster using JuiceFS.
Wordpress Theme Designed By mc256.
Encrypted By Let's Encrypt.  Hosted On Linode + OVH + AWS.
DNS Provided By Hostker.
Status Page by CloudFlare Worker.