Hexo博客评论、代码高亮等组件设置、性能优化及SEO

1 修改主题配色

有自定义的配色还是不错的选择的,所以,我们可以自定义配色。

一般在 /themes/hexo-theme-matery/source/css/matery.css中,搜索 .bg-color 来修改背景颜色,修改标题栏、菜单栏、各种标签背景的颜色,使主题颜色为Material的黑色。感谢Material Design Colours提供的配色方案。

其他的也可以在这个css文件中修改,自己琢磨一下。

2 为你的Hexo加上评论系统-Valine

给个链接:https://blog.csdn.net/blue_zy/article/details/79071414

注意:Valine用在matery主题上有个bug就是第一条评论位置会错位

如下图:

解决办法:

F12开发者模式,控制台定位bug位置,修改参数,调整对应主题源文件参数,得以解决,如下图示:

修改图示

3 SEO 优化

给个链接:https://blog.csdn.net/sunshine940326/article/details/70936988/

4 优化网站加载速度

4.1 优化图片加载

issue问题:

优化网站加载逻辑问题:图片最后加载,加入图片懒加载方法

hexo-lazyload-image的作用原理是讲你博客里面img标签的src属性替换为一个loading image,把真实的图片地址放在data-origin属性下面。然后当你的网页翻到那张图片时(也就是图片在窗口中完全可见时),他会有一段js用data-origin的内容替换src,打到懒加载的目的。

一般情况下懒加载和gallery插件会发生冲突,比如按照我上面所说,最终结果就会变成,可能只有第一张图片在gallery中打开是原图,右翻左翻都会是那张loading image,需要你掌握js,可以修改matery.js里面的内容,甚至可能换一个gallery,比如photosiwpe之类的

解决方法:修改/themes/matery/source/js中的matery.js文件

第103行:


$('#articleContent, #myGallery').lightGallery({
    selector: '.img-item',
    // 启用字幕
    subHtmlSelectorRelative: true,
    showThumbByDefault: false   //这句加上
});

后面加上:


$(document).find('img[data-original]').each(function(){
    $(this).parent().attr("href", $(this).attr("data-original"));
});

再装个插件,https://github.com/Troy-Yang/hexo-lazyload-image
在博客根目录配置.yml文件加入对应字段,如下:


# lazyload configuration  2019.08.23
lazyload:
  enable: true 
  onlypost: false
  loadingImg:     # eg ./images/loading.gif

好了,这样实现了博客网站的图片懒加载。

4.2 Gulp实现代码压缩

Gulp实现代码压缩,以提升网页加载速度。

1 首先我们需要安装Gulp插件和5个功能模块,依次运行下面的两条命令。


npm install gulp -g  #安装gulp
# 安装功能模块
npm install gulp-htmlclean gulp-htmlmin gulp-minify-css gulp-uglify gulp-imagemin --save
# 额外的功能模块
npm install gulp-debug gulp-clean-css gulp-changed gulp-if gulp-plumber gulp-babel babel-preset-es2015 del --save

2 接下来在博客的根目录下新建gulpfile.js文件,并复制下面的内容到文件中。


var gulp = require("gulp");
var debug = require("gulp-debug");
var cleancss = require("gulp-clean-css"); //css压缩组件
var uglify = require("gulp-uglify"); //js压缩组件
var htmlmin = require("gulp-htmlmin"); //html压缩组件
var htmlclean = require("gulp-htmlclean"); //html清理组件
var imagemin = require("gulp-imagemin"); //图片压缩组件
var changed = require("gulp-changed"); //文件更改校验组件
var gulpif = require("gulp-if"); //任务 帮助调用组件
var plumber = require("gulp-plumber"); //容错组件(发生错误不跳出任务,并报出错误内容)
var isScriptAll = true; //是否处理所有文件,(true|处理所有文件)(false|只处理有更改的文件)
var isDebug = true; //是否调试显示 编译通过的文件
var gulpBabel = require("gulp-babel");
var es2015Preset = require("babel-preset-es2015");
var del = require("del");
var Hexo = require("hexo");
var hexo = new Hexo(process.cwd(), {}); // 初始化一个hexo对象

// 清除public文件夹
gulp.task("clean", function() {
  return del(["public/**/*"]);
});

// 下面几个跟hexo有关的操作,主要通过hexo.call()去执行,注意return
// 创建静态页面 (等同 hexo generate)
gulp.task("generate", function() {
  return hexo.init().then(function() {
    return hexo
      .call("generate", {
        watch: false
      })
      .then(function() {
        return hexo.exit();
      })
      .catch(function(err) {
        return hexo.exit(err);
      });
  });
});

// 启动Hexo服务器
gulp.task("server", function() {
  return hexo
    .init()
    .then(function() {
      return hexo.call("server", {});
    })
    .catch(function(err) {
      console.log(err);
    });
});

// 部署到服务器
gulp.task("deploy", function() {
  return hexo.init().then(function() {
    return hexo
      .call("deploy", {
        watch: false
      })
      .then(function() {
        return hexo.exit();
      })
      .catch(function(err) {
        return hexo.exit(err);
      });
  });
});

// 压缩public目录下的js文件
gulp.task("compressJs", function() {
  return gulp
    .src(["./public/**/*.js", "!./public/libs/**"]) //排除的js
    .pipe(gulpif(!isScriptAll, changed("./public")))
    .pipe(gulpif(isDebug, debug({ title: "Compress JS:" })))
    .pipe(plumber())
    .pipe(
      gulpBabel({
        presets: [es2015Preset] // es5检查机制
      })
    )
    .pipe(uglify()) //调用压缩组件方法uglify(),对合并的文件进行压缩
    .pipe(gulp.dest("./public")); //输出到目标目录
});

// 压缩public目录下的css文件
gulp.task("compressCss", function() {
  var option = {
    rebase: false,
    //advanced: true,               //类型:Boolean 默认:true [是否开启高级优化(合并选择器等)]
    compatibility: "ie7" //保留ie7及以下兼容写法 类型:String 默认:''or'*' [启用兼容模式; 'ie7':IE7兼容模式,'ie8':IE8兼容模式,'*':IE9+兼容模式]
    //keepBreaks: true,             //类型:Boolean 默认:false [是否保留换行]
    //keepSpecialComments: '*'      //保留所有特殊前缀 当你用autoprefixer生成的浏览器前缀,如果不加这个参数,有可能将会删除你的部分前缀
  };
  return gulp
    .src(["./public/**/*.css", "!./public/**/*.min.css"]) //排除的css
    .pipe(gulpif(!isScriptAll, changed("./public")))
    .pipe(gulpif(isDebug, debug({ title: "Compress CSS:" })))
    .pipe(plumber())
    .pipe(cleancss(option))
    .pipe(gulp.dest("./public"));
});

// 压缩public目录下的html文件
gulp.task("compressHtml", function() {
  var cleanOptions = {
    protect: /<\!--%fooTemplate\b.*?%-->/g, //忽略处理
    unprotect: /<script [^>]*\btype="text\/x-handlebars-template"[\s\S]+?<\/script>/gi //特殊处理
  };
  var minOption = {
    collapseWhitespace: true, //压缩HTML
    collapseBooleanAttributes: true, //省略布尔属性的值  <input checked="true"/> ==> <input />
    removeEmptyAttributes: true, //删除所有空格作属性值    <input id="" /> ==> <input />
    removeScriptTypeAttributes: true, //删除<script>的type="text/javascript"
    removeStyleLinkTypeAttributes: true, //删除<style>和<link>的type="text/css"
    removeComments: true, //清除HTML注释
    minifyJS: true, //压缩页面JS
    minifyCSS: true, //压缩页面CSS
    minifyURLs: true //替换页面URL
  };
  return gulp
    .src("./public/**/*.html")
    .pipe(gulpif(isDebug, debug({ title: "Compress HTML:" })))
    .pipe(plumber())
    .pipe(htmlclean(cleanOptions))
    .pipe(htmlmin(minOption))
    .pipe(gulp.dest("./public"));
});

// 压缩 public/uploads 目录内图片
gulp.task("compressImage", function() {
  var option = {
    optimizationLevel: 5, //类型:Number  默认:3  取值范围:0-7(优化等级)
    progressive: true, //类型:Boolean 默认:false 无损压缩jpg图片
    interlaced: false, //类型:Boolean 默认:false 隔行扫描gif进行渲染
    multipass: false //类型:Boolean 默认:false 多次优化svg直到完全优化
  };
  return gulp
    .src("./public/medias/**/*.*")
    .pipe(gulpif(!isScriptAll, changed("./public/medias")))
    .pipe(gulpif(isDebug, debug({ title: "Compress Images:" })))
    .pipe(plumber())
    .pipe(imagemin(option))
    .pipe(gulp.dest("./public"));
});
// 执行顺序: 清除public目录 -> 产生原始博客内容 -> 执行压缩混淆 -> 部署到服务器
gulp.task(
  "build",
  gulp.series(
    "clean",
    "generate",
    "compressHtml",
    "compressCss",
    "compressJs",
    "compressImage",
    gulp.parallel("deploy")
  )
);

// 默认任务
gulp.task(
  "default",
  gulp.series(
    "clean",
    "generate",
    gulp.parallel("compressHtml", "compressCss", "compressImage", "compressJs")
  )
);
//Gulp4最大的一个改变就是gulp.task函数现在只支持两个参数,分别是任务名和运行任务的函数

3 最后 hexo clean && hexo g && gulp && hexo d 就可以了。

注意,很可能你会运行到第三步,也就是运行gulp压缩命令时会报错。

那是因为gulp安装的本地版本和hexo自带的版本不对应导致,第三步gulp压缩可以用下面命令强制使用本地版本:


node ./node_modules/gulp/bin/gulp.js

4.3 Github & Coding Pages 双部署

Github & Coding Pages 双部署,对国内,国外用户进行分流访问,以提升网站的访问速度。

Github Pages 的部署前面已经说了,这里就讲一讲 Coding Pages 如何部署.其实与 Github Pages 也类似,先到coding官网注册,创建一个与用户名同名的仓库,添加仓库地址到配置文件中,在根目录_config.yml对应地方添加如下:


# Deployment
## Docs: https://hexo.io/docs/deployment.html
deploy:
- type: git                                                      # 设置发布类型,如git     
  repo: 
    github: git@github.com:OUYANGSIHAI/OUYANGSIHAI.github.io.git   # 设置repository对应的链接
    coding: git@e.coding.net:ouyangsihai/sihaiblog.git
  branch: master                                                 # 设置提交到的分支
  message: Site updated at {{ now("YYYY-MM-DD HH:mm:ss") }}      # 设置我们提交的信息
- type: baidu_url_submitter

把本地生成 SSH 公匙添加到 Coding 这一步看我前面的教程,原理类似.

然后 hexo clean && hexo g && hexo d 部署上去就是了.

当然,部署上去后,你需要开启 page 服务.

你可以在 pages 设置里面自定义域名,区域名解析控制台,添加两条 CNAME 记录,将域名指向 RepoName.coding.me就可以的,申请 ssl 证书,强制开启https

可能遇到的问题:

  • coding pages 申请ssl 证书总是提示:错误!

这里提一句,如果你是github pages 和 coding pages双部署,用同一个域名的话,可以将xxx.github.io 解析成 境外, xxx.coding.me 解析成 默认,这个时候如果你之前就申请过 ssl 证书的话,再在 coding 里面申请 ssl证书会一直提示 失败,解决办法:

先去域名解析控制台,将境外解析的两条 CNAME 记录 暂停,过个五六分钟,回到 coding 点击申请 ssl,很快就会提示,申请成功!

刚好我过程中遇到了这个问题,所以把它记下来,方便后面的小伙伴看到.

5 代码高亮

由于 Hexo 自带的代码高亮主题显示不好看,所以主题中使用到了 hexo-prism-plugin 的 Hexo 插件来做代码高亮,安装命令如下:


npm i -S hexo-prism-plugin

然后,修改 Hexo 根目录下 _config.yml 文件中 highlight.enable 的值为 false,并新增 prism 插件相关的配置,主要配置如下:


highlight:
  enable: false

prism_plugin:
  mode: 'preprocess'    # realtime/preprocess
  theme: 'tomorrow'
  line_number: false    # default false
  custom_css:

做了除此设置之外,还有一个很大的问题,就是写代码块的时候,并不会自动的识别是哪种语言,还需要在代码前面标记是哪种语言,所以,非常的麻烦,未来解决这个问题还问了一个同用这个主题的网友,非常感谢他的热心帮助。

解决方法

在这个路径在找到这个文件


/**
 * Code transform for prism plugin.
 * @param {Object} data
 * @return {Object}
 */
function PrismPlugin(data) {
  // Patch for caption support
  if (captionRegex.test(data.content)) {
    // Attempt to parse the code
    data.content = data.content.replace(captionRegex, (origin, lang, caption, code) => {
      if (!lang || !caption || !code) return origin;
      return `<figcaption>${caption}</figcaption><pre><code class="${lang}">${code}</code></pre>`;
    })
  }
  //============= 
   var myflag=true
//===================
  data.content = data.content.replace(regex, (origin, lang, code) => {
    const lineNumbers = line_number ? 'line-numbers' : '';
    const startTag = `<pre class="${lineNumbers} language-${lang}"><code class="language-${lang}">`;
    const endTag = `</code></pre>`;

    code = unescape(code); 
    let parsedCode = '';

    if (Prism.languages[lang]) {
      parsedCode = Prism.highlight(code, Prism.languages[lang]);
    } else {
      parsedCode = code;
    }
    if (line_number) {
      const match = parsedCode.match(/\n(?!$)/g);
      const linesNum = match ? match.length + 1 : 1;
      let lines = new Array(linesNum + 1);
      lines = lines.join('<span></span>');
      const startLine = '<span aria-hidden="true" class="line-numbers-rows">';
      const endLine = '</span>';
      parsedCode += startLine + lines + endLine;
    }
    myflag=false
    return startTag + parsedCode + endTag;
  });

//================================================================================================
   if(myflag){
            data.content=data.content.replace(/<code>/igm,'<code class="c">\n')  //c 改成 java 即可
            data.content = data.content.replace(regex, (origin, lang, code) => {
            const lineNumbers = line_number ? 'line-numbers' : '';
            const startTag = `<pre class="${lineNumbers} language-${lang}"><code class="language-${lang}">`;
            const endTag = `</code></pre>`;
            code = unescape(code); 
            let parsedCode = '';

            if (Prism.languages[lang]) {
              parsedCode = Prism.highlight(code, Prism.languages[lang]);
            } else {
              parsedCode = code;
            }
            if (line_number) {
              const match = parsedCode.match(/\n(?!$)/g);
              const linesNum = match ? match.length + 1 : 1;
              let lines = new Array(linesNum + 1);
              lines = lines.join('<span></span>');
              const startLine = '<span aria-hidden="true" class="line-numbers-rows">';
              const endLine = '</span>';
              parsedCode += startLine + lines + endLine;
            }
            return startTag + parsedCode + endTag;
          });
   }
//================================================================================================

  return data;
}

/**
 * Copy asset to hexo public folder.
 */
function copyAssets() {
  const assets = [{
    path: `css/${prismThemeFileName}`,
    data: () => fs.createReadStream(prismThemeFilePath)
  }];

  // If line_number is enabled in plugin config add the corresponding stylesheet
  if (line_number) {
    assets.push({
      path: 'css/prism-line-numbers.css',
      data: () => fs.createReadStream(path.join(prismLineNumbersPluginDir, 'prism-line-numbers.css'))
    });
  }

  // If prism plugin config mode is realtime include prism.js and line-numbers.js
  if (mode === 'realtime') {
    assets.push({
      path: 'js/prism.js',
      data: () => fs.createReadStream(prismMainFile)
    });
    if (line_number) {
      assets.push({
        path: 'js/prism-line-numbers.min.js',
        data: () => fs.createReadStream(path.join(prismLineNumbersPluginDir, 'prism-line-numbers.min.js'))
      });
    }
  }

  return assets;
}

/**
 * Injects code to html for importing assets.
 * @param {String} code
 * @param {Object} data
 */

如果你不是Java,想改成其他语言,修改上面代码的这部分即可。

给代码块开启行号

我们在配置文件.yml中找到prism_plugin配置项line_number: false(# default false)改为true,开启行号,但是在我们这个matery主题中中是无效的,有bug需要改一下matery.css样式参数,在第95行位置将:


pre {
    padding: 1.5rem !important;
    margin: 1rem 0 !important;
    background: #272822;
    overflow: auto;
    border-radius: 0.35rem;
    tab-size: 4;
}

改为:


pre {
    padding: 1.5rem 1.5rem 1.5rem 3.3rem !important;
    margin: 1rem 0 !important;
    background: #272822;
    overflow: auto;
    border-radius: 0.35rem;
    tab-size: 4;
}

注释掉紧接着的code代码块里面的font-size项,如下:


code {
    padding: 1px 5px;
    font-family: Inconsolata, Monaco, Consolas, 'Courier New', Courier, monospace;
    /*font-size: 0.91rem;*/
    color: #e96900;
    background-color: #f8f8f8;
    border-radius: 2px;
}

好了这下可以显示行号了。

6 修改页面底部

找到这个文件

修改成以下内容


本站由&copy;<a href="https://blog.ouyangsihai.cn" target="_blank"> 欧阳思海 </a>维护.

7 图片压缩

参考文章:https://www.zrahh.com/archives/269.html

8 更多详情查看


 上一篇
面试官问你B树和B+树,就把这篇文章丢给他 面试官问你B树和B+树,就把这篇文章丢给他
原文链接:面试官问你B树和B+树,就把这篇文章丢给他 1 B树在介绍B+树之前, 先简单的介绍一下B树,这两种数据结构既有相似之处,也有他们的区别,最后,我们也会对比一下这两种数据结构的区别。 1.1 B树概念B树也称B-树,它是一颗多
下一篇 
InnoDB与MyISAM等存储引擎对比 InnoDB与MyISAM等存储引擎对比
InnoDB存储引擎介绍InnoDB引擎是Mysql的默认的存储引擎,他有很多自己的特性,下面一一列举。 支持事务,InnoDB存储引擎主要就是为了在线事务处理(OLTP)的应用而设计的。 行锁设计,支持外键,非锁定读。 支持多版本的并发
  目录