起因

刚搭好博客后觉得还不错,很好,很精致,但久了之后就发现其中还存在的问题(访问加载速度太慢了),而这还是通过别人的提醒后才真正着手去处理的。

reason.png

一般人的做法都是先通过搜索引擎看看有没有人解决过类似的问题,但我经过一番折腾后发现,这些都比较旧,而且只是适应他们自己的网站优化的,所以通过各种比较,悉知共性后,自己查找资料文档来逐步解决。

问题分析

先在Firefox中输入我的博客网址,然后点击分析(一个时钟图标)按钮即可。

我这里使用了一个很好用的工具
Firefox性能分析工具

打开网络监视器有几种不同的方法:

  • 按 Ctrl+ Shift+ E(Mac上为Command+ Option+ E)。
  • 从Web Developer菜单中选择“Network”(这是OS X和Linux上Tools菜单的子菜单)。
  • 按F12后点击上面的“网络”菜单

network_analysis_tool.png

刚开始我是用chrome的Network工具,结果(极度失望):

so_slow.png

当时没认真截图,但这张图也充分反映出了核心的问题:图片分辨率太大,就17.jpg这张图就耗费了1分钟,加载时间主要花费在图片上了。

解决办法:

  1. 少发送请求
    把要加载的js文件(css文件同理)合并成一个(尽量少)文件,则可以向服务器少发送请求,从而减少等待时间。
  1. 压缩文件
    使用压缩之后的js、css、img文件,同样可以减少请求时间。
  1. Css Sprite
    这是css的一项技术,将图片尽可能多的合并成一个图片文件(例如:如果用到很多图标的话),第一次使用的时候加载这张图片,然后浏览器会缓存下来,其他地方再使用的时候就不需要重新请求了。
  1. js/css位置
    css引用建议放在head标签里面;js脚本建议放到body内容的最后,原因:等待js加载或者脚本有错误的时候不会影响html页面的展示。

GULP自动化构建工具


简介

  • gulp是前端开发过程中对代码进行构建的工具,是自动化项目的构建利器;她不仅能对网站资源进行优化,而且在开发过程中很多重复的任务能够使用正确的工具自动完成;使用她,我们不仅可以很愉快的编写代码,而且大大提高我们的工作效率。
  • gulp是基于Nodejs的自动任务运行器, 她能自动化地完成 javascript/coffee/sass/less/html/image/css 等文件的的测试、检查、合并、压缩、格式化、浏览器自动刷新、部署文件生成,并监听文件在改动后重复指定的这些步骤。在实现上,她借鉴了Unix操作系统的管道(pipe)思想,前一级的输出,直接变成后一级的输入,使得在操作上非常简单。通过本文,我们将学习如何使用Gulp来改变开发流程,从而使开发更加快速高效。

  • gulp 和 grunt 非常类似,但相比于 grunt 的频繁 IO 操作,gulp 的流操作,能更快地更便捷地完成构建工作。

开始使用

这个使用需要用到两个文件:gulpfile.js和package.json文件,它们都放在项目的根目录下。

gulpfile.js:

var gulp = require('gulp');
var cleanCSS = require('gulp-clean-css');
var uglify = require('gulp-uglify');
var pipeline = require('readable-stream').pipeline;
var htmlmin = require('gulp-htmlmin');
var imagemin = require('gulp-imagemin');

// 压缩 /public/css 目录中的css文件
gulp.task('compress-css', () => {
  return gulp.src('./public/css/*.css')
    .pipe(cleanCSS({compatibility: 'ie8'}))
    .pipe(gulp.dest('./public/css'));
});

// 压缩 /public/2018 目录中的html文件
gulp.task('compress-html2018', () => {
  return gulp.src('./public/2018/**/*.html')
    .pipe(htmlmin({ collapseWhitespace: true }))
    .pipe(gulp.dest('./public/2018'));
});

// 压缩 /public/2019 目录中的html文件
gulp.task('compress-html2019', () => {
  return gulp.src('./public/2019/**/*.html')
    .pipe(htmlmin({ collapseWhitespace: true }))
    .pipe(gulp.dest('./public/2019'));
});

// 压缩 /public/js 目录中的js文件
gulp.task('compress-js', function () {
  return pipeline(
        gulp.src(['./public/js/*.js', '!./public/js/search.js']),
        uglify(),
        gulp.dest('./public/js')
  );
});

// 压缩 /public/img 目录中的图片
gulp.task('compress-images', function() {
    var stream = gulp.src('./public/img/**/*.*')
        .pipe(imagemin([
          imagemin.gifsicle({interlaced: false}),
          imagemin.jpegtran({progressive: true}),
          imagemin.optipng({optimizationLevel: 6}),
          imagemin.svgo({
              plugins: [
                  {removeViewBox: true},
                  {cleanupIDs: false}
              ]
          })
      ]))
        .pipe(gulp.dest('./public/img'));
        return stream;
});

// 默认任务 gulp 4.0 适用的方式
gulp.task('default', gulp.series(gulp.parallel('compress-js', 'compress-html2018', 'compress-html2019'
 //build the website
)));

以上文件中的用法,需根据自己的项目来配置,底部的参考文献中有详细的解释,因此不再赘述。

温馨提示:**为匹配当前所有目录。

异步执行task

有时候执行完会遇到Did you forget to ….等字样的信息,是因为你没有使用异步的方式执行task中的function。这里给出官方提供的三种方式:

  1. 接受一个 callback

// 在 shell 中执行一个命令
var exec = require('child_process').exec;
gulp.task('jekyll', function(cb) {
  // 编译 Jekyll
  exec('jekyll build', function(err) {
    if (err) return cb(err); // 返回 error
    cb(); // 完成 task
  });
});
  1. 返回一个 stream

gulp.task('somename', function() {
  var stream = gulp.src('client/**/*.js')
    .pipe(minify())
    .pipe(gulp.dest('build'));
  return stream;
});
  1. 返回一个 promise

var Q = require('q');

gulp.task('somename', function() {
  var deferred = Q.defer();

  // 执行异步的操作
  setTimeout(function() {
    deferred.resolve();
  }, 1);

  return deferred.promise;
});

package.json:

{
  "name": "hexo-site",
  "version": "0.0.0",
  "private": true,
  "hexo": {
    "version": "3.8.0"
  },
  "dependencies": {
    "braces": "^2.3.1",
    "clean-css": "^4.1.11",
    "gulp-minify-css": "^1.2.4",
    "hexo": "^3.7.0",
    "hexo-deployer-git": "^1.0.0",
    "hexo-generator-archive": "^0.1.5",
    "hexo-generator-category": "^0.1.3",
    "hexo-generator-feed": "^1.2.2",
    "hexo-generator-index": "^0.2.1",
    "hexo-generator-search-zip": "0.0.1",
    "hexo-generator-tag": "^0.2.0",
    "hexo-prism-plugin": "^2.3.0",
    "hexo-renderer-ejs": "^0.3.1",
    "hexo-renderer-marked": "^0.3.2",
    "hexo-renderer-stylus": "^0.3.3",
    "hexo-server": "^0.3.1",
    "marked": "^0.6.2"
  },
  "devDependencies": {
    "gulp": "^4.0.1",
    "gulp-clean-css": "^4.2.0",
    "gulp-htmlclean": "^2.7.22",
    "gulp-htmlmin": "^5.0.1",
    "gulp-imagemin": "^5.0.3",
    "gulp-rename": "^1.4.0",
    "gulp-uglify": "^3.0.2",
    "pump": "^3.0.0",
    "readable-stream": "^3.3.0",
    "uglify-js": "^3.5.9"
  }
}

这个文件中主要得区分dependencies和devDependencies,前者为全局依赖,后者为此项目开发下的依赖。安装时的区别为:

  1. 全局安装 gulp
    $ npm install –global gulp

  2. 作为项目的开发依赖(devDependencies)安装:
    $ npm install –save-dev gulp

在Git Bash下进入博客根目录下,然后键入上述命令之后还得安装如下插件:(注意最好用–save-dev)

    gulp-clean-css
    gulp-htmlclean
    gulp-htmlmin
    gulp-imagemin
    gulp-rename
    gulp-uglify
    readable-stream

之后只要按顺序输入以下命令即可:

    hexo clean
    hexo g
    gulp
    hexo d

其中的gulp执行结果显示:

$ gulp
[11:51:49] Using gulpfile F:\blog\blog\gulpfile.js
[11:51:49] Starting 'default'...
[11:51:49] Starting 'compress-images'...
[11:51:49] Starting 'compress-js'...
[11:51:49] Starting 'compress-html2018'...
[11:51:49] Starting 'compress-html2019'...
[11:51:52] Finished 'compress-html2018' after 2.69 s
[11:51:53] Finished 'compress-js' after 3.58 s
[11:51:53] Finished 'compress-html2019' after 3.63 s
[11:53:03] gulp-imagemin: Minified 81 images (saved 2.87 MB - 13.1%)
[11:53:03] Finished 'compress-images' after 1.22 min
[11:53:03] Finished 'default' after 1.22 min

压缩后的结果:

img原来大小:121MB 压缩后大小:113MB(其中有很多没用到的图片,后面已移除)
js原来大小:468KB 压缩后大小:222KB
css原来大小:46.3KB 压缩后大小:67.5KB(这个压缩后反而更大。。暂时搞不清楚,所以就不压缩了)

analyse_first.png
analyse_first_min.png

重新访问后速度没提升多少,图片还是太大,而且我还发现其中还存在一个问题,就是有部分访问响应结果为404之类的错误,严重拖慢了加载的速度,然后我根据问题的来源,(就是一些时间脚本,还有leancloud评论功能加载错误导致的)解决后,我意外获得了一个jpg图片压缩工具。

jpg_tool.png

经本人测试,效果与原图保持相同的最低图片压缩比就30了,低于30图片会失真,工具应该网上都有。

21张jpg,总共13.9MB,压缩后为4MB

再次测试结果:

为了确保由于网速问题,先检查一下(前几次很可能是网速问题:T):
web_speed.png

然后再次测试:

analyse_second.png
analyse_second_min.png

到这里可以看出,还是图片的问题,我只能说美观得有代价。除非把图片都改成分辨率为800x300的那种(我这些都是1920x990以上的),如今只能将图片大小尽量控制在200KB一下会好一点。以上测试每次都是清除了缓存后再测的,第二次访问加载还是很快的。(尴尬的微笑~)

最终结果:
finish.png

错误解决办法:

如果gulp命令出现err,说是找不到某某模块,则可键入命令npm install来重新构建所需模块,若此命令还出现如下问题:

npm WARN checkPermissions Missing write access to F:\blog\blog\node_modules\

则直接将你的node_modules目录删除,然后重新以管理员身份重新npm install即可。

若安装出现什么npm audit fix等之类的,则可以先键入命令npm audit来进行所有插件的审阅,分析出所需插件的特定版本号,然后根据版本号和所需插件名,在package.json中的dependencies添加即可(^这个符号意思是不小于大版本号)


前面的解决办法只是治标不治本的,要想显著提升访问速度,根源还是在服务器上。我这个服务器是借助于 Github 的,外国的服务器,访问有一定速度限制和固定 ip 段的约束(Google为例吧),一般都很慢。最好的做法是将站点放在国内的云服务器上,然后申请个域名,这个暂时不搞,一没钱二没时间​ emmm~​。

参考文献

  1. gulp详细入门教程
  2. gulp中文网
  3. hexo博客进阶-性能优化