需求背景
由于我们是saas服务 用户需要在自己的网站上添加特定的SEO信息 但是后台管理里配置动态meta是不生效的 原因在于爬虫只会搜索静态资源 并不会读取js加载后的内容 所以针对这个需求 我们整理了一些方案 在这里分享给大家
方案整理
针对这个问题整理了如下两个方案
-
前端打包后把资源上传到S3 然后在后台项目里出一个接口返回S3上的前端页面 这样的话可以读取后台配置里的条目去添加 优点是可以直接从后台配置比较灵活 缺点是要从后端改造 会侵入后端代码 而且用java去返回静态文件的话 服务端压力过大时也会对前端加载造成影响
-
第二个方案是查了一些资料后 确定可以通过直接修改nginx配置 针对不同的域名替换不同的SEO配置 优点是不需要侵入业务代码 改动成本低 缺点是没法通过后台配置 只能每次手动修改 需要重新打包web页面(这里重新打包是因为前端项目部署在docker里 虽然前端文件并没有更改 依然要走整个的ci/cd流程 但是由于前端代码没有变化 打包后的文件哈希并不会变 不会让用户重新加载资源)
实施过程
经过一番讨论我们确定了方案二 因为SEO配置不会频繁改动 而且这种方式的实施成本很低 只需要前端改动下项目里的nginx配置即可 这里我们使用了nginx的sub_filter来进行了第一次尝试 (因为涉及到公司的一些内容 这里对域名和content进行了脱敏 大家替换成自己的域名和content即可)
server {
listen 80 default_server;
server_name _;
root /bh/www ;
index index.html index.htm;
location / {
if ($host ~ "new.xxx"){
sub_filter '<head>' '<head><meta name="google-site-verification" content="xxx" />';
sub_filter_once on;
}
if ($host ~ "xxxxxx"){
sub_filter '<head>' '<head><meta name="google-site-verification" content="xxx" />';
sub_filter_once on;
}
try_files $uri $uri/ /index.html;
}
location ^~ /static/ {
gzip_static on;
expires max;
add_header Cache-Control public;
}
error_page 404 /index.html;
client_max_body_size 20M;
}
sub_filter指令接受两个参数 第一个是要替换的字符串 第二个是替换后的字符串 我们更改成如上配置后进行了第一次尝试.发现nginx没有正常启动起来 报错是"sub_filter" directive is not allowed here 通过查询确定这个问题的原因
这个意思是在http server location这几个规则中 sub_filter无法在其他指令下使用 意味着我们不能写在if里 于是我们这里使用了map来做一个映射 改造后配置如下
map $host $conditional_filter {
~xxx '<head><meta name="google-site-verification" content="xxx" />';
~xxx.app '<head><meta name="google-site-verification" content="xxx" />';
~xxxxxx '<head><meta name="google-site-verification" content="xxx" />';
default '<head><meta name="google-site-verification" content="xxx" />';
}
server {
listen 80 default_server;
server_name _;
root /bh/www ;
index index.html index.htm;
location / {
sub_filter "<head>" $conditional_filter;
sub_filter_types *;
sub_filter_once off;
try_files $uri $uri/ /index.html;
}
location ^~ /static/ {
gzip_static on;
expires max;
add_header Cache-Control public;
}
error_page 404 /index.html;
client_max_body_size 20M;
}
再次提交部署后 部署流程走通 我们来看一下部署后的效果


针对不同的域名正确的返回了对应的meta信息 此时我们的需求就正常完成了 希望我的踩坑经历能对大家有所帮助
参考资料:
use-of-sub-filter-in-if-block-under-nginx-config
nginx_sub_module
