0x00 前言

这几天闲来无事,学习了下Hexo的博客速度优化,发现有好多方法。CDN加速、Coding部署、gulp压缩、hexo-neat、InstantClick 黑科技等等。这里记录下我使用gulp压缩进行Hexo速度优化和在此过程中遇到的问题,以及使用hexo-neat对Hexo进行速度优化。
这两种方法都是静态文件压缩,静态文件包括: html,css,js,images

0x01 优化之前

在博客速度优化之前,先来说说在浏览器输入url到页面打开,都做了些什么?,因为没怎么了解过,所以参考了很多博客,具体参考的博客链接在文末。
当在浏览器地址栏输入网址,如:www.baidu.com后浏览器是怎么把最终的页面呈现出来的呢?这个过程可以大致分为两个部分:网络通信和页面渲染。

1、大致流程

URL 解析->DNS 查询->TCP 连接->处理请求->接受响应->渲染页面
简单的来说,就是:

  • 浏览器里输入网址
  • 浏览器查找域名对应的IP地址
    DNS具体的查找过程,包括:浏览器缓存->系统缓存->路由器缓存->ISP DNS缓存->根域名服务器
  • 浏览器向web服务器发送一个HTTP请求
  • 服务器的永久重定向响应(从http://baidu.comhttp://www.baidu.com

为什么要重定向?其中一个原因跟搜索引擎排名有关。如果一个页面有两个地址,就像http://baidu.com/http://www.baidu.com/,搜索引擎会认为它们是两个网站,结果造成每一个的搜索链接都减少从而降低排名。所以要把带www的和不带www的地址归到同一个网站排名下。还有一个原因是用不同的地址会造成缓存友好性变差

  • 浏览器跟踪重定向地址,发起GET请求
  • 服务器”处理”请求,向浏览器发回一个HTML响应
  • 浏览器解析显示HTML
  • 浏览器发送请求获取嵌入在 HTML 中的资源(如图片、音频、视频、CSS、JS等等)
  • 浏览器发送异步请求(ajax请求等)

2、简单分析

从上面的过程可以看出,大部分过程我们无法控制,所以只能从浏览器端入手来找一些可以做的事情。
少发送请求

把要加载的js文件(css文件同理)合并成一个(尽量少)文件,则可以向服务器少发送请求,从而减少等待时间。

压缩文件

使用压缩之后的js、css、img文件,同样可以减少请求时间。

Css Sprite

这是css的一项技术,将图片尽可能多的合并成一个图片文件,第一次使用的时候加载这张图片,然后浏览器会缓存下来,其他地方再使用的时候就不需要重新请求了。

js/css位置

css引用建议放在head标签里面;js脚本建议放到body内容的最后,原因:等待js加载或者脚本有错误的时候不会影响html页面的展示。

那么怎么提高hexo这个静态博客的页面加载速度呢?可以从以下的几个方面去入手:

  1. 将js文件尽可能放到body的闭合标签之前,因为在加载或者引入js文件时是阻塞式的,如果在页面的最开始就引入这些js文件,而这些文件又比较大,会造成页面在渲染时长时间处于白屏状态。
  2. 尽量避免去引用访问速度非常低下的cdn或者图片,可改用访问速度更快的cdn,或将难以迅速加载的图片保存到自己的站点目录下,以免在加载图片时耗费大量时间,最后还加载失败。
  3. 对页面的静态资源进行压缩,包括css、js和html等文件。

我们自己添加的css和js文件为了可读性,往往会有很多换行和空格,这些对于浏览器来说并没什么用,甚至还会降低渲染页面的速度。
至于html文件,由于Markdown转成html的bug,会导致页面存在大量的空白,查看下页面的源代码,会发现有大量的空白符,这也会造成页面渲染的性能问题。

0x02 gulp4压缩静态文件

1、安装gulp

在站点根目录下安装
1.安装gulp工具

npm install gulp -g

2.安装gulp插件

npm install gulp-minify-html gulp-minify-css gulp-uglify gulp-imagemin --save

# 解决【Gulp打包问题】 GulpUglifyError: unable to minify JavaScript
# 解决 gulp-uglify 压缩JavaScript 不兼容 es5 语法的问题
#npm install babel-core@6.26.3 --save
#npm install gulp-babel@7.0.1 --save
#npm install babel-preset-es2015@6.24.1 --save

# gulp-babel 取消严格模式方法("use strict")
#npm install gulp-remove-use-strict --save

#问题:如果安装gulp-imagemin错误请执行以下语句
#sudo npm i gulp-imagemin --unsafe-perms

2、建立gulpfile.js文件

在站点根目录下创建gulpfile.js

var gulp = require('gulp');

//Plugins模块获取
var minifycss = require('gulp-minify-css');
var uglify = require('gulp-uglify');
var minifyhtml = require('gulp-minify-html');
// 压缩 public 目录 css文件
gulp.task('minify-css', function () {
    return gulp.src('./public/**/*.css')
        .pipe(minifycss())
        .pipe(gulp.dest('./public'));
});

// 压缩 public 目录 html文件
gulp.task('minify-html', function () {
    return gulp.src('./public/**/*.html')
        .pipe(minifyhtml())
        .pipe(gulp.dest('./public'))
});
// 压缩 public/js 目录 js文件,忽略/public/lib/blog-encrypt.js
gulp.task('minify-js', function () {
    //纠错前:return gulp.src('./public/**/*.js')
    return gulp.src(['./public/**/*.js', '!./public/lib/blog-encrypt.js'])
        .pipe(uglify())
        .pipe(gulp.dest('./public'))
});
// 压缩图片
//gulp.task('minify-images', function() {
//    return gulp.src('./public/images/**/*.*')
//        .pipe(imagemin(
//        [imagemin.gifsicle({'optimizationLevel': 3}),
//        imagemin.jpegtran({'progressive': true}),
//        imagemin.optipng({'optimizationLevel': 7}),
//        imagemin.svgo()],
//        {'verbose': true}))
//        .pipe(gulp.dest('./public/images'))
//});
//因为我图片用的第三方图床存放的,所以就没压缩图片。(并且最后测试压缩图片时,发现有点权限问题,
//整了两个多小时没整好!@^@)

// 分别执行css、heml、js的压缩任务
gulp.task('default', gulp.parallel('minify-css', 'minify-html', 'minify-js'));


1.修改上面的各个目录为你的真实目录, ** 代表0或多个子目录
2.在默认任务中,gulp.parallel()是gulp4中的新写法:
gulp.series 用于串行(顺序)执行
gulp.parallel 用于并行执行
3.部署执行

hexo clean && hexo g && gulp && hexo d

感觉命令有点多,也可以直接在package.json文件里添加

"scripts": {
    "hexo": "hexo clean && hexo g && gulp && hexo d"
},

然后在博客根目录执行npm run hexo即可
Hexo速度优化及遇到的问题(gulp4、hexo-neat)_加载

3、遇到的问题

在使用gup4压缩静态文件时遇到一些问题,总结一下:
1.gulp4的默认任务执行问题

//4.0以前的写法 
//gulp.task('default', ['minify-html', 'minify-css', 'minify-js']);
//4.0以后的写法
// 执行 gulp 命令时执行的任务
gulp.task('default', gulp.parallel('minify-css', 'minify-html', 'minify-js'));

2.TypeError: dest.on is not a function
先检查gulpfile.js若没有问题,删掉node_modules,重装一遍依赖npm install

3.GulpUglifyError: unable to minify JavaScript(Gulp打包问题)
错误原因有很多,如:有的文件不能打包、javascirpt语法问题等等。我遇到的问题是有的文件不能打包。
(1)解决方法1:
检查哪一个文件中的哪一行有问题,安装 gulp-util 模块 用于打印日志

npm install --save-dev gulp-util

gulpfile.js里添加:

gulp.task('script', function() {
    gulp.src(['public/**/*.js', 'public/lib/**/*.js'])
        .pipe(uglify())
        .on('error', function(err) {
            gutil.log(gutil.colors.red('[Error]'), err.toString());
        })
        .pipe('dist/js')
})

执行gulp script,这样就可以精准的逐个排查文件了。这里我排查到:
Hexo速度优化及遇到的问题(gulp4、hexo-neat)_加载_02
发现blog-encrypt.js有问题,在gulpfile.js忽略blog-encrypt.js即可,即

// 压缩 public/js 目录 js文件
gulp.task('minify-js', function () {
    //纠错前:return gulp.src('./public/**/*.js')
    return gulp.src(['./public/**/*.js', '!./public/lib/blog-encrypt.js'])
        .pipe(uglify())
        .pipe(gulp.dest('./public'))
});

(2)解决方法2:
继续方法1 安装 babel 模块
gulp-babelbabel-preset-es2015

npm install --save-dev gulp-babel babel-preset-es2015
gulp.task('script', function() {
    gulp.src(['public/**/*.js', 'public/lib/**/*.js'])
        .pipe(babel({
            presets: ['es2015'] // es5检查机制
        }))
        .pipe(uglify())
        .on('error', function(err) {
            gutil.log(gutil.colors.red('[Error]'), err.toString());
        })
        .pipe('dist/js')
})

这样就解决 gulp-uglify 压缩JavaScript 不兼容 es5 语法的问题了。
4.The following tasks did not complete: html Did you forget to signal async completion?
运行gulp,出现下面报错:

 The following tasks did not complete: html 
 Did you forget to signal async completion?

解决办法:在注册的任务函数里使用 async 和 await。

gulp.task("html",async()=>{
	await gulp.src(folder.src + "html/*")
	.pipe(htmlClean())
	.pipe(gulp.dest(folder.build + "html"))
})

gulp4安装使用过程中,我暂时就遇到上面这几种错误。除了上述错误,还有很多可能会出错的地方,这里有个博客记录了一些:gulp 错误集锦

0x03 hexo-neat压缩静态文件

hexo-neat是由rozbo大佬开发的压缩插件,配置简单,无需额外命令,只要使用原本的调试三连或者部署三连就可以自动完成静态资源的压缩

1、安装hexo-neat

在站点根目录下

npm install hexo-neat --save

2、添加相关配置

在站点配置文件_config.yml添加相关配置,直接添加到站点配置文件_config.yml的末尾就可以。可以安装自己的需求去自定义配置,不过有些注意事项

# hexo-neat
# 博文压缩
neat_enable: true
# 压缩html
neat_html:
  enable: true
  exclude:
# 压缩css  
neat_css:
  enable: true
  exclude:
    - '**/*.min.css'
# 压缩js
neat_js:
  enable: true
  mangle: true
  output:
  compress:
  exclude:
    - '**/*.min.js'
    - '**/jquery.fancybox.pack.js'
    - '**/index.js'  

3、hexo-neat插件注意事项

在使用hexo-neat插件时,可以在命令窗口中看到各个文件的压缩率,于是可以通过跳过一些文件让效率更高。
1.跳过压缩文件的正确配置方式
如果按照官方插件的文档说明来配置exclude,会发现完全不起作用。这是因为配置的文件路径不对,压缩时找不到你配置的文件,自然也就无法跳过了。于是需要给这些文件指定正确的路径,万能的配置方式如下:

neat_css:
  enable: true
  exclude:
    - '**/*.min.css'

2.压缩html时不要跳过.md文件和.swig文件
.md文件就是markdown文件,如果跳过压缩.md文件,而又刚好在文章中使用到了tab标签,那么当hexo在生成静态页面时就会发生解析错误。这会导致使用到了tab标签的页面生成失败而无法访问。

.swig文件是模板引擎文件,也就是hexo可以通过这些文件来生成对应的页面。如果跳过这些文件,所有页面完全没有起到压缩的效果,页面源代码里依然存在着一大堆空白。
Hexo速度优化及遇到的问题(gulp4、hexo-neat)_加载_03

0x04 后记

对Hexo进行简单的速度优化过程中,我主要学习了从输入url到页面打开的过程、使用gup4和hexo-neat进行速度优化,最好的速度优化方式应该是使用CDN加速,在下太穷,所以没使用。同时在使用gup4速度优化过程中也培养了自己的纠错改错的能力,继续加油!!!

参考博客:
在浏览器输入 URL 回车之后发生了什么(超详细版)
从输入URL到页面加载的全过程
从输入URL到页面加载的过程?如何由一道题完善自己的前端知识体系!
从输入URL到浏览器显示页面发生了什么
网络通信总结(TCP/IP协议、HTTP协议等)

Hexo折腾记——性能优化篇
加速 Hexo 博客
基于Hexo搭建个人博客优化(五)—压缩篇(gulp4.0压缩静态资源)
hexo博客进阶-性能优化
hexo优化之——使用gulp压缩资源