从去年(2016年)秋季重新收拾这个网站开始,本着精益求精的想法,从结构上完成这个站点的优化。WordPress本身是为Apache而设计的,它有更新.htaccess
的一系列方法,使得网站可以正常工作。但是如果使用了nginx作为服务器,.htaccess
文件不起作用了,因而弯路是需要走一点的。
下面根据本站的情况进行配置的总结。
本站运行条件是:
腾讯云服务器
1核心 Xeon E5-26xx / 1GB DDR3 RAM
网络带宽 1Mbps / 本地盘
Ubuntu 16.04 amd64打广告,我的企鹅云推荐码是:GIZZQP
首次购买企鹅云服务器输入享9折优惠哦~
WordPress的ReWrite规则
SEO的原则一般就是机器可读性强、文字语法合理。首先很多人搞SEO的第一步就是把WordPress自带的?p=123
一类的固定链接换掉。这个时候,用Apache的孩子不会发现有什么异常。而用nginx的孩子回到自己的主页,正满心欢悦地想看看自己那有逼格的固定链接的时候,却被送了满屏幕的404 Not Found。这是为什么呢?
打开WordPress的.htaccess
文件,内容是这样的:
# BEGIN WordPress RewriteEngine On RewriteBase / RewriteRule ^index\.php$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L] # END WordPress
大概的意思,就是找不到请求uri的文件的时候,自动把path重写到index.php
这一个入口。现在就以本文链接https://xzclip.cn/serverheld/note-for-this-website-1/为例子分析:
- 你请求uri为
/serverheld/note-for-this-website-1/
的文档; - nginx理所当然地找不到文档;
- nginx向你扔出了一个404…
但是经过重写配置之后的情况是这样子的:
- 你请求uri为
/serverheld/note-for-this-website-1/
的文档; - nginx理所当然地找不到文档again;
- nginx
变机智了,重写uri到index.php,自己请求uri为index.php/serverheld/note-for-this-website-1/
的文档; - WordPress返回正常的内容给nginx,nginx将得到的内容作为
/serverheld/note-for-this-website-1/
的内容发送给你的浏览器。
由于使用WordPress的nginx用户已经很多了,所以说网上总结的重写方法有很多。对于经常流传的,会是这个版本:
if (-f $request_filename/index.html){ rewrite (.*) $1/index.html break; } if (-f $request_filename/index.php){ rewrite (.*) $1/index.php; } if (!-f $request_filename){ rewrite (.*) /index.php; }
不过在进行WP-Super-Cache的配置时,这种简单粗暴的方法完全不能符合要求。而且WordPress官方现在给出了一套更加简洁的方案。[1]
修改site的配置文件中location /
段为如下内容:
location / { try_files $uri $uri/ /index.php?$args; } rewrite /wp-admin$ $scheme://$host$uri/ permanent;
代码的意思是,当有一个uri被请求时,会先查找对应文件,再查找对应文件夹下index语句定义的索引页面,最后把请求交给index.php
处理。最后的一句是用以解决进入了uri为/wp-admin
(结尾不带/
)的后台的时候,点击的所有设置链接无效的问题,建议未配置的萌新加上。
如果WordPress的安装目录不是根目录,应该按照如下修改:
location /path/to/wordpress/ { try_files $uri $uri/ /path/to/wordpress/index.php?$args; } rewrite /path/to/wordpress/wp-admin$ $scheme://$host$uri/ permanent;
回头一看,你有了一条逼格满满的……固定链接哈哈哈~
WP Super Cache重写模式配置
相信我和很多人,使用WP-Super-Cache是为了加快页面的提供速度,毕竟WordPress的效率确实很低。对于Apache用户,又双叒叕可以轻轻松松地用上各种很好用的功能,而对于nginx用户,又要走弯路了。虽然,还是能直接使用PHP缓存方法,但是nginx处理静态文件的能耐就被浪费了。不过,这个插件的作者考虑到有广大nginx用户的实际,给出了一个重写方法。[1]
set $cache_uri $request_uri; #POST请求交由php处理 if ($request_method = POST) { set $cache_uri 'null cache'; } if ($query_string != "") { set $cache_uri 'null cache'; } #这些请求uri是不能缓存的 if ($request_uri ~* "(/wp-admin/|/xmlrpc.php|/wp-(app|cron|login|register|mail).php|wp-.*.php|/feed/|index.php|wp-comments-popup.php|wp-links-opml.php|wp-locations.php|sitemap(_index)?.xml|[a-z0-9_-]+-sitemap([0-9]+)?.xml)") { set $cache_uri 'null cache'; } #不要为已知用户提供缓存(如已登陆用户、评论过的用户) if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_logged_in") { set $cache_uri 'null cache'; } location / { #如果你是普通用户,用以下语句: try_files /wp-content/cache/supercache/$http_host/$cache_uri/index.html $uri $uri/ /index.php?$args; #如果你配置了纯https,用以下语句: #try_files /wp-content/cache/supercache/$http_host/$cache_uri/index-https.html $uri $uri/ /index.php?$args; }
配置无误后,在运行nginx -t
检查语法之后再进行nginx的重载即可。
搭载systemd的系统重载命令:systemctl reload nginx
之后在插件页面更新设置,配置好预缓存设定确定生成supercache文件即可。
等到预缓存完成,可以尝试将php-fpm的服务停止,然后用隐私模式浏览页面。此时如果仍正常,则mod_rewrite模式配置成功。
进阶 – 配置gzip压缩缓存与提供预压缩文件
在插件设置页面的“高级”选项卡中爽朗地选择“压缩页面以便让来访者更快浏览。 (推荐)”,更新设置。细心的孩子会发现,生成的supercache文件中都有一个带有.gz
后缀的文件。这个时候需要利用一个nginx的特性。
在site配置文件或者nginx.conf添加如下内容:[2]
gzip on; gzip_static on;
第一句话很好理解,打开gzip压缩,而第二句话,意思就是:
当客户端支持gzip压缩时,查找对应文件带.gz
后缀的预压缩文件,直接提供给客户端。此时会自动把生成的预压缩文件提供,无需nginx再自行压缩,节约了CPU资源。
使用CDN/对象储存提供静态资源(动静态分离)
因为国外云服务器到国内速度很一般,或者国内云服务器的带宽小得可怜,往往打开带有大量元素的网页会非常缓慢。在网站业务推进之后,访问量变大时,体验就下去了。此时需要一些图床或对象储存解决静态资源的分发。
本文以腾讯云为例进行操作实例,其余平台自行参考。
配置静态元素站点
首先在www目录(Debian/Ubuntu是/var/www
)建立静态内容文件夹,链接你需要静态加速的资源文件夹:
mkdir /var/www/static/ ln -s /var/www/path-to-your-wordpress/wp-includes /var/www/static/wp-includes ln -s /var/www/path-to-your-wordpress/wp-content /var/www/static/wp-content #...
随后编辑站点文件:
server { listen 80 default_server; listen [::]:80 default_server; server_name 你的静态站点域名; root /var/www/static; location / { try_files $uri $uri/ =404; } location ~* \.(js|css|png|jpg|jpeg|gif|ico|tiff|mp3|mp4)$ { expires 10d; } location ~* \.php$ { deny all; } location ~ /\.ht { deny all; } location /wp-content/cache/ { deny all; } }
随后检查语法、重载nginx。此时服务器已经准备就绪了,下一步在云服务的控制台上配置:
使用对象储存配置
对象储存可以用以储存一些静态文件,作为一种在网络上廉价提供文件的方法。对象储存使用云服务厂商的域名,所以说无需考虑备案的问题;通常对于小开发者,对象储存服务是会提供一定免费额度的,因此对象储存加速成本会很低。
- 新建一个Bucket
点击创建Bucket,配置好自己对象储存的属性:
- 进入配置界面,设置回源。
因为这是一个储存库,里面不一定有所需数据。当客户端请求一个文件时,如果储存库没有这个文件,将触发回源操作,对象储存库会自动拉取文件,并自动返回给客户端。
- 获取域名,通过cdn插件替换资源路径。
本实例使用的是WP Super Cache的CDN功能。域名如下图:
此时应该在插件页填写设置:
- 保存设置,查看效果。
第一次访问会进行回源,所以速度会比较慢。
使用CDN(内容分发网络)配置
使用内容分发网络可以实现更加灵活的缓存配置,而且因为节点数目多,因而可以获得更快的速度。但是,CDN一般都不是免费的。CDN要求绑定域名,所以说一方面,域名需要备案才可以使用;另一方面,CDN支持基于SNI的https。
换句人话说,你用了CDN的话,你的全局https站点小锁能保住,但是android2.3及以下、Windows xp及以下的用户将无法正常地访问了。不过,既然是支持全局https以响应Google、Apple和Mozilla,那就毫无畏惧地抛弃老系统用户吧!
- 老套路,新建CDN。
- CDN必须有源站,配置回源。
- 在域名解析按需配置cname记录
- (可选)配置https。
- 填入CDN插件。
此时注意,纯https网站可以使用//
和https://
前缀
自适应网站可以使用//
后缀
进阶 – 跨站问题解决
由于CORS策略的存在,引用外部网站的资源这种跨域请求往往会被浏览器拦截,因而在对象储存或者CDN上需要配置Access-Control-Allow-Origin。其内容可以是一个站点,或者单纯通配符*以允许在任意网站上引用。[3]
进阶 – 被遗忘的一个js文件
点开浏览器开发者工具的小伙伴会发现,CDN插件替换路径往往不彻底。比如一个叫wp-emoji-release.min.js的文件。查看代码发现,那是写在一个style块的,采用了很多反斜杠用以反转移,因而只能修改代码解决。
方法如下,在主题functions.php文件中添加以下代码:
function filter_my_script_location( $script_url, $script_name ) { if ( 'concatemoji' == $script_name ) { $script_url = '//你的cdn地址/wp-includes/js/wp-emoji-release.min.js'; } return $script_url; } add_filter( 'script_loader_src', 'filter_my_script_location', 10, 2 );
考完电路分析与电子线路基础,第二天还是那么虚。先写到这里吧,有空再补充。
alphaxz@SCUT
References
[1]. Nginx, WordPress Codex
[2]. Module ngx_http_gzip_static_module, Nginx
[3]. HTTP访问控制(CORS), Mozilla