WordPress 3.8开启Google AMP的问题

关于 AMP

Accelerated Mobile Pages(简称 AMP)是 Google 带领开发的开源项目,主要为了提升移动设备对网站的访问速度,大概包括 AMP HTMLAMP JSAMP Cache 三部分,非常适合博客及新闻展示类的静态网站。

有关 AMP 的详细介绍可以参考其官方网站:

https://www.ampproject.org/zh_cn/

AMP 网页只能使用 AMP HTML 中允许的有限的标签,不允许使用 AMP Runtime、AMP Components 之外的 JS,而且 AMP Runtime、Components 都必须从 cdn.ampproject.org 加载,因此目前 AMP 网页都必须在翻墙状态下才能正常浏览。

AMP Cache 是负责缓存并传输 AMP 页面的 CDN 服务器,用户在 Google 移动端中点击 AMP 网站时,实际访问的是缓存过的页面。

WordPress 启用 AMP 的问题

WordPress 官方提供了 AMP 插件以支持直接为博客开启 AMP 加速,只是官方插件要求 WordPress 最低为 4.4 版本。

由于我的博客安装了 qTranslate 这款多语言插件,而该插件却只支持到 WordPress 3.8.1 版本,如果升级 WordPress 到最新版本,qTranslate 插件就会自动禁用。然而 qTranslate 插件是对 WordPress 数据库直接进行修改的,禁用之后博客文章就可能会同时显示多种语言的内容,这样显然是不可接受的。

虽然网上已经有人继承 qTranslate 原作发布了例如 qTranslate X 之类的支持新版本 WordPress 的插件,但为了数据安全(其实是懒)考虑我暂时还是不打算直接升级 WordPress 了。

不过还好我在 WordPress 插件库里找到一款看起来支持 WordPress 3.8 的 AMP 插件:AMP for WP,毕竟看此插件的介绍和评分都比官方的 AMP 插件要强哦,而且最低只要求 WordPress 3.0 版本。

AMP for WP 安装起来还是非常顺利的,插件选项里目前基本只提供了 Google Analytics UID 的设置选项,启用之后访问 AMP 版网站的方法是在地址后面加上 ?wpamp 后缀。

不过我刚开始测试访问 AMP 首页和文章就碰到问题了,直接没有任何显示了,看网页源代码输出信息不全,显然是 AMP for WP 插件对老版本 WordPress 兼容性还是有点问题。

修改 AMP for WP

首先修改 AMP for WP 插件的 wp-amp-ninja/admin/common.php 文件,打开 PHP 报错开关:

error_reporting(1);

这下访问博客首页和文章页面就能看到详细报错了:

Fatal error: Call to undefined function get_the_permalink() in /www/zohead.com/wp-content/plugins/wp-amp-ninja/includes/wpamp-front.php on line 24

Fatal error: Call to undefined function the_posts_pagination() in /www/zohead.com/wp-content/plugins/wp-amp-ninja/template/wpamp-content.php on line 53


Fatal error: Call to undefined function the_archive_title() in /www/zohead.com/wp-content/plugins/wp-amp-ninja/includes/wpamp-functions.php on line 600

Fatal error: Call to undefined function the_archive_description() in /www/zohead.com/wp-content/plugins/wp-amp-ninja/includes/wpamp-functions.php on line 601

经过查阅 WordPress 官方文档发现:

  1. get_the_permalink 函数在 WordPress 3.9.0 版本开始引入,其实就是 1.0.0 版本就已经有的 get_permalink 函数;
  2. the_posts_pagination 函数在 WordPress 4.1.0 版本开始引入,一同引入的还有 the_posts_navigation 函数,与 get_the_permalink 函数一样都位于 WordPress 代码库的 wp-includes/link-template.php 文件;
  3. 至于 the_archive_titlethe_archive_description 函数的功能比较类似,支持显示文章的标题和描述并在前后插入自定义代码,同样也在 WordPress 4.1.0 版本开始引入,位于 WordPress 代码库的 wp-includes/general-template.php 文件。

由此可见,AMP for WP 实际上应该至少要求 WordPress 4.1.0 版本,只是作者并没有测试过是否兼容较低版本的 WordPress。

不过还好我看了下 WordPress 最新 4.8 版本的代码,上面缺少的几个 WordPress 内置函数都是功能比较独立的。

因此我稍微修改了一下博客目录下的 link-template.phpgeneral-template.php 文件,将最新版本的 get_the_permalinkthe_posts_paginationthe_posts_navigationthe_archive_titlethe_archive_description 函数实现分别 Backport 到 WordPress 3.8 版本。Backport 完成之后再访问博客首页和文章,就没有 PHP 报错了。

不过初步试用下来,我还是发现 AMP for WP 插件的一些小问题:

  1. 如果通过 qTranslate 插件访问博客的英文版本(通过增加 ?lang=en 地址后缀),对应的 AMP 版页面地址会不正确,AMP for WP 插件在转换地址时并没有考虑地址中会带有其它后缀的情况;
  2. AMP for WP 对于带有多种语言标题的文章直接显示数据库中多种语言合并在一起的标题效果,而并不是 qTranslate 插件根据客户端语言自动处理后的效果,这个问题在我使用的几个 WordPress 主题中都不会出现;
  3. 文章中插入的多行代码被合并成一行显示了,这是明显不能接受的;
  4. 文章的中文发表时间无法正确显示,统一显示为当前日期。

第一个问题需要修改 AMP for WP 插件的 wpamp-front.phpwpamp-functions.phpwpamp-header.php 这几个文件中转换地址的代码,例如 wpamp-front.php 文件的修改:

 		$the_permalink = get_the_permalink( $post->ID );
 	}
 	
-	$the_permalink = rtrim( $the_permalink, '/' ) . '/';
+	$the_permalink = rtrim( $the_permalink, '/' );
 	$perma = strpos( $the_permalink, "?" );
 	if ( $perma === false ) {
+		$the_permalink .= '/';
 		$sConnector = "?";
 	} else {
 		$sConnector = "&";

第二个问题需要修改 wpamp-content.php 文件,文章标题要做 apply_filters 处理:

                 <div id="amp-pagination">
                 	<?php $prev_post = get_previous_post(); if (!empty( $prev_post )): ?>
-                    	<div class="prev"><a href="<?php echo wp_amp_permalink($prev_post->ID, AMP_CONSTANT); ?>"> &laquo; <?php echo $prev_post->post_title ?></a></div>
+                    	<div class="prev"><a href="<?php echo wp_amp_permalink($prev_post->ID, AMP_CONSTANT); ?>"> &laquo; <?php echo apply_filters( 'the_title', $prev_post->post_title, $prev_post->ID ); ?></a></div>
 					<?php endif ?>
 					<?php  $next_post = get_next_post(); if (!empty( $next_post )): ?>
-                        <div class="next"><a href="<?php echo wp_amp_permalink($next_post->ID, AMP_CONSTANT); ?>"><?php echo $next_post->post_title ?> &raquo; </a></div>
+                        <div class="next"><a href="<?php echo wp_amp_permalink($next_post->ID, AMP_CONSTANT); ?>"><?php echo apply_filters( 'the_title', $next_post->post_title, $next_post->ID ); ?> &raquo; </a></div>
 					<?php endif ?>
                     <div class="clearfix"></div>
                 </div>

第三个问题就比较简单了,将 simple_html_dom.php 文件中替换回车和换行符的处理去掉就可以了。

第四个文章发表时间的问题也可以修改 wpamp-content.php 文件简化处理:

                     <?php endif; ?>
                     By <span class="amp-wp-author"><a href="<?php echo wp_amp_permalink( NULL, AMP_CONSTANT, get_author_posts_url( get_the_author_meta( 'ID' ) ) ); ?>"><?php echo esc_html( get_the_author() ); ?></a></span>
-                    <?php $the_time = date_i18n( get_option( 'date_format' ), strtotime( get_the_time('F jS, Y') ) ); ?>
-                    on <time datetime="<?php echo $the_time; ?>"><?php echo $the_time; ?></time>
+                    on <time datetime="<?php echo get_the_date('c'); ?>"><?php echo get_the_date('c'); ?></time>
                 </li>

另外我还对 AMP for WP 插件的页脚处理做了点小修改,将页脚上切换到博客首页桌面版本的链接改为切换到当前文章的桌面版本,方便访问者使用。

总结

对 AMP for WP 插件修改完成之后就可以访问博客的 AMP 版进行验证了,例如我的博客的 AMP 版首页地址就是:

https://zohead.com/?wpamp

普通用户可以通过安装 Google 推出的 AMP Validator 官方 Chrome 扩展检测所访问的 AMP 站点是否配置正确。

网站所有者可以用 Google 搜索的 AMP 在线测试工具进行检测:

https://search.google.com/test/amp

输入要测试的 AMP 版网址就可以开始检测,另外这个测试工具的另一个好处就是检测通过之后可以直接把你的 AMP 站点提交给 Google,让 Google 搜索蜘蛛尽快收录并进行 CDN 缓存。

现在通过 Google 移动端(例如 Android Chrome 浏览器)搜索我的博客,应该就能在搜索结果里看到下面的 AMP 闪电标志了:

Google 搜索结果 AMP 标志

点击搜索结果,你会发现访问的其实是 Google 缓存过的 AMP 地址,下面地址只有移动端浏览器才会显示 AMP 网页:

https://www.google.com/amp/s/zohead.com/%3fwpamp

初步启用 AMP 的大体感受就是如果你的梯子还可以,那访问 Google 缓存过的 AMP 网站速度还是非常快的,我这里估计访问 AMP 版网站所需要的流量大概为桌面版本的 1/3。

后面有时间的话还是希望能对 AMP for WP 插件继续改进,例如支持其它的 AMP 后缀或者使用专门的 AMP 子域名方便自己的服务器进行缓存之类的,最后祝大家玩的开心。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*