sweeetcc / blog

Personal blog powered by Github issues
2 stars 0 forks source link

SPA 的 SEO 解决方案 #1

Open sweeetcc opened 8 years ago

sweeetcc commented 8 years ago

SPA 的 SEO 解决方案

这一篇放了最久,因为这是一个很老的话题了,大约在我刚刚接触 Angular 的时候,需要处理 Angular 项目的 SEO 问题,实践了一个解决方案,也在实践过程中遇到了很多问题,丰富了这个解决方案。

背景:

当时是 Angular 的时代,还没有流行起来使用 React 和 Vue,也就没有现在的 Server-Render 和 isonomorphic(同构)的解决方案。所以当时的解决方案放在现在的单页面应用上能够有用,但是已经不再推荐了。

方案:

用一张图来表示的话:

spa seo

技术:

基于以上的过程,确定基本使用以下技术来实现:

c6e0a462-08f5-4bce-8927-ab3cad8b4703

遇到的问题:

后面几个问题基本是设置上的问题。

后来,运行的过程中当然也出现了一些问题:

  1. 预爬取不到位,会在爬虫到来时产生很多实时爬取,这样机器的 CPU 和内存消耗飙升;
  2. 使用 redis 存取几十万个页面缓存,很快 redis 的存储被占满,而缓存时间又不能太短,所以决定采用文件存储;
  3. 使用文件存储又遇到问题,加入都存在同一个目录下,Linux 文件系统对于单个目录下存取的文件数量有限制(单个目录最多存储31998个?),所以采用了以下解决方案:
function FileSystem(options) {
  this.options = options;
  mkdirp.sync(this.options.snapshotFolder);
}

/**
 * 从路径中获取 html snapshot
 */
FileSystem.prototype.get = function (hashedPath, callback) {
  var filePath = this.options.snapshotFolder + '/' + hashedPath.substring(0, 10).split('').join('/') + '/' + hashedPath;

  fs.readFile(filePath, 'utf8', function (err, data) {
    if (err) {
      callback(err);
    } else {
      callback(err, data);
    }
  });
};

/**
 * 向路径中存储 html snapshot
 */
FileSystem.prototype.set = function (hashedPath, snapshot, callback) {
  var that = this;
  mkdirp(that.options.snapshotFolder + '/' + hashedPath.substring(0, 10).split('').join('/'), function () {
    var filePath = that.options.snapshotFolder + '/' + hashedPath.substring(0, 10).split('').join('/') + '/' + hashedPath;

    fs.writeFile(filePath, snapshot, function (err, data) {
      callback(err, data);
    });
  });
};

/**
 * 从路径中删除 html snapshot
 */
FileSystem.prototype.del = function (hashedPath, callback) {
  var filePath = this.options.snapshotFolder + '/' + hashedPath.substring(0, 10).split('').join('/') + '/' + hashedPath;

  fs.unlink(filePath, callback);
};

module.exports = function (options) {
  return new FileSystem(options);
};

好啦,这个小小的总结完成了一个心愿。