0%

Hexo使用Gulp压缩静态资源

Gulp简介

gulp是一个自动化构建工具,能够强化我们的前端工作流。

gulp is an open-source JavaScript toolkit created by Eric Schoffstall used as a streaming build system (similar to a more package-focussed Make) in front-end web development.

It is a task runner built on Node.js and npm, used for automation of time-consuming and repetitive tasks involved in web development like minification, concatenation, cache busting, unit testing, linting, optimization, etc.

gulp uses a code-over-configuration approach to define its tasks and relies on its small, single-purpose plugins to carry them out. The gulp ecosystem includes more than 3500 such plugins.

更多内容,参考wikipedia-gulp.jsGulp官网Gulp中文网
本文中,会使用gulp来压缩hexo生成的静态资源文件,加快站点的访问速度。

安装配置gulp

1、安装gulp
npm install --global gulp-cli

2、安装gulp模块

1
2
3
4
npm install gulp --save
npm install gulp-htmlclean gulp-htmlmin gulp-clean-css gulp-uglify gulp-imagemin --save
npm install gulp-babel babel-preset-env babel-preset-mobx --save
npm install -D @babel/core @babel/preset-react @babel/preset-env --save

最终生成的package.json为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
{
"name": "hexo-site",
"version": "0.0.0",
"private": true,
"scripts": {
"build": "hexo generate",
"clean": "hexo clean",
"deploy": "hexo deploy",
"server": "hexo server"
},
"hexo": {
"version": "4.2.0"
},
"dependencies": {
"babel-preset-env": "^1.7.0",
"babel-preset-mobx": "^2.0.0",
"gulp": "^4.0.2",
"gulp-babel": "^8.0.0",
"gulp-clean-css": "^4.2.0",
"gulp-htmlclean": "^2.7.22",
"gulp-htmlmin": "^5.0.1",
"gulp-imagemin": "^7.1.0",
"gulp-uglify": "^3.0.2",
"hexo": "^4.0.0",
"hexo-generator-archive": "^1.0.0",
"hexo-generator-baidu-sitemap": "^0.1.6",
"hexo-generator-category": "^1.0.0",
"hexo-generator-feed": "^2.2.0",
"hexo-generator-index": "^1.0.0",
"hexo-generator-searchdb": "^1.2.0",
"hexo-generator-sitemap": "^2.0.0",
"hexo-generator-tag": "^1.0.0",
"hexo-neat": "^1.0.4",
"hexo-renderer-ejs": "^1.0.0",
"hexo-renderer-marked": "^2.0.0",
"hexo-renderer-stylus": "^1.1.0",
"hexo-server": "^1.0.0"
},
"devDependencies": {
"@babel/core": "^7.8.4",
"@babel/preset-env": "^7.8.4",
"@babel/preset-react": "^7.8.3"
}
}

4、在hexo目录创建gulpfile.js,内容为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
let gulp = require('gulp')
let cleanCSS = require('gulp-clean-css')
let htmlmin = require('gulp-htmlmin')
let htmlclean = require('gulp-htmlclean')
let babel = require('gulp-babel') /* 转换为es2015 */
let uglify = require('gulp-uglify')
let imagemin = require('gulp-imagemin')

// 设置根目录
const root = './public'

// 匹配模式, **/*代表匹配所有目录下的所有文件
const pattern = '**/*'

// 压缩html
gulp.task('minify-html', function() {
return gulp
// 匹配所有 .html结尾的文件
.src(`${root}/${pattern}.html`)
.pipe(htmlclean())
.pipe(
htmlmin({
removeComments: true,
minifyJS: true,
minifyCSS: true,
minifyURLs: true
})
)
.pipe(gulp.dest('./public'))
})

// 压缩css
gulp.task('minify-css', function() {
return gulp
// 匹配所有 .css结尾的文件
.src(`${root}/${pattern}.css`)
.pipe(
cleanCSS({
compatibility: 'ie8'
})
)
.pipe(gulp.dest('./public'))
})

// 压缩js
gulp.task('minify-js', function() {
return gulp
// 匹配所有 .js结尾的文件
.src(`${root}/${pattern}.js`)
.pipe(
babel({
presets: ['env']
})
)
.pipe(uglify())
.pipe(gulp.dest('./public'))
})

// 压缩图片
gulp.task('minify-images', function() {
return gulp
// 匹配public/images目录下的所有文件
.src(`${root}/images/${pattern}`)
.pipe(
imagemin(
[
imagemin.gifsicle({ optimizationLevel: 3 }),
imagemin.jpegtran({ progressive: true }),
imagemin.optipng({ optimizationLevel: 7 }),
imagemin.svgo()
],
{ verbose: true }
)
)
.pipe(gulp.dest('./public/images'))
})

gulp.task('default', gulp.series('minify-html', 'minify-css', 'minify-js'))

4、执行压缩
gulp

命令精简

使用了gulp时候,构建发布需要四个命令:

1
2
3
4
hexo clean
hexo g
gulp
hexo d

这四个命令,可以都写在package.json。

1
2
3
4
"scripts": {
"build": "hexo clean && hexo g && gulp",
"deploy": "hexo clean && hexo g && gulp && hexo d"
}

构建只需要执行npm run build,构建发布只需要执行npm run deploy

travis配置

对应的,修改.travis.yml配置为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
sudo: false
language: node_js
node_js:
- 10.16.3
cache: npm
branches:
only:
- master # build master branch only

env:
global:
- HEXO_BACKUP_REPO: github.com/voidking/hexo-backup.git
- HEXO_THEME_REPO: github.com/voidking/hexo-theme-next.git
- GITHUB_PAGES_REPO: github.com/voidking/voidking.github.io.git
- VOIDKING_REPO: github.com/voidking/voidking.git

before_install:
- npm install hexo -g
- npm install gulp-cli -g

install:
- npm install

script:
- git clone https://${HEXO_THEME_REPO} themes/next
- git clone https://${GITHUB_TOKEN}@${HEXO_BACKUP_REPO} hexo-backup
- mv hexo-backup/source .
- rm -rf source/private
- npm run build

after_success:
- git config --global user.name "voidking"
- git config --global user.email "voidking@qq.com"
- git clone https://${GITHUB_TOKEN}@${GITHUB_PAGES_REPO} voidking
- unalias cp
- cp -rf public/* voidking
- cd voidking
- git add .
- git commit -m "Travis CI Auto Builder"
- git push --force --quiet "https://${GITHUB_TOKEN}@${GITHUB_PAGES_REPO}" master:master

精简search.xml

html、css和js都压缩了,很开心。但是,还有一个大文件没有压缩,就是本地搜索的DB文件search.xml。我的博客有接近600篇文章,这个search.xml文件的大小为7.5M,很大。
打开search.xml文件,发现里面不止包含文章内容,还包含html标签。参考hexo-generator-searchdb,发现可以设置不生成标签。

修改localsearch配置

1、修改hexo/_config.yml的localsearch配置为:

1
2
3
4
5
6
# local search
search:
path: search.xml
field: post
format: striptags
limit: 10000

2、重新生成search.xml文件,新的文件只有3.5M。

3、修改local-search.js
为了正常使用搜索功能,需要修改hexo主题的local-search.js。如果不修改的话,搜索时只搜索标题,不会搜索内容。编辑next/source/js/local-search.js,如下修改:

1
2
3
// line 120
// let content = data.content ? data.content.trim().replace(/<[^>]+>/g, '') : '';
let content = data.content;

以上,实现了search.xml的精简,nice。

自定义精简

但是,3.5M依然很大,能不能再精简一下?可以。
1、localsearch的format改回html。

2、修改xml_generator.js
编辑hexo/node_modules/hexo-generator-searchdb/lib/xml_generator.js,定义自己想要删除的字符:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
'use strict';

const path = require('path');
const fs = require('fs');
const nunjucks = require('nunjucks');
var env = new nunjucks.Environment();

var searchTmplSrc = path.join(__dirname, '../templates/search.xml');
var searchTmpl = nunjucks.compile(fs.readFileSync(searchTmplSrc, 'utf8'), env);

var stripe_code_line_num = function(str) { // 去除代码
return str.replace(/<figure class="highlight.*?<\/figure>/ig, '');
}
var stripe = function (str) { // 去除html标签
return str.replace(/(<([^>]+)>)/ig, '');
}
var minify = function (str) { // 压缩成一行
return str.trim().replace(/\n/g, ' ').replace(/\s+/g, ' ');
}

module.exports = function(locals) {
var config = this.config;
var database = require('./database')(locals, config);
database.forEach( function(element, index) {
element.content = minify(stripe(stripe_code_line_num(element.content)));
});
var xml = searchTmpl.render({
articles: database,
config : config.search
});
return {
path: config.search.path,
data: xml
};
};

3、重新生成search.xml,这次只有2.5M,nice。

以上两种精简search.xml的方法都很好,这里我选择使用修改localsearch format的方法。因为如果在xml_generator.js不删除文章中的代码,两种方法的压缩结果基本相同,而方法一通用性更好。