使用七牛CDN对博客静态资源进行加速

WordPress 博客程序默认静态资源全部存放在 wp-content、wp-includes 目录下,包括主题样式和各种插件样式。

使用七牛CDN对博客静态资源进行加速步骤:

第一步、同步所有静态资源到七牛空间

第二步、替换静态资源域名

if (!is_admin())
{
	function qiniu_ob_start()
	{
		ob_start('qiniu_cdn_replace');
	}

	function qiniu_cdn_replace($html)
	{
		if ($_SERVER['SERVER_PORT'] == '443' || $_SERVER['HTTPS'] == 'on')
		return  str_replace('blog.zhengxianjun.com/wp-content', 'dn-zhengxianjun.qbox.me/wp-content',
				str_replace('blog.zhengxianjun.com/wp-includes', 'dn-zhengxianjun.qbox.me/wp-includes', $html));

		return  str_replace('blog.zhengxianjun.com/wp-content', 'zhengxianjun.qiniudn.com/wp-content',
				str_replace('blog.zhengxianjun.com/wp-includes', 'zhengxianjun.qiniudn.com/wp-includes', $html));
	}

	add_action('wp_loaded', 'qiniu_ob_start');
}

上述代码需要添加到 wp-content/themes/twentyfifteen/functions.php。其中,twentyfifteen 是当前博客使用的主题。

实现效果

访问博客首页

博客首页

查看网络资源

网络资源

可以看到博客已经使用了CDN对静态资源加速。

以后每次更新静态资源时需要同时更新到七牛空间。

为了简化静态资源同步,使用脚本 wp-static-sync.php 同步静态资源到本地七牛空间目录,七牛的 QRSBox 会自动更新目录下的所有文件。

<?php
// 文件 wp-static-sync.php
if (!isset($_SERVER['argv']))
{
	return;
}

function copy_static($static_source, $static_target)
{
	if (!is_dir($static_source))
	{
		echo "static_source : <$static_source> is not a dir\n";
		return false;
	}

	if (!is_dir($static_target))
	{
		if (false === mkdir($static_target))
		{
			echo "mkdir ERROR target <$static_target>\n";
			return false;
		}
		else
		{
			echo "mkdir Ok target <$static_target>\n";
		}
	}

	$handler_source = opendir($static_source);
	$handler_target = opendir($static_target);

	$reg_static = '/\.css$|\.js$|\.gif$|\.jpg$|\.png$/i';

	while ($name = readdir($handler_source))
	{
		if ($name == '.' || $name == '..') continue;

		$file_source = $static_source . '/' . $name;

		if (is_file($file_source))
		{
			if (preg_match($reg_static, $name))
			{
				$file_target = $static_target . '/' . $name;
				if (false === copy($file_source, $file_target))
				{
					echo "copy ERROR <$file_source> to <$file_target>\n";
				}
				else
				{
					echo "copy Ok <$file_source> to <$file_target>\n";
				}
			}
		}
		else if (is_dir($file_source))
		{
			$file_target = $static_target . '/' . $name;
			if (false === copy_static($file_source, $file_target))
			{
				return false;
			}
			// 删除空目录
			if (count(scandir($file_target)) == 2)
			{
				if (false === rmdir($file_target))
				{
					echo "rmdir ERROR empty  <$file_target>\n";
				}
				else
				{
					echo "rmdir Ok empty  <$file_target>\n";
				}
			}
		}
	}
}

$static_source = 'D:\work\blog';
$static_target = 'D:\work\zhengxianjun_cdn\www\static';

copy_static($static_source . '/wp-content', $static_target . '/wp-content');
copy_static($static_source . '/wp-includes', $static_target . '/wp-includes');

至此,虽然流程上略长,但基本实现了想要的功能。

另一种方法,是使用 wpjam-qiniu 这款插件,该插件可以绑定到七牛空间。因为我在使用过程中出现了一些问题,之前发布的文章中图片地址出现了错误,所以使用上面所述的方法实现。

我心匪石,不可转也

《诗经·邶风·柏舟》

天涯海角

泛彼柏舟,亦泛其流。耿耿不寐,如有隐忧。微我无酒,以敖以游。
我心匪鉴,不可以茹。亦有兄弟,不可以据。薄言往愬,逢彼之怒。
我心匪石,不可转也。我心匪席,不可卷也。威仪棣棣,不可选也。
忧心悄悄,愠于群小。觏闵既多,受侮不少。静言思之,寤辟有摽。
日居月诸,胡迭而微?心之忧矣,如匪浣衣。静言思之,不能奋飞。

JavaScript Function bind

JavaScript bind 函数允许返回一个跟源函数一样的绑定函数。绑定函数与源函数区别在与绑定函数的 this 已经被 bind 修改。

函数定义

new Function().bind(this, arg0, arg1…)

代码示例

function sayHello(guest) {
	console.log('Hello ' + guest + ', I am ' + this.age + ' years old');
}
sayHello('Yue');

var me = {
	name: 'Seven',
	age: '24'
};

var sayHi = sayHello.bind(me);
sayHi('Yue');

执行结果

JavaScript bind

尽管没有通过调用成员方法而是直接执行函数 sayHi(‘Yue’),sayHi 内部的 this 仍然指向了对象 me,而不是默认的 window。

从控制台可以看到 sayHi 已经被“编译”为本地方法。

bind 函数的可选参数 arg0、arg1 等是绑定到源函数对应的第0个参数、第一个参数。执行绑定函数时自动传递已绑定的参数。

与 bind 相比,apply 和 call 方法是在函数执行时改变 this,bind 可以理解为在函数定义时改变 this。

apply、bind、call 对比

函数名 参数列表 说明
apply (this_arg, arguments_array) 调用函数,通过 this_arg 替代源函数默认的 this,arguments_array 是传递给函数的参数列表
var A = {
	name: 'A',
	sayHi: function(guest) {
		console.log('Hi ' + guest + ', I am ' + this.name);
	}
}
var me = {name: 'Seven'};
A.sayHi('Yue');
A.sayHi.apply(me, ['Yue']);
bind (this_arg, arg0, arg1…) 创建与源函数函数体一样的绑定函数,并根据 this_arg 和 arg0、arg1 等分别修改绑定函数的 this 和 默认参数
call (this_arg, arg0, arg1…) 调用函数,通过 this_arg 替代源函数默认的 this,arg0、arg1 等是传递给函数的参数列表
var A = {
	name: 'A',
	sayHi: function(guest) {
		console.log('Hi ' + guest + ', I am ' + this.name);
	}
}
var me = {name: 'Seven'};
A.sayHi('Yue');
A.sayHi.call(me, 'Yue');