Normal view

There are new articles available, click to refresh the page.
Before yesterdayMain stream

我如何使用WordPress—记博客成立一周年

12 July 2019 at 14:26

一年前的今天,一位刚刚考完期末考的大一学生,坐在电脑前

他用lamp部署了wordpress——他人生中的第一个博客,并起名为Newlearnerの小站

一段缘分,从这里开始

Newlearnerの小站终于在今天(7.12)走过了它的一周年纪念日,从建站一路走来,有许许多多的事情想要和大家分享。在这里首先要感谢各位读者和tg群的群友对本博客的支持和鼓励。

我将和大家讲述博客一年来走过的路,以及我如何使用Wordpress这个Blog CMS平台探索未知、记录点滴。

《我如何使用Wordpress—记博客成立一周年》

建博客的初衷

18年上半年我感受到了贴吧的没落,自己辛苦整理的内容无人问津,复读机的生活索然无味。

mbp吧里的大佬瑞仙森偶尔有一次和我谈到了当前的现状,并且劝我别当复读机了,不如找一些自己感兴趣的事情做做。

导火索:在mbp吧发了一个答疑帖,并分享了一个自己整理的mbp型号表格。结果遭到隔壁吧mb吧的吧务插手,说我是借鉴了他们的图片样式而没有标注。于是注明,然而还是遭到了不依不饶的举报最后被吧务删帖。

发展:不能自由地发表自己的看法是我无法忍受的,于是离开了贴吧。直到六月底我开始接触VPS,搭建了国际网络之后想要物尽其用。搜索了「VPS用途」之后,发现还可以搭建博客,当时就萌发了这个想法并在18年7月12日付诸了行动,于是就有了大家今天所见的Newlearnerの小站

博客的logo和名称从建站开始就一直沿用了,核心主题叫做「探索未知,记录点滴」,主要分享IT相关文章。作为一个非计算机专业的学生,是兴趣使然让我对IT相关产生了兴趣,深感自己的浅薄,于是想要有一个记录自己学习&感悟的地方。

博客是自己的自留地,在这里可以畅所欲言,而无需担心会被删帖。也可以即时修改与更新博客的内容,使其与时俱进。

写出来的文章不算是教程,而是自己在摸索过程中的记录与分享。若干年之后回头看看,也算是成长的历程了。

时间轴

  • 2018.7.12 中午:通过LAMP+Wordpress搭建了这个博客,主题用的是Ribbon Lite。按捺不住内心的喜悦,将自己的几篇贴吧文章搬运了过来。后来百度贴吧也没有让我失望,原文在贴吧几乎悉数尽失
  • 2018.7.14:给网站手动添加了SSL证书,从此小站用上了绿标
  • 2018.7.20:网站开始采用Google Analytics作为博客访问量统计
  • 2018.9.16:增加「给我留言」页面
  • 2018.11.12:博客从Vultr迁移到搬瓦工主机,升级了机器配置
  • 2018.12:博客采用新主题Kratos
  • 2018.12.29:增加「FriendsのLinks」页面,正式开始征集友链
  • 2019.2.19:增加「博文归档」页面
  • 2019.6:优化了博客CSS加载和首页图片大小

梦开始的样子

《我如何使用Wordpress—记博客成立一周年》

现在

《我如何使用Wordpress—记博客成立一周年》

博客统计

2018.7.122019.7.12Newlearnerの小站一岁了。在这一年里,博客文章共有60篇,码了117,044

共有73,000位用户来访了小站,网站用访问量(PV)为145,000,目前日均PU在650左右

其中访问量最多的文章为Telegram群组/频道/机器人推荐,贡献了50,100次访问量

小站在Alexa的世界排名约为240,000名,国内排名约为50,000-100,000

博主平均更博速度为4篇每月,目前友链数量为8个,评论数目为104

网站风雨无阻地运行了363天,其中2天因为不可抗力关站维护

《我如何使用Wordpress—记博客成立一周年》

从上图可见网站在进入9102之后访问量大增,在6月初曾经关站两天,目前访问量依然在小幅增长中。小站的流量来源大多为谷歌搜索引擎,本人不喜欢硬广,有缘的人自然会相遇。相比1月初的2019,新的开始这篇博文的数据,小站的各项指标得到了长足的进步和增长。

今后也会认真更新博客,和各位大佬互相交换友链,即使个人博客不比昔日。希望等博客两周年时,又会看到不一样的Newlearnerの小站

对主题的修改

之前的Ribbon Lite一度被朋友吐槽很复古,后来更换了Kratos之后我对主题做了部分修改。

  • 统计网站运行时间

建站不久想给博客做一个运行时间统计,于是谷歌了相关办法,并决定把这个模块放到博客的侧栏。美中不足的是手机端不可以看到。

在侧栏中选择「自定义html」模块并添加,代码为:

<script>
    function secondToDate(second) {
        if (!second) {
            return 0;
        }
        var time = new Array(0, 0, 0, 0, 0);
        if (second >= 365 * 24 * 3600) {
            time[0] = parseInt(second / (365 * 24 * 3600));
            second %= 365 * 24 * 3600;
        }
        if (second >= 24 * 3600) {
            time[1] = parseInt(second / (24 * 3600));
            second %= 24 * 3600;
        }
        if (second >= 3600) {
            time[2] = parseInt(second / 3600);
            second %= 3600;
        }
        if (second >= 60) {
            time[3] = parseInt(second / 60);
            second %= 60;
        }
        if (second > 0) {
            time[4] = second;
        }
        return time;
    }
</script>
<script type="text/javascript" language="javascript">
    function setTime() {
        // 博客创建时间秒数,时间格式中,月比较特殊,是从0开始的,所以想要显示5月,得写4才行,如下
        var create_time = Math.round(new Date(Date.UTC(2018, 6, 12, 0, 0, 0))
                .getTime() / 1000);
        // 当前时间秒数,增加时区的差异
        var timestamp = Math.round((new Date().getTime() + 8 * 60 * 60 * 1000) / 1000);
        currentTime = secondToDate((timestamp - create_time));
        currentTimeHtml = currentTime[0] + '年' + currentTime[1] + '天'
                + currentTime[2] + '时' + currentTime[3] + '分' + currentTime[4]
                + '秒';
        document.getElementById("htmer_time").innerHTML = currentTimeHtml;
    }
    setInterval(setTime, 1000);
</script>

<strong>网站运行:<span id="htmer_time" style="color:grey;font-size: 12pt;"></span></strong>

  • 统计博客访问量

博客的统计可以在Google Analytics后台看到详细的数据,但是我想在博客页面也显示出来。最后采用的方案适合大多人一样的,采用不蒜子统计。

官网不蒜子-极简网页计数器

根据官网的方法,只需要在footer.php里面增加两行代码就可以了。但是我的情况比较特殊,因为在我试用不蒜子统计的时候,网站已经有了一些流量,我想要做增量统计。所以最后在页脚的php页增加了如下代码:

<script src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
<span id="busuanzi_container_site_pv" style='display:none'>本站总访问量<span id="busuanzi_value_site_pv"></span>次</span> 

<script>
        $(document).ready(function() {
            var int = setInterval(fixCount, 50);  // 50ms周期检测函数
            var countOffset = 46081;  // 46081为截止2019.3.14日访问本站的总page views数
			function fixCount() {            
       if (document.getElementById("busuanzi_container_site_pv").style.display != "none")
        {
            $("#busuanzi_value_site_pv").html(parseInt($("#busuanzi_value_site_pv").html()) + countOffset); 
            clearInterval(int);
        }                  
        if ($("#busuanzi_container_site_pv").css("display") != "none")
        {
            $("#busuanzi_value_site_uv").html(parseInt($("#busuanzi_value_site_uv").html()) + countOffset); // 加上初始数据 
            clearInterval(int); // 停止检测
        }  
    }
       	
});
</script>

  • 增加文章阅读时间和字数统计

Kratos默认在文章开头只显示日期、点赞、阅读数等,不符合我的需求。

效果图

《我如何使用Wordpress—记博客成立一周年》

function.php中加入如下代码:

function count_words_read_time () {
global $post;
   $text_num = mb_strlen(preg_replace('/\s/','',html_entity_decode(strip_tags($post->post_content))),'UTF-8');
   $read_time = ceil($text_num/400);
   $output .= '本文共' . $text_num . '个字,预计阅读时间' . $read_time  . '分钟。';
   return $output;
}

function count_words () {
global $post;
   $text_num = mb_strlen(preg_replace('/\s/','',html_entity_decode(strip_tags($post->post_content))),'UTF-8');
   $output .= '本文共' . $text_num . '个字';
   return $output;
}

然后在文章首页single.php合适位置添加如下代码:

<i class="fa fa-book"></i><?php echo count_words_read_time(); ?><br>

content.php加入如下代码,使其在首页也生效:

<a href="<?php the_permalink() ?>"><i class="fa fa-book"></i> <?php echo count_words(); ?></a>

  • 增加文章最后修改时间

效果图

《我如何使用Wordpress—记博客成立一周年》

这个主题依然没有提供文章最后修改时间,这可能会让几年后看到文章的人无法判断该文章的时效性,于是我经过谷歌,在single.php加入如下代码:

<?php if ((get_the_modified_time('Y')*365+get_the_modified_time('z')) > (get_the_time('Y')*365+get_the_time('z'))) : ?> 最后修改:<?php the_modified_time('Y-m-j h:s'); ?><?php else : ?><?php endif; ?>

  • 优化meta

原主题自带的meta头很糟糕,在tg中放出链接甚至不能显示文章简介,在这里要特别感谢青鸟大佬为我指出这个问题。后来我在header.php中加入如下代码:

<?php // add meta keywords and description by conditionary
//以下内容针对网站首页
if ( is_home() || is_front_page() ) { //判断是否为首页
    $description = "Newlearner365的自留地,不定期更新一些关于IT的文章。探索未知,记录点滴!";//将双引号中的内容修改为你自己的
    $keywords = "博客,Mac,iOS,VPS,IT,技术分享";//将双引号中的内容修改为你自己的
}

elseif ( is_singular() && !is_attachment() ) {

	$exerpt = $post->post_excerpt; //2012.11.01 因 get_the_excerpt() 会在没有设定 excerpt 时自动生成一个 excerpt 而导致某些情况下出错。
	if ( $exerpt != '') { //是否存在摘要
		$description = $exerpt; //使用文章摘要作为描述
	}
	else {
		$description = $post->post_content; //使用文章内容的前 200 个字符(后面会进行截短)作为描述
    }

	$keywords ="";
	$tags = wp_get_post_tags( $post->ID, array( 'fields' => 'names' ) );
	$keywords = implode(",", $tags);
}

elseif(is_category()) {
    $description = category_description();
// $keywords = "";
}
elseif(is_tag()) {
    $description = tag_description();
// $keywords = "";
}


if ( $description != '' ) {
    $description = preg_replace('#\[[^\]]+\]#', '', $description);
    // 清理 description 中的 HTML 代码,并截短为 200 个字符
    $description = wp_html_excerpt( wp_strip_all_tags( $description, true ), 200 );
?>
    	<meta name="description" content="<?php echo $description; ?>" />
<?php }

//类似 description 来处理 keywords
if ( $keywords !='' ): ?>
    	<meta name="keywords" content="<?php echo $keywords; ?>" />
<?php endif; ?>

  • 彩蛋/Something else

1、给调试中的控制台(console)加入:“居然被你发现啦,既然这样来telegram一起吹水:https://t.me/NewlearnerGroup”文字

通过控制台在主题中找到相关文件并加入:

var copyright = function() {
		console.log("居然被你发现啦,既然这样来telegram一起吹水:https://t.me/NewlearnerGroup");
	}

2、给网站源代码页加入了字符画

<!--
     __              _                                 
  /\ \ \_____      _| | ___  __ _ _ __ _ __   ___ _ __ 
 /  \/ / _ \ \ /\ / / |/ _ \/ _` | '__| '_ \ / _ \ '__|
/ /\  /  __/\ V  V /| |  __/ (_| | |  | | | |  __/ |   
\_\ \/ \___| \_/\_/ |_|\___|\__,_|_|  |_| |_|\___|_|   
-->

3、加入了复制提醒

header.php加入如下代码:

<script type="text/javascript">
    document.body.oncopy=function(){alert("复制成功!转载请注明出处");}
</script>

  • 一点遗憾

主题并不支持移动端搜索以及侧边栏显示,这令人很头疼

顶部的菜单导航栏排布太多在低分屏下会出现重叠情况,我只好加了一个「更多」菜单,并将多余的项目收入其中

插件

简单和大家分享下我正在用的插件,wp的一大好处就是主题和插件的支持很到位。

1、Autoptimize

可以优化图片、js、css的加载速度

2、Captcha by BestWebSoft

数字评论验证码插件,有效防范垃圾评论

3、Crayon Syntax Highlighter

代码高亮插件,不过早就对它不满意了。什么时候不咕了打算用prism.js替换之

4、Cresta Posts Box

免费版会在读者翻到文章结尾处时自动弹出上一篇的简介,实用的小插件

5、Google Analytics Dashboard for WP

谷歌分析插件,免去直接修改themes文件的麻烦,还可以直接在admin后台显示统计情况

6、Google XML Sitemaps

网站地图插件,会生成方便谷歌收录的网站地图

7、Permalink Manager Lite

自定义每篇文章的link

8、Sassy Social Share

博文分享栏,对国内社交软件支持有限

9、TablePress

表格插件,可以拿来制作友链等

10、Unique Cursor

更改网站鼠标样式

11、UpdraftPlus

网站备份及恢复

12、WP FancyZoom

支持博文图片以大图显示

13、WP Super Cache

动态页面缓存,有助于加快网页打开速度,支持cdn嵌套

14、先荐

在每篇博文底部以及侧边栏推荐相关类型博文

15、年度归档

归档页面所用插件,按年份月份归档

16、WP Word Count

统计博客字数

以后的发展

只要咱有钱续费服务器,Newlearnerの小站就会一直陪伴大家。第二年将会考虑增加一些硬件、Mac相关的话题和文章。

囿于年龄和学生身份等限制,有些领域我还无法去涉足。博客作为一个小型的自媒体,发表的观点也是很个人的,如有幼稚和片面的地方希望大家多多宽容!

虽然没有加入博客十年之约,但是还是希望能认真写好每一篇文章,探索未知,记录点滴。

特别感谢

1、我的读者们

很多人其实是在谷歌认识这个网站的,在网站建立前期我还去过贴吧和威锋做过硬广。谢谢你们的关注和留言。

2、舍友ss大佬

在网站建立前期给了我很多有用的指导,并帮助我迁移网站到搬瓦工。

3、不愿透露姓名的J大和朋友们

一年内给了我很多鼓励和支持,也帮我纠正了一些错误的地方。写博客始于热爱,贵于坚持。


最后给大家带来一个小抽奖,评论本篇博文即可参与,留下你的真实邮箱。在7.13日晚九点半会准时开奖。

奖品:2个奈飞4k独享账号1个月+2个spotify美区会员2个月

WordPress 5.0 更新现已发布,全新编辑器,全新主题

By: James Guo
7 December 2018 at 07:14

WordPress 5.0 正式版已于 2018-12-07 发布,自建 WordPress 用户可以在 WordPress 后台的 Web 管理页面中进行升级。本次更新的最明显的两个特点就是:1. 后台管理使用了全新的编辑器,2. 新增了 2019 年的主题,该主题适配这个全新的编辑器。

这次的 5.0 是一个大版本更新,而不像之前的 4.9、4.8 更新那样,这从版本号就可以看出。

编辑器

这个新的块编辑器(Gutenberg Editor)给人的第一感受就是更加简洁了,这个新的编辑器有着更大的留白。初次使用编辑器的时候会感觉有些不适应,这是因为新的编辑器中没有我们熟悉的工具条了。取而代之的是一个简单的添加块(Add Block)按钮和其他的一些基本操作。

在新版的编辑器中,每一个自然段、图片、副标题、引用等都是一个 “块”。你可以为每个块进行自定义操作,如为每个自然段设置不同的字体大小、字体颜色,甚至是背景色和自定义 CSS。而这一切都是通过右侧的 “组件” 工具可视化的实现的。

你可以直接拖移块,以实现拖移自然段等效果。

经典块(Classic Block)

新版编辑器兼容老板编辑器。要想使用老款的编辑模式,可以通过插入一个或多个经典块(Classic Block)来实现。这个经典块与新编辑器中的其他块(如自然段块、副标题块等)同等级别。经典块中能包含一个或多个自然段、副标题,对于简单的排版,它可以代替最新的块编辑器。在使用经典块时,你依然能够看到你所熟悉的工具条。

经典块

经典块截图

在编辑以前发布的文章与页面时,默认依然使用原有的编辑模式,即在新的编辑器中包含一个经典块。

支持的原有的块

原有的块都是与 HTML 标签对应的,功能相对少一些。经典块用于兼容上一代编辑器。要想使用新特性,你需要学习使用这些新的块。

  • 自然段块(Paragraph):对应原先的 <p>
  • 标题块(Heading):对应原先的 <h1> ~ <h6> 标题。
  • 列表块(List):对应原先的 <ul> 或 <ol> 列表。
  • 更多(More):用于在首页显示 “阅读更多”(Read more),对应原先的 <!--more-->
  • 图像块(Image):对应原先的 <img>
  • Shortcode:新版本中可以使用用 Shortcode 块来插入 Shortcode,这样可以使编辑界面更加简洁。
  • 引用块(Quote):对应原先的 <blockquote>。新版的应用块支持了引文(Citation)。
  • 视频块(Video):对应上一版的 WordPress 编辑器中的 video Shortcode。
  • 分割线(Separator):对应原先的 <hr>
  • 多行代码块(Preformatted):对应原先的 <pre>
  • 代码块(Code):也支持多行,对应原先的 <pre><code> 组合。

新增的一些块

新版本中新增了很多块,通过使用这些块,你可以直接可视化地插入一些你想要的内容,而不用编辑源代码或者是使用插件。

  • 自定义 HTML 块(Custom HTML):尽管你可以在许多块中使用编辑源代码(Edit as HTML),但如果真的需要插入自定义 HTML,建议使用这个块。
  • 空白块(Spacer):在文章中插入一定高度的空白。
  • 画廊(Gallery):插入多张照片组成的画廊。
  • 音频(Audio)
  • 文件(File)
  • 背景图(Cover):使用此块可以在插入的图片上方添加文字。
  • 表格(Table):你终于可以在 WordPress 中可视化的插入表格了。
  • 重要引述(Pull Quote):与引用块的样式有所不同,也是引用。
  • 韵文(Verse):类似多行代码块,也是使用 <pre> 实现的。可以实现英文字符的等宽显示。
  • 按钮(Button):可以添加按钮样式的超链接了。
  • 分栏(Columns)
  • 分页(Page Break)
  • 媒体和文字(Media & Text):用于左右显示媒体和文字。

以下内容原本可以作为 Widgets 在网页菜单中添加。现在还可以作为块在文章中直接添加。

  • 归档
  • 分类
  • 最新文章
  • 最新评论

除此之外,现在还有了嵌入(Embed)功能,可以直接嵌入第三方内容了,如 Twitter、YouTube、SoundCloud 等。

2019 主题

为了更好的配合新的编辑器的所有排版功能,WordPress 同时推出了全新的 2019 默认主题。详情

文章界面截图

正如以往的默认主题一样,新的 WordPress 主题也是十分通用的。然而我感觉新的 2019 主题不如上一个 2017 主题(即本 Blog 正在使用的主题)简洁。

文章界面截图

是否应该升级?该如何升级?

WordPress 不保证老版本继续提供安全性更新,所以你应该升级到最新的 5.0 版本。然而实际上,从 WordPress 的版本历史可以看出,目前 WordPress 仍在维护 3.7(发布于 2013-10-24)及之后的所有版本。所以即使你不更新 5.0 版本,你也可能继续收到安全性更新。

需要注意的是,每次更新 WordPress 版本,尤其是大版本更新,其源代码中的一些函数功能会有所改变,这意味着并不保证你的插件能够在新的 WordPress 中正确运行。你应当检查一下你所启用的插件是否能够在最新版本上正确运行,或者已经发布了适配新版本的更新。如果你是插件开发者,你应该有安装测试版 WordPress 的站点,并早该让你的插件适配最新的版本。

在升级前,请务必备份你的站点。对于 WordPress 而言,你需要备份 WordPress 的代码目录以及数据库内容。

国内外几家全站 CDN 对比

By: James Guo
30 January 2017 at 08:00

配置全站 CDN 可以缓存 HTML 页面和加快页面首次加载所耗时间。本文重点讲述 WordPress 的全站缓存,国内外 CDN 混用的解决方案,以及让页面也在 CDN 上缓存的正确做法。本文主要介绍 CloudFront,同时也对 Cloudflare、又拍云、百度云加速、KeyCDN、Google Cloud CDN 这几家 CDN 进行对比。

全站 CDN 能在哪些地方加速?

我已经像你之前一样只缓存了图片、视频、CSS 和 JS 之类的静态资源,全站 CDN 有什么优点?

就算不缓存任何内容,全站 CDN 也是有他的优点的:

  1. SSL 卸载:源站到 CDN 之前走 HTTP 传输,CDN 到用户走 HTTPS 传输。这样,能减轻源站原本因为 SSL 所造成的硬件负担。然而,由于源站到 CDN 的传输是明文的,仅建议全程内网的情况,或线路可控的情况下使用,否则有很大的安全隐患。然而几乎所有的 CDN 也可以配置源站到 CDN 之间走 HTTPS 加密传输。
  2. 安全防护:所有的 CDN 都自带基于第一、二、三层网络的防护(防止 SYN 攻击),大多数还带了第七层的防护(防止 CC 攻击)。
  3. 减少延迟:建立 HTTP 连接之前需要先进行 TCP 和 HTTP 的 SSL 握手,这样会增加首次加载所需时间。而很多 CDN 都会与服务器进行预连接,而且 CDN 的服务器离用户较近,所以能减少首次加载所需时间,即使没有缓存页面。
  4. 缓存动态页面:所谓动态页面,其实大多数对于没有登录的用户来说内容其实是固定的(如 WordPress 的文章页),所以可以针对未登录的用户缓存。这需要 CDN 能自动根据 Cookie 判断用户有没有登录,这下就只剩 Cloudflare 企业版和 CloudFront 可以做到了。

使用 CloudFront 作为全站 CDN

CloudFront 有 Amazon 自建的网络,单价较高但是 0 元起步,适合中小客户。本文将重点介绍 CloudFront 和 WordPress 配合实现动静分离,缓存 HTML 页面。之后将对比其他的一些 CDN。

  • 国外速度:★★★★☆,节点数量众多,但相比 Cloudflare 要差一些,并且不支持 Anycast。
  • 国内速度:★★★☆☆,国内开始走亚洲节点,速度要比 Cloudflare 快
  • 可定制性:★★★★★,可以根据不同的路径回源使用不同的服务器,甚至回源到不同的服务器,且没有规则数量上限。此外,配合 Lambda@Edge 甚至可以将原本需要源站响应的动态内容交给缓存服务器做,只需使用 Node.js。
  • 廉价指数:★★★☆☆,从免费起,Pay-as-you-go,单价确实高,但是可以通过价格级别牺牲速度来换取更低廉的价格
  • 方便接入:★★☆☆☆,需要配置各种缓存参数才能使用,NS 接入并不直接,CNAME 接入相比 NS 更有难度。SSL 证书首次也需要手动申请,但自动续签。
  • 缓存命中:★★★★☆,支持 _Regional Edge Caches_,先缓存到全球的 9 个节点,再向下分发,大大提升缓存命中率
  • 动静分离:★★★★★,自动分离,一个服务下可以根据不同目录设置不同 Behaviors,甚至配置多个源站服务器,支持匹配 Cookie、GET、Header 规则缓存,支持禁用 POST 等提交方式
  • 缓存刷新:★★★★☆,支持单个 URL 刷新以及规则匹配刷新
  • 接入方式:NS/CNAME
  • 证书兼容性:默认仅限支持 SNI 的浏览器,可额外购买服务($600/月)以兼容所有浏览器。

CloudFront 作为全站 CDN 的特性:

  • 支持根域名
  • 缓存静态文件
  • 缓存页面
  • 页面更新自动清理缓存
  • 免费 SSL 证书
  • 可配置国内外 CDN 混用

使用方法

先去 CloudFront 控制面板,点击 “Create Distribution”,选择 “Web”,然后进行类似如下的配置。源站配置注意 Origin Domain Name 必须是完整域名,而且如果用了 HTTPS,那么那个域名下必须有配置有效证书。

CloudFront 基础配置截图

缓存配置,我把 Host 加入了 Header 白名单,Cookie 要添加 wordpress*wp* 到白名单。

CloudFront 详细配置截图

然后前端配置,证书点 “Request or Import a Certificate with ACM” 就能申请 Amazon 颁发的证书了。CNAMEs 下填写你的网站的域名。

CloudFront 前端配置截图

注意,创建后可能要等不到一小时才能被访问到。 为了根域名和 CloudFront 配合使用,我还得换 Route 53 这个 DNS 解析。由于这是精度非常高的 GeoDNS,是需要将解析服务器向各大 DNS 缓存服务器去提交,让这些缓存服务器去针对你的 DNS 缓存服务器加入到启用 EDNS Client Subnet 的白名单中。还好 Route 53 是最流行的 GeoDNS 之一,所以如果你用它给的 NS 记录,而不去自定义,就不用操心这个了。在配置根域名时,直接选择 A 记录,然后开启 Alias,填写 CloudFront 域名就行。如果想要支持 IPv6,那就再建一个 AAAA 记录即可。这样的话如果你从外部解析,你会直接解析到 A 记录和 AAAA 记录,而不是 CNAME 了!

CloudFront 配合 Route 53 使用截图

此时,CloudFront 就配置完了。现在 CloudFront 会自动缓存页面约一周的时间,所以需要配置文章更新时清理缓存。我写了一个插件,可以在有文章更新/主题修改/内核更新时清理所有缓存,新评论时清理文章页面,控制刷新频率为 10 分钟(这是由于 CloudFront 刷新缓存的速度是出奇的慢,而且刷新缓存只有前一千次免费)。欢迎使用我制作的插件。 不过,CloudFront 在国内的访问速度还不如我之前用的 GCE,这可怎么办?没关系,Route 53 可以 GeoDNS,我把中国和台湾还是解析到了原本的 GCE 上,这样速度其实只提不减。注意,若要这样做,原本的服务器也要有有效证书(同理,你要是域名已经备案,则可以设置为国内的 CDN 的 IP,达到国内外 CDN 混用的效果)。CloudFront 会影响 Let’s Encrypt 的签发,所以需要通过设置 Behaviors 和多个源站服务器,来继续实现 80 端口的文件认证。实际测试 Route 53 为中国解析的 IPv4 识别率为 100%,IPv6 的识别率欠佳。

CloudFront 配合 Route 53 使用截图 2

实际使用情况

GeoDNS 效果测试

国内解析情况:

$ dig @8.8.8.8 +short guozeyu.com a104.199.138.99$ dig @8.8.8.8 +short guozeyu.com aaaa2600:9000:2029:3c00:9:c41:b0c0:93a12600:9000:2029:9600:9:c41:b0c0:93a12600:9000:2029:2a00:9:c41:b0c0:93a12600:9000:2029:1600:9:c41:b0c0:93a12600:9000:2029:c00:9:c41:b0c0:93a12600:9000:2029:ce00:9:c41:b0c0:93a12600:9000:2029:6400:9:c41:b0c0:93a12600:9000:2029:ac00:9:c41:b0c0:93a1

国外解析情况:

$ dig @8.8.8.8 +short guozeyu.com a52.222.238.23652.222.238.22752.222.238.20752.222.238.10752.222.238.20852.222.238.7152.222.238.6852.222.238.67$ dig @8.8.8.8 +short guozeyu.com aaaa2600:9000:202d:5c00:9:c41:b0c0:93a12600:9000:202d:ec00:9:c41:b0c0:93a12600:9000:202d:7c00:9:c41:b0c0:93a12600:9000:202d:2a00:9:c41:b0c0:93a12600:9000:202d:9400:9:c41:b0c0:93a12600:9000:202d:c600:9:c41:b0c0:93a12600:9000:202d:f600:9:c41:b0c0:93a12600:9000:202d:6200:9:c41:b0c0:93a1

没错,CloudFront 分配给的 IP 数量就是多,让别人看了会感觉很厉害。

Ping 启动前后对比

这里只对比国外的速度

源站速度CDN 速度

HTTPs Get 启动前后对比

这里也是只对比国外的速度

源站速度CDN 速度

启动 CDN 后的 TTFB 几乎全面绿色,建立 TCP 和 TLS 的时间显著降低。

Amazon 的 SSL 证书

CloudFront 免费签发的 SSL 证书是多域名通配符证书(Wildcard SAN),并且主要名称是自定的,要比 Cloudflare 的共享证书高级。此类证书在 Cloudflare 上需要花费每月 10 美元。此类证书在市面上很难买到,而且价格取决于域名数量,在一年几千到几万不等。 然而,这个证书只能在 AWS 的 CloudFront 和负载均衡器上使用。

Amazon 证书

CloudFront 的证书链较长,会影响 TLS 时间,不过由于它同时也是 CDN,这样 TLS 时间几乎减少到了可以忽略不计的程度。主要还是因为 macOS 上还没有直接信任 Amazon Root CA,如果直接信任了,就用不着这样了。

其他 CDN 厂商对比

以下列出的所有提供商(或某一提供商的某些版本),均符合以下条件,如果不符合则单独列出:

  1. 是个 CDN 厂家
  2. 支持 HTTPS、HTTP/2
  3. 免费签发 SSL 证书,且自动续费
  4. 我现在正在使用,或曾经长期使用过,或深入了解过
  5. 可以给 WordPress 全站 CDN 加速

Cloudflare 免费版/专业版

有自建的网络,最快的速度、最低廉的价格,主要提供网站安全防护,当然还附带了 CDN。其提供的 NS 服务也是(国外)业界第一的速度。本站国外使用了 Cloudflare,欢迎直接测试本站国外的速度。

  • 国外速度:★★★★★,由于拥有众多的海外节点并支持 Anycast,给满分。速度指标指全球各地的 Ping 值,下同
  • 国内速度:★★☆☆☆,国内走美国西岸的节点,速度欠佳
  • 可定制性:★★★★★,需要使用 Page Rules 进行基础定制,还可以使用 Worker 进行编程定制。
  • 廉价指数:★★★★★,从免费起步,给满分
  • 方便接入:★★★★★,改完 NS 直接接入,自动签发 SSL 证书,无需服务器配置,还有比这更简单的吗?
  • 缓存命中:★★★★★,由于节点数量实在众多,于是在每一个地方都需要单独缓存,所以缓存命中率很低;但是如果开启了 Argo,那么就能够实现更高的缓存命中率,此外还能自动调配最优线路。Argo 需要每月额外的消费($5/mo + $0.10/GB)。
  • 动静分离:★★★☆☆,自动分离,它遵守 Cache-Control 规则,也可以设置 Page Rules 修改默认缓存规则。但是,默认不缓存 HTML 页面、Page Rules 只有 3 个的限制、以及没有开放匹配 Cookie 规则的缓存。
  • 缓存刷新:★★☆☆☆,仅支持刷新某个页面的 URL 和刷新全部内容,不支持规则刷新
  • 接入方式:NS(如果是 Partner 则可以有免费的 CNAME 接入)
  • 证书兼容性:仅限支持 SNI 的浏览器

Cloudflare 作为全站 CDN 的特性:

  • 支持根域名
  • 缓存静态文件
  • 不支持缓存页面
  • 免费 SSL 证书

有一点不同的是,Cloudflare 签发的是共享证书,证书样式如下:

Cloudflare 共享证书

我觉得 Cloudflare 签发共享证书有两个原因,一是历史遗留问题:Cloudflare 专业版的 SSL 证书服务是支持无 SNI 的客户端的,而为了支持无 SNI 的客户端,一个 IP 就只能配置一个证书,所以就使用了共享证书节约 IP 资源。而现在免费版也有了 SSL,虽然免费版使用了 SNI 技术,但是证书总不能比付费版本还要高级吧,于是还是使用了共享 SSL 证书;二是为了增加更多的增值服务,现在 Cloudflare 上可以购买 Dedicated SSL Certificates,实现独立的证书(如果是付费版本启用,不支持 SNI 的客户端仍然 Fall back 到共享证书,所以仍然兼容不支持 SNI 的设备)。

Cloudflare 企业版

简介同上,此版本适合大客户,流量越大越适合用。百度云加速是和 Cloudflare 深度整合的,其实基础设施完全一样,但百度云加速没有提供 API 接口。

  • 国外速度:★★★★★,同上
  • 国内速度:★★★★★,有众多的国内节点
  • 可定制性:★★★★★,同上,Page Rules 数量有所提升
  • 廉价指数:★★☆☆☆,每月固定的花销,不是按需付费,量越大越实惠
  • 方便接入:★★★★★,同上
  • 缓存命中:★★★★★,同上
  • 动静分离:★★★★☆,对于 WordPress 来说安装了官方插件就可以自动分离,相比免费版,他有更多的 _Page Rules_、支持匹配 Cookie 规则缓存,相比 CloudFront 差一些
  • 缓存刷新:★★★★☆,相比免费版,支持了 Cache-Tag 刷新规则,然而需要服务端的配置
  • 接入方式:NS/CNAME
  • 证书兼容性:所有浏览器

Cloudflare 企业版作为全站 CDN 的特性:

  • 支持根域名
  • 缓存静态文件
  • 支持缓存页面
  • 页面更新自动清理缓存(完美清理缓存)(由于百度云加速没有提供 API,所以云加速没有这个功能)
  • 强大的 DDOS 防御以及 WAF 功能
  • 免费 SSL 证书

UPYUN

使用自己管理的机房,网络有些受限于中国的环境,单价业界最低。

  • 国外速度:★★☆☆☆,北美洲、欧洲、亚洲都有一定数量的节点,但速度欠佳。且 CNAME 接入所用的 NS 在国外没有节点,在解析速度上就牺牲很多。
  • 国内速度:★★★★★,国内节点很多,但是由于只能 CNAME 接入,需要多一次解析请求,花费时间
  • 可定制性:★★★★☆,可以设置很多个缓存规则,并且有自定义 Rewrite,可以实现比 Rewrite 更丰富的功能,但是函数功能受限。
  • 廉价指数:★★★★½,从免费起,Pay-as-you-go,价格也是一降再降,业界较低的标准
  • 方便接入:★★★☆☆,不需要配置多少参数,CNAME 接入相比 NS 更有难度。SSL 证书首次需要手动添加,自动续签。
  • 缓存命中:★★★★½,有源站资源迁移功能,首次访问后直接永久缓存。但是如果要删除文件,还需要用 API 手动删除,扣半分
  • 动静分离:★★★★☆,自动分离,可以配置不同目录的缓存规则,但是不支持Cookie 规则缓存
  • 缓存刷新:★★★★☆,支持单个 URL 刷新以及规则匹配刷新
  • 接入方式:CNAME,所以不能根域名使用
  • 证书兼容性:仅限支持 SNI 的浏览器

UPYUN 作为全站 CDN 的特性:

  • 不支持根域名
  • 缓存静态文件
  • 不支持缓存页面
  • 有 WAF 功能
  • 免费 SSL 证书
  • 可配置国内外 CDN 混用

UPYUN 和下面的 KeyCDN 签发的都是 Let’s Encrypt 的独立证书,但都是单域名证书,甚至有 www 和无 www 的都要单独申请。

Google Cloud CDN

有全球最密集的网络集群,最快的速度、较低的单价,主要提供负载均衡,SSL 卸载,当然还附带了 CDN。由于缓存命中率低,需要超大型访问量的网站才有效。正是因为这一点,Google 自己只是将用户量极大的搜索服务用上了这个 CDN 系统,其余的很多 CDN 用的是 Cloudflare 和 Fastly 的。Google 的网络和 Cloudflare 和 Fastly 的网络有内网链接。详细介绍看本站的这篇文章

  • 国外速度:★★★★★,由于拥有众多的海外节点并支持 Anycast,给满分。
  • 国内速度:★★★☆☆,国内直连香港节点,几乎是速度最快的香港网络的,与国内几大运营商都有接入,但毕竟没有国内节点,比不过一些国内的速度。(但是目前所分配到的一些 IP,联通会绕道至美西了)
  • 可定制性:★★☆☆☆,可以根据不同路径配置不同的服务器,然后,好想也没什么别的可定制的了。
  • 廉价指数:★★☆☆☆,由于占用了 IP 资源,每月需要花费 18 美元的固定价格,并还需要再为流量付费。流量的单价较低。
  • 方便接入:★☆☆☆☆,需要各种复杂的配置,但是一旦完成了配置,就同时有了负载均衡,弹性伸缩等等特性。
  • 缓存命中:★½☆☆☆,节点太多,小流量网站都很难遇到命中的情况。但可以利用跨区域负载均衡提高缓存命中率。
  • 动静分离:★★☆☆☆,自动分离,但不能配置任何规则。
  • 缓存刷新:★★★★☆,支持单个 URL 刷新以及规则匹配刷新
  • 接入方式:IP 绑定,它直接给你分配一个独立的 Anycast IP,只需要 A 记录解析即可。
  • 证书兼容性:所有浏览器
  • 不包含免费 SSL,需要自己购买

Google Cloud CDN 作为全站 CDN 的特性:

  • 支持根域名
  • 缓存静态文件
  • 不支持缓存页面
  • 免费 SSL 证书
  • 可配置国内外 CDN 混用

KeyCDN

他们是租用别人的独立服务器,提供一体化 CDN 服务,单价业界最低。

  • 国外速度:★★★★☆,和 CloudFront 有一拼,但是由于只能 CNAME 接入,需要多一次解析请求,花费时间
  • 国内速度:★☆☆☆☆,国内的话香港节点,但是狂绕道,反而比美国还慢
  • 廉价指数:★★★☆☆,有最低年费(相当于起步价)
  • 方便接入:★★★½☆,不需要配置多少参数,CNAME 接入相比 NS 更有难度。SSL 可以一键添加。
  • 缓存命中:★★★★☆,有类似 CloudFront Regional Edge Caches 的功能
  • 动静分离:★★☆☆☆,自动分离,但不能配置规则。支持针对 Cookie 的缓存配置,但不能匹配 Cookie 内容
  • 缓存刷新:★★★★☆,支持单个 URL 刷新、全部刷新、Cache-Tag 刷新
  • 接入方式:CNAME,所以不能根域名使用
  • 证书兼容性:仅限支持 SNI 的浏览器

KeyCDN 作为全站 CDN 的特性:

  • 不支持根域名
  • 缓存静态文件
  • 缓存页面
  • 页面更新自动清理缓存(完美清理缓存)
  • 免费 SSL 证书
  • 可配置国内外 CDN 混用

我为他写了一个插件可以实现完美清理缓存,详情见此

关于 WordPress 动静分离的新方法

WordPress 可以分别设置 Site URL 和 Home URL,对于 https://example.com 这个网站,这两栏就可以这样设置:

然后,直接给 Home URL 上 CDN,在 CDN 或者源站上配置忽略 Cookie 信息。Site URL 回源,用作 WordPress 后台管理即可。

修复 WordPress 2017 主题中奇怪字形的 Bug

By: James Guo
17 December 2016 at 17:18

最近国外掀起了一股用 system-font 的热潮(额,好像国内一直都在用系统字体)。最近更新了 WordPress 4.7,并用上了其 2017 主题,这个主题正是使用系统字体。但是在 macOS 上查看发现中文显示的是繁体字形。 实在是太丑了,究其原因,其实是因为新版的主题的 system-font 用的是繁体中文字体:

html[lang^="zh-"] body,html[lang^="zh-"] button,html[lang^="zh-"] input,html[lang^="zh-"] select,html[lang^="zh-"] textarea {    font-family: "PingFang TC", "Helvetica Neue", Helvetica, STHeitiTC-Light, Arial, sans-serif;}

看来这是 WordPress 的 Bug,已经提交并修复。在官方修复前,可以在外观的 “自定义” 里面添加以下 CSS 解决此问题:

html[lang="zh-CN"] body,html[lang="zh-CN"] button,html[lang="zh-CN"] input,html[lang="zh-CN"] select,html[lang="zh-CN"] textarea {    font-family: "PingFang SC", "Helvetica Neue", Helvetica, STHeitiSC-Light, Arial, sans-serif}

为什么这次 WordPress 要为每个语言单独指定系统字体呢?因为如果将字体设置为 -apple-system 后,在 Safari 下能够正确显示苹方字体,但是在 Chrome 下显示的还是老的字体。但如果特定指明字体种类,就能正确显示了。

用回 WordPress 自带评论系统

By: James Guo
22 August 2016 at 11:32

最近 Disqus 被某国的墙搞的十分不稳定,于是又用回了 WordPress 自带的评论系统,但是这个评论系统却不带评论者被回复时的邮件提醒。我有自己的发信服务器(AWS SES)系统,所以理论上可以配合插件实现这个效果。但是我看了很多插件,基本上操作页面都太复杂,而且回复的邮件通常不支持中文,我只需要一个简单的回复系统,不用那么麻烦,于是干脆自己开发一个,最终比较完美的实现了这个功能。

我开发的这个功能特点是:当评论者被回复时,邮件标题是 “Re: [文章标题]”,这样评论者的一个留言被多个人回复时,会被自动在本地邮件客户端上归为一类;而且评论者收到邮件后可以直接回复邮件,会直接给回复的发出者发邮件(不会显示在网站上,我也无法看到,这将是两人的私聊)。

邮件内容简洁,无额外无用的东西,不会被认定为 Spam。

收件例子

所有代码已经放到 GitHub Gist 上。

<?phpfunction tlo_comment_mail_notify($comment_id) {    global $comment_author;    $comment = get_comment($comment_id);    $parent_id = $comment->comment_parent ? $comment->comment_parent : '';    $spam_confirmed = $comment->comment_approved;    $from = $comment->comment_author_email;    $to = get_comment($parent_id)->comment_author_email;    if (($parent_id != '') && ($spam_confirmed != 'spam') && $from != $to && $to != get_bloginfo('admin_email') ) {        $blog_name = get_option('blogname');        $blog_url = site_url();        $post_url = get_permalink( $comment->comment_post_ID );        $comment_author = $comment->comment_author;        $subject = 'Re: '.html_entity_decode(get_the_title($comment->comment_post_ID));        $headers[] = 'Reply-To: '.$comment_author.' <'.$comment->comment_author_email.'>';        $comment_parent = get_comment($parent_id);        $comment_parent_date = tlo_get_comment_date( $comment_parent );        $comment_parent_time = tlo_get_comment_time( $comment_parent );        $message = <<<HTML<!DOCTYPE html><html lang="zh">    <head>        <meta content="text/html; charset=utf-8" http-equiv="Content-Type">        <title>$blog_name</title>    </head>    <body>        <style type="text/css">        img {            max-width: 100%; height: auto;        }        </style>        <div class="content">            <div>                <p>$comment->comment_content</p>            </div>        </div>        <div class="footer" style="margin-top: 10px">            <p style="color: #777; font-size: small">                &mdash;                <br>                Reply to this email to communicate with replier directly, or <a href="$post_url#comment-$comment_id">view it on $blog_name</a>.                <br>                You're receiving this email because of your comment got replied.            </p>        </div>        <blockquote type="cite">            <div>On {$comment_parent_date}, {$comment_parent_time},$comment_parent->comment_author &lt;<a href="mailto: $comment_parent->comment_author_email">$comment_parent->comment_author_email</a>&gt; wrote:</div>            <br>            <div class="content">                <div>                    <p>$comment_parent->comment_content</p>                </div>            </div>        </blockquote>    </body></html>HTML;        add_filter( 'wp_mail_content_type', 'tlo_mail_content_type' );        add_filter( 'wp_mail_from_name', 'tlo_mail_from_name' );        wp_mail( $to, $subject, $message, $headers );    }}add_action('tlo_comment_post_async', 'tlo_comment_mail_notify');function tlo_comment_mail_notify_async($comment_id) {    wp_schedule_single_event( time(), 'tlo_comment_post_async', [$comment_id] );}add_action('comment_post', 'tlo_comment_mail_notify_async');// add_action('comment_post', 'tlo_comment_mail_notify');function tlo_mail_content_type() {    return 'text/html';}function tlo_mail_from_name() {    global $comment_author;    return $comment_author;}function tlo_get_comment_time( $comment ) {    $date = mysql2date(get_option('time_format'), $comment->comment_date, true);    return apply_filters( 'tlo_get_comment_time', $date, $comment );}function tlo_get_comment_date( $comment ) {    $date = mysql2date(get_option('date_format'), $comment->comment_date);    return apply_filters( 'tlo_get_comment_date', $date, $comment );}

几个 WordPress 的加速建议

By: James Guo
9 June 2016 at 17:36

WordPress 是目前最流行的内容管理系统,本网站正是使用着它。但对于一个全新安装的 WordPress 来说,它的性能并不是很高,当网站的访问量突然增加时,优化性能就显得十分重要了。通过实施以下几个方案,可以大大提升 WordPress 访问速度:

配置缓存

WordPress 是一个动态的系统,如果不配置缓存,每次请求都需要服务器去读取数据库,生成页面内容,对于不同性能的主机,这可能就需要 20ms~1000ms 甚至更慢。如果能够正确配置缓存,就可以明显的加速,并且减少主机的运算资源。

配置页面缓存

使用插件来配置缓存是最简单的方法。在此推荐 WP Super Cache,这是 WordPress.com 出品的缓存插件,就页面缓存来说,功能非常全面,它支持多种缓存模式,包括 mod_rewrite,如果你使用 Nginx,那么可以使用我这个配置文件,这样可以直接跳过 PHP 而直接服务静态文件,页面相应速度有显著提升。 同时,为浏览器返回正确的 Cache-Control 也是十分有必要的,尤其是 CSS 和 JS 文件。

配置对象缓存

对象缓存比页面缓存更灵活,使用范围更广,但速度肯定不如页面缓存。在此推荐 APCu 缓存系统。在 Ubuntu/Debian 安装方法如下:

$ apt install php-apcu

然后重启 Web server,安装 APCu Object Cache Backend 即可。 Redis、Memcached 等都算此类型的缓存,不过 APCu 配置最为简单,速度也很快。

建立分布式缓存系统

比如我的网站使用北美东岸(主要)和亚洲的 VPS,主服务器配置了 Nginx,PHP 和 MySQL;亚洲的服务器只配置了 Nginx。在这些服务器上都配置好缓存,并用 lsyncd 同步缓存内容。每次访问时 Nginx 检查缓存,仅当没有缓存时代理,这样可以大大减少首页面的延迟。

使用 CDN

使用全站 CDN

使用全站 CDN,可以免去在自己的服务器上配置缓存的问题,还可以为服务器增加 HTTPS、HTTP/2 等功能,同时还能过滤非法流量,防御 DDOS(前提是你的 IP 没有被暴露,或者你设置好了白名单)。 除此之外,使用 CDN 后还能更加明显的提高网站加载速度,让访客从中受益。

使用 CloudFlare

CloudFlare 是可以免费使用的,使用 CloudFlare 前需要更改 DNS 服务商,然后无需额外配置就能使用了。但是它只会缓存 CSS、JS 和多媒体文件,不会缓存 HTML 页面,也就是说用户每次访问时还是会返回到原始服务器,页面本身的速度不会有明显提高,在原始服务器上配置缓存也是必要的。

使用 KeyCDN 并配合插件

KeyCDN 是一个按流量使用付费的 CDN 提供商,使用我制作的插件 Full Site Cache for KeyCDN 可以简单的对其配置,这个插件会自动刷新缓存。 KeyCDN 相比 CloudFlare,可以缓存 HTML 页面,大大减少源服务器的压力,同时在刷新缓存时可以通过 Tag 方式刷新,避免不必要的刷新。 在网站访问量较大时,使用 KeyCDN 就能明显的提高速度,缓存命中率也会有很大的提高。

仅资源部份使用 CDN

你可以配置另一个域名,在那个域名上使用 CDN,然后通过插件重写页面地址实现部分 CDN。上文提到的 WP Super Cache 就能配置 CDN,或者使用 CDN Enabler 也能实现部分 CDN 功能。至于 CDN 的选择无所谓,只要支持 Origin Pull(也就是请求回源)就行。

服务器性能

提高服务器本身的性能是最简单的方法,使用更大的内存,更多核心的 CPU 能明显提速。除此之外,提高服务器上应用的性能也很重要:

脚本性能

PHP 脚本的处理速度是 WordPress 的一大瓶颈,使用最新版本的 PHP,可以获得更高的性能,例如 7.0 就比 5.6 快了 3 倍

其次,少用插件能减少 PHP 需要执行的脚本,因为在加载每一个页面时,WordPress 都会加载一遍所有的插件。少量的插件(10个以下)对 WordPress 速度的影响不大,当然也取决于插件本身。

数据库性能

数据库是 WordPress 性能的瓶颈之一,在数据库上优化能提高一定的速度。 一般情况下,如果正确的使用 WordPress,并不需要清理数据库。但可能会有某些插件可能在数据库中创建了太多没用的表,这时服务器的响应速度就会大大降低(约 1~3 倍),推荐使用 WP-Optimize 进行清理。 不是太多的文章数量,是不太会的影响加载速度(1 万篇文章以下速度其实都还能接受,不过你写那么多文章干嘛,质量比数量更重要嘛)。

图片优化

图片占据着网页中很大一部分的大小,同时也关系着用户体验。

图片压缩

对图片压缩不仅可以提高访问时图片加载速度,还能减少服务器带宽 推荐使用免费的 EWWW Image Optimizer,可以在服务器上对图片进行处理。如果你的服务器性能有限,可以使用 Optimus 在线处理,免费版功能十分有限。

响应式图片

对于不同的设备加载不同的图片,比如在手机上加载的图片,就可以比视网膜屏幕的电脑上要加载的图片小的多。使用本站曾经提到过的 srcset 技术可以最简单的实现这个功能,只要你的主题支持就可以了(官方的最新默认主题已经支持),如果主题本身不支持,也可以通过插件实现。

禁用不需要的服务

WordPress 中有一些自带的服务你可能并不需要,禁用它们可以减少页面所需要加载的资源以及服务器需要做的事情。

Emoji 支持

WordPress 支持 Emoji 表情符号,但会因此在页面中引入额外的 CSS,使用这个脚本可以禁用它(如果你不需要的话)。

Google Fonts

Google Font 在国内加载非常慢,而且加载完成之前页面会一直白屏。你可以专门安装 Disable Google Fonts 的插件,或者在下文要提到的 Autoptimize 插件中的设置里禁用它。

Pingback

进入 设置 => 讨论 中可以禁用 “尝试通知文章中链接的博客” 和 “允许其他博客发送链接通知(pingback和trackback)到新文章” 功能(如果你不需要的话)。 此功能并不影响页面加载时间。

减少请求数和页面大小

减少请求数在也一些情况下也能提高加载速度,减少页面大小能缩短下载页面所需要的时间。推荐使用 Autoptimize,它可以 minify CSS、JS 和 HTML,还能 combine CSS 和 JS 以减少请求数。

然而,如果你的博客启用了 HTTP/2 协议,那么减少请求数就没什么必要了,不过为了启用 HTTP/2,必须要使用 HTTPS,所以最终下来是快是慢也不好说。不过还是强烈推荐使用 HTTPS,为了安全,牺牲点速度算什么。

总结

做到上面几点,就能有效提速了,我的网站做到以上几点,在国内无缓存的 Wi-Fi 情况下本网站的时间线如下:

在 1 秒钟内完成包括图片在内的加载

WordPress 上的几个推荐安装的插件

By: James Guo
29 January 2016 at 10:19

EWWW Image Optimizer

无损及有损压缩 JPEG 和 PNG 图像,支持压缩已有的图像,可以加快访问者加载图片的速度。同时支持 JPEG 的渐进式加载。正常情况下,网速低时,图片是一点点从上往下加载,而使用渐进式加载,则是先加载这个图片的低分辨率版本,然后逐渐变得清晰。我已经成为这个插件的付费用户,能够进一步有损压缩 PNG 和 JPEG 格式图片、降低服务器 CPU 占用(否则每上传一张图片,CPU 都消耗很多)。不过最近使用了 Cloudflare 的 Polish 功能,就没有再在服务器上安装同类软件了。

Autoptimize

这个插件能够自动的合并 CSS 和 JS,并对其压缩,非常的方便。而且一些主题会有大量的 inline CSS,当开启了合并 CSS 后,这些 inline CSS 会自动添加到文件中。 我在这个插件中的一些配置,分享出来:

Exclude scripts from Autoptimize

functions.js,player,mediaelement,sparkline,toolbar,admin,akismet,themes

  • functions.js,themes:排除所有主体主题相关的脚本,全面解决合并后会导致菜单的交互出现问题
  • player,mediaelement:排除 WordPress 播放器的合并,因为这部分文件有的页面有,有的页面没有
  • sparkline,toolbar,admin:这些文件只有用户登录后才会加载
  • akismet:安装了 akismet 插件后推荐添加

Exclude CSS from Autoptimize

admin,mediaelement,wordfence,piwik,toolbar,dashicons,crayon-syntax-highlighter/themes,crayon-syntax-highlighter/fonts

  • admin,mediaelement,toolbar,dashicons:同上,只有管理员才会加载,或者是只有部分页面才会加载的东西
  • crayon-syntax-highlighter/themes,crayon-syntax-highlighter/fonts:排除 Crayon Syntax Highlighter 插件仅在部分页面才会加载的 CSS
  • wordfence,piwik:排除一些插件

建议开启

  • Optimize HTML Code:优化 HTML 代码,能减少页面大小
  • Optimize JavaScript Code:优化 JS 代码,能减少 JS 大小并合并 JS
  • **Force JavaScript in <head>**:能提前加载 JS
  • Optimize CSS Code:优化 CSS 代码,能减少 CSS 大小并合并 CSS
  • Generate data: URIs for images:将文件直接嵌入 CSS 中,减少请求数
  • Remove Google Fonts:移除 Google 字体,这种字体文件都是只对西文有效的,对于中文没有意义。
  • Also aggregate inline CSS:将 Inline 的 CSS 放到 CSS 文件里,能减少页面大小
  • Save aggregated script/css as static files:能提高处理性能

建议关闭

  • Keep HTML comments:有些时候 HTML comments 是有作用的
  • Also aggregate inline JS:每个页面的 JS 都不同,不要开启
  • Add try-catch wrapping:没有什么意义的东西
  • Inline and Defer CSS:将 CSS 全面嵌入到页面里,会极大增加页面大小,但能减少请求数,但是真的大多数情况下只会让网站更慢。
  • Inline all CSS:同上

AMP

插件作者是:Automattic ,为 Google 优化,搜索结果中展示超快的 AMP 页面。详情:使用 AMP 构建超快的移动页面

Google Authenticator

二部认证器(需要配合同名手机客户端,或者 1Password 专业版)。你可曾听说过 Heart Bleed 漏洞?有了二部认证,就算再有 Heart Bleed 漏洞,都无需害怕。 原理:手机生成器上扫描二维码保存密钥,然后生成器根据时间变量生成6位数字。这6位数字有有效期,并且只能用一次。安全性甚至大于短信验证码

IP Dependent Cookies

更换 IP 后需要重新登录,就算使用 HTTP 也可以一定程度上避免 Cookie 泄漏的风险

Wordfence

WordPress #1 的安全防御插件,可限制密码尝试次数防止暴力破解,可为你的 WordPress 增加 WAF 功能,查看实时访问。通过查看它的日志我才发现,原来我的 WordPress 一直在被恶意的暴力破解,有时一天几千次,几乎天天都有。不过还好只要尝试 3 次错误密码,IP 会直接被屏蔽掉,这也是 Failed Logins 数量不多的原因。 像这种是基于应用层面的防御,并不是 Cloudflare 等云加速,抗 DDOS 服务所能防御的。

Crayon Syntax Highlighter

这个插件能够让 WordPress 上展示自动高亮的源代码,有多种主题可以选择,支持多种编程语言。

Slimpack

Slimpack 截图

这是 Jetpack 的简化版,没有 Jetpack 那一堆没用的特性,不需要登录到 wordpress.com,功能齐全,使用起来也非常简便。

XML Sitemap & Google News feeds

这个插件能够自动生成网站的 sitemap.xmlrobots.txt,你可以直接将 sitemap.xml 提交到百度和 Google,这样搜索引擎就不会漏掉你的网站上的每一篇文章了。 这个插件支持 WordPress 的多站点,不需要任何配置,推荐在整个网络上启用。

WP-Piwik

WP-Piwik 截图

这个插件能够让你的整个网站拥有统计功能,支持 WordPress 的多站点,推荐在整个网络上启用。关于 Piwik 配合 WordPress,请参见这篇文章:Piwik 与 WordPress 配合使用,建立强大统计系统

Blubrry PowerPress

这个插件能够让你的 WordPress 生成一个 Podcast Feed,让你有一个播客平台,你也可以把这个 Feed 直接提交到 iTunes 等地方。

iOS 上播客软件的截图

Exif Caption

这个插件可以让你将图片的 Exif 信息插入到图片的说明中,缺点是需要上传图片后手动添加,但是它可以批量添加,还算方便。将 Exif 信息插入到图片的说明后,再将这个图片插入到文章中,Exif 信息就能够显示在文章中。

Matomo 与 WordPress 配合使用,建立强大统计系统

By: James Guo
23 January 2016 at 08:00

在配合使用之前,首先需要安装 Matomo (原 Piwik)。前往 Matomo 官网下载软件包,然后解压到服务器上。当然,如果你的服务器上支持一键安装 Matomo 那更好。需要 PHP 环境和 MySQL 数据库。安装只需要根据步骤一步步来就好了。最好和 WordPress 安装在一个主机下,这样更方便配合使用。

地理位置功能

前往设置中的地理位置页面,在页面左下角选择下载一个 GeoIP 数据库。下载了之后,你就可以使用 GeoIP (Php) 了,然而这个比较慢。我推荐你使用 GeoIP (PECL),如果你使用的是 cPanel,那么你可以直接在 Select PHP Version 页面中开启 GeoIP 模块,然后再去 php.ini 中加入或编辑这一行:

geoip.custom_directory = /Matomo/misc

然后就 OK 了,选择 GeoIP (PECL) 即可!

安装中文字体

如果你的语言设置的是中文,那么你的图像报表中会出现乱码。请 下载字体文件,然后解压放到 plugins/ImageGraph/fonts/ 下即可。

与 WordPress 配合使用

首先,需要在 WordPress 下安装 Matomo Analytics(完美支持多站点),之后前往设置。如果你的 WordPress 和 Matomo 都安装在一个站点下了,那么就选择 PHP API,否则选择 HTTP API。填写 Matomo 路径和 Auth Token(可在 Matomo 的后台中找到)即可,然后打开 Enable Tracking,选择默认跟踪即可。在 Show Statistics 里可以选择在哪些地方显示哪些统计,非常方便。

当你选择了 Show per post stats 后,你可以在每一个文章的编辑页面都能看到这个文章的访客信息,非常赞。

与 CloudFlare 配合使用

首先,为了能够正确的识别用户 IP,你需要在 config/config.ini.php 中添加下面这行代码。

proxy_client_headers[] = "HTTP_CF_CONNECTING_IP"

如果你的 CloudFlare 启用了 IP Geolocation 功能,那么你其实不需要在主机上开启 GeoIP。只需要根目录下创建 .htaccess 文件,添加下面这几行代码:

RewriteEngine OnRewriteBase /RewriteRule ^ - [E=GEOIP_COUNTRY_CODE:%{HTTP:CF-IPCountry}]

然后前往 Matomo 统计的地理位置选项,现在,你的地理位置选项就可以选第三个了 GeoIP (Apache),这个是速度最快的。

苟日新

By: fivestone
5 September 2023 at 07:41

突然被人跑来问,是怎么做到写博客坚持这么久的,而且可以持续输出?

(荣幸地,拿起话筒:)啊,我不觉得我这个样子,叫做「持续输出」啦。早就连每月一更都不能保证了,而且那些技术相关的帖子,在我心里都不能算是「更新博客」的,用这些凑数也为我自己所不齿……

但我看到这个问题时,首先想到的,一个很重要的因素:大概是因为,这个站就一直在这儿吧~ 我的技术能力,不需要花什么额外的精力,就能让这个 blog 一直存活下去。于是,想写东西的时候,这里始终有个地方,可以让我写。

——也有很多时期,是完全写不下去的,长时期没法去面对、去反刍自己的生活;然而也没必要因此而关站,就让 blog 存活在那里,终归是个表述的出口。大概是因为,我也是希望,自己能够从那些「无法整理自己」的状态中,渐渐走出来,回复到可以写东西的状态吧。所以站点的持续存在,满重要的,因为确实能感觉到,想写点什么的时候,如果没有这么个站,又或者需要自己重新架一个,可能也就不写了……


这种「随时可以在站点写东西」的状态,也影响着对 blog 平台的选择(怎么又拐到技术贴去了?好吧,之前也一直想吐槽这方面,就顺带提一下)。这些年一直有 〖wordpress vs 各种静态博客〗哪个更好的争论。双方确实各有利弊。总体来说,静态博客最大的优点就是……省钱,可以薅 github、vercel 之类托管网站的羊毛。但另一方面,静态博客每次发布、或者修改一篇文章的过程,其实满折腾的。通常情况下,它需要

  • 一台固定的电脑,安装静态博客编译程序,并且从这台电脑发布到 github 的专门权限。而不是随便打开一台电脑或手机,从浏览器就能编辑发文;
  • 每次发文时的一系列专门操作。

我不乏看到有人,好久没有更新,突然想写一篇文章时,忘了怎么操作,翻出攻略来重温一遍;甚至忘了连接 github 的 ssh-key……可能别人觉得这样的折腾无所谓,或者自我管理优秀的话,不会出现这种情况。但我个人觉得,这是会在主观上,影响发文章的状态的。所以,随便在任何地方任何电脑上都能直观地发文,感觉还是蛮重要的。

好像也是可以通过一系列操作,实现用浏览器某个网站上编辑文章,然后自动编译发布到托管网站的。我没有仔细去关注。但是,如果把 blog 的生命周期,放到 5~10 年这个尺度上,那么这些网站之间的复杂依赖关系,很大程度上是不靠谱的。譬如我已经看到好几个静态 blog 的外挂评论系统,不知为什么不工作了……总之,相比之下,我可能更宁愿去使用那些免费带广告的 blog 平台。

我对写 blog 的新人的推荐,一直是——

  • 如果有技术能力、也有服务器的话,自建 wordpress;
  • 或者找人蹭一个。如果我们比较熟,你可以去买个域名,把 blog 挂在我的服务器上。这并不是很大的负担。(ps,个人 wordpress 小站,是可以不必安装开销很大的 mysql 数据库的);
  • 如果上面两条都不行,那么,我优先推荐去注册现成的 wordpress.com 或者 blogspot.com,目前看起来,长期靠谱的只有这两家了。虽然免费版界面不好看、还有广告,但长期写着应该没问题的;
  • 当然,我不会给乐于尝试静态博客的人泼冷水。但我会根据你的技术能力和气质,暗戳戳地担心:
    • 你能坚持写多久;
    • 你写出来的,会不会很多都是关于你怎么建站的经历和心得……

转一张,对于熟悉这十几年来 blog 平台变迁的人,应该会很搞笑:用不同工具写 blog 的人,(写 blog 文章)vs(写关于怎么配置 blog 的文章)的对比。右下角那些术语,都是在各个年代,需要各种不同程度的折腾的,静态 blog 方案:gatsby、org mode、jekyll、hugo、git workflow……


ps,两个月前,用这段代码方案,把我在 twitter 的所有 po 文,都导入到了自建的 mastodon 里。Twitter 那边,应该会随着 Elon Musk 的各种不靠谱折腾,渐渐放弃掉了吧。而每条推文的字数限制,从 twitter 的 140 字,变成 mastodon 的 500 字后,很多几百字的感受,要不要专门写到 blog 这边来,就比从前,更让人犹豫。具体怎么处理,我还没想好。

❌
❌