Koa站群处理网站地图sitemap的最佳实践

之前写了篇《KOA启动多个模版二级域名网站的实践》的文章,昨天在针对这个站群做网站地图sitemap的时候发现一点问题,在网上没找到相关解答,自己解决之后写下这篇文章。

网站地图是做seo比较关键的一个操作,是为了新站得不到搜索引擎爬虫的青睐,主动告诉搜索引擎:我这里有很多链接你来看看。

网站地图有两种格式,一种是txt,一种是xml。

txt就是纯文本格式如下

https://sxg.kuashou.com
https://sxg.kuashou.com/简单的用NodeJS抓取腾讯电视剧数据的实操.html

而xml相对高级一点,除了有链接,还有一些额外的信息告诉搜索引擎


<?xml version="1.0" encoding="UTF-8"?>
  <urlset
    xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://sxg.kuashou.com">
      <url>
        <loc>https://sxg.xxx.com/</loc>
        <priority>1.0</priority>
        <lastmod>2019-02-05</lastmod>
        <changefreq>daily</changefreq>
      </url>
      <url>
        <loc>https://sxg.kuashou.com/简单的用NodeJS抓取腾讯电视剧数据的实操.html</loc>
        <priority>0.8</priority>
        <lastmod>2019-02-05</lastmod>
        <changefreq>daily</changefreq>
      </url>
    </urlset>

相对来说,我更喜欢用xml的,毕竟xml提供了更多的譬如权重,最后更新日期,更新频率等的信息。

建设一个标准网站格式的sitemap.xml后(新建网站地图的过程本文不表),通常要主动在各家搜索引擎的网站管理处提交网站地图的url,譬如百度的提交网站地图是在http://zhanzhang.baidu.com/

通常网站地图的一般规则是根目录下,比方对于我的博客网站https://sxg.kuashou.com,网站地图的url链接就应该是https://sxg.kuashou.com/sitemap.xml

对于使用NodeJS/Koa框架的用户来说,很轻易的能想到把这个sitemap.xml放在静态文件夹里,通常是public,这确实没错。

但是问题来了,我因为管理的是一个站群,会有http://wjk.xxx.com http://yyqx.xxx.com两个站(两个端口进程)共用同一个public,那怎么办?

一开始很傻瓜的想,那干脆就以sitemap的命名来区分,譬如http://wjk.xxx.com的网站地图是http://wjk.xxx.com/wjk_sitemap.xml,而http://yyqx.xxx.com的网站地图是http://yyqx.xxx.com/yyqx_sitemap.xml

但是这太不友好了,为什么其他网站的sitemap都是干净的sitemap.xml而你的却要带个尾巴???

这时思考了一下,想到可以利用之前的配置文件server.config.js在请求逻辑时遍历返回相应的sitemap文件,写成一个中间件!

中间件sitemap核心逻辑


const fs = require('fs')
const path = require('path')

module.exports = async (ctx,next)=>{
  const {
    app
  } = ctx
  let reg = /\/sitemap.(xml|txt)/ //处理xml或txt格式的sitemap路径
  if(reg.test(ctx.request.url)){
    let type = ctx.request.url.split('.').reverse()[0]
    ctx.response.type = type
    ctx.response.body = await fs.readFileSync(path.resolve(__dirname, `../public/${app.hostname}_sitemap.${type}`)) //读取public下不同的文件返回客户端
  }
  await next() //不匹配请求url,交给之后的handler
}

之后再将这个sitemap中间件在路由前挂载到app实例上就完美实现需求。

简单来说,这个中间件就是使a.xxx.com/sitemap.xml返回的是物理服务器里的a_sitemap.xml的这个文件

在解决这个的时候发现koa的一个问题,就是路由中间件捕捉不到.xml结尾的请求,甚是奇怪。

这次处理sitemap的实践同样提交了commit放在了该项目上 https://github.com/18978909244/group-app-demo