一、静态资源概述
静态资源,从其名称便可大致理解其特性,即通常情况下不会自行发生变化的资源。这里所说的 “不会变化” 并非绝对意义上的永远不变,而是指在网站未进行更新之前,这些资源不会主动发生变动。最为常见的静态资源种类繁多,其中包括但不限于 HTML 文件、各种多媒体文件(如图片、音频、视频等)、字体文件以及 JS/CSS 文件等等。
(一)HTML 及 JS/CSS 文件优化
首先来说说 HTML 以及 JS/CSS 文件。这类由代码构成的文件,在编写过程中,为了提高其可读性,开发者往往会插入大量的空格、换行等字符。这些字符有些是肉眼可见的,有些则不可见,但无论其是否可见,它们的存在与否都不会对程序的运行结果产生影响。然而,不可忽视的是,这些字符确实占用着一定的存储空间。因此,通过使用特定的工具删掉这些不必要的字符,便能够在一定程度上减小文件的体积。
(二)多媒体文件优化
对于多媒体文件而言,大部分都可以进行压缩处理。在压缩过程中,多多少少会出现一定程度的失真(即有损压缩),但只要这种失真程度不会对用户的体验造成明显影响,我们便不必过于纠结这些微小的损失。常见的压缩手段多种多样,包括但不限于使用 webp 格式、降低图片分辨率等等。
(三)字体文件优化
字体文件方面,对于英文网站来说,通常不会带来特别严重的负担。然而,中文字符的数量极为庞大,如果将所有的中文字符都囊括进一个字体文件中,那么这个字体文件的大小动辄就会达到 4MB,甚至有些能够超过 20MB。如此高昂的空间成本是我们难以接受的。所以,一般情况下,我们也会对字体文件进行压缩处理。
压缩字体文件主要有两种方案。第一种是从字体文件中提取出常用的文字;第二种则是仅保留我们实际需要用到的文字。这两种方案各有优劣。第二种方案的压缩率通常要显著高于第一种,同时也更加安全,不会出现某些生僻字我们在后续使用时却发现被误删的情况。但是,第二种方案也存在一个明显的缺陷,那就是每当我们更新网站内容时,就需要重新生成新的字体文件。这个问题乍一看可能并不严重,但当我们使用客户端缓存时,就需要想办法避免缓存带来的影响。
二、静态资源优化教程
接下来,为大家详细说明我所采用的压缩方案。我是使用 gulp 来压缩静态资源。需要注意的是,我并没有通过 gulp 压缩多媒体资源,多媒体资源我是通过 netlify 插件和又拍云进行压缩的。如果您需要压缩多媒体资源,可以自行在网上查找相应的插件。
(一)安装 gulp
首先,在博客根目录打开终端,输入以下命令安装 gulp:
npm install --global gulp-cli
npm install gulp --save
(二)安装 gulp 插件
接下来,安装 gulp 插件,小伙伴们可以根据自己的实际需求进行安装,无需全部安装。
压缩 HTML:
npm install gulp-htmlclean --save-dev
npm install gulp-html-minifier-terser --save-dev
压缩 CSS:
npm install gulp-cssnano --save-dev
压缩 JS:
npm install gulp-terser --save-dev
压缩 TTF:
npm install gulp-fontmin --save-dev
(三)创建 gulpfile.js 文件
在根目录创建 gulpfile.js,并输入以下内容:
const gulp = require("gulp");
// 用到的各个插件
const htmlMin = require('gulp-html-minifier-terser');
const htmlClean = require('gulp-htmlclean');
const terser = require('gulp-terser');
const cssnano = require('gulp-cssnano');
const fontmin = require('gulp-fontmin');
// 压缩 js
// 参数 doc:https://github.com/terser-js/terser#minify-options
gulp.task('minify-js', () =>
gulp.src(['./public/**/*.js'])
.pipe(terser({
compress: {
/** @see https://blog.csdn.net/weixin_39842528/article/details/81390588 */
sequences: 50,
unsafe: true,
unsafe_math: true,
pure_getters: true,
ecma: true
}
}))
.pipe(gulp.dest('./public'))
);
// 压缩 css
// 参数 doc:https://cssnano.co/docs/what-are-optimisations/
gulp.task('minify-css', () =>
gulp.src(['./public/**/*.css'])
.pipe(cssnano({
mergeIdents: false,
reduceIdents: false,
discardUnused: false
})).pipe(gulp.dest('./public'))
);
// 压缩 html
// 参数 doc:https://github.com/terser/html-minifier-terser#readme
gulp.task('minify-html', () =>
gulp.src('./public/**/*.html')
.pipe(htmlClean())
.pipe(htmlMin({
removeComments: true, // 清除 html 注释
collapseWhitespace: true, // 合并空格
collapseBooleanAttributes: true, // 压缩布尔类型的 attributes
noNewlinesBeforeTagClose: false, // 去掉换行符
removeAttributeQuotes: true, // 在可能时删除属性值的引号
removeRedundantAttributes: true, // 属性值与默认值一样时删除属性
removeEmptyAttributes: true, // 删除值为空的属性
removeScriptTypeAttributes: true, // 删除 `type="text/javascript"`
removeStyleLinkTypeAttributes: true, // 删除 `type="text/css"`
minifyJS: true, // 压缩页面 JS
minifyCSS: true, // 压缩页面 CSS
minifyURLs: true // 压缩页面 URL
}))
.pipe(gulp.dest('./public'))
);
//压缩字体
function minifyFont(text, cb) {
gulp
.src('./public/fonts/*.ttf') //原字体所在目录
.pipe(fontmin({
text: text
}))
.pipe(gulp.dest('./public/fontsdest/')) //压缩后的输出目录
.on('end', cb);
}
gulp.task('minify-ttf', (cb) => {
var buffers = [];
gulp
.src(['./public/**/*.html']) //HTML 文件所在目录请根据自身情况修改
.on('data', function (file) {
buffers.push(file.contents);
})
.on('end', function () {
var text = Buffer.concat(buffers).toString('utf-8');
minifyFont(text, cb);
});
});
//压缩
gulp.task("zip", gulp.parallel('minify-js', 'minify-css', 'minify-html', 'minify-ttf'))
//如果有不需要的压缩功能,直接删除对应代码并在 zip 任务中删除对其的调用即可。
(四)压缩资源
现在,只要我们在执行 hexo g 后执行 gulp zip 即可压缩我们想要压缩的资源了。
我们可以列一个表比较一下压缩前后文件大小的区别(这里只列出我使用到的插件):
文件 压缩前(KB) 压缩后(KB) 减少(KB)
index.css 251 146 105
main.js 35.6 9.31 26.29
HTML 总和 8141.5 7415 726.5
注意:这里使用 gulp 压缩 TTF 的原理是读取所有 HTML 文件从而得出我们需要的字符集,然后从 TTF 文件中提取出我们需要的字体,然后输出到指定目录中。所以当没有执行 gulp 任务的时候,就不会在目录中生成压缩后的文件。该插件在输出字体文件时支持输出:ttf、woff、eot 及 svg 四种格式。使用时务必根据自己的实际情况修改 js 文件中的目录信息。插件的压缩参数各位可以自行前往插件官网查看文档并自行修改。
(五)整合 CSS
我们可以通过将 CSS 整合进一个文件中来提高空间的利用率(原理可自行百度 “小文件多为什么占用空间大”),同时也能提高插件的压缩率(因为插件压缩的时候只会分析正在压缩的文件,不会分析多个 CSS 之间的关系)。
整合 CSS 有两个方案,一种是手动整合,一种是修改博客主题源代码。我们尽量使用第二种方案,这里我只给出 butterfly 主题对应的方案,其它主题的读者可以自行摸索或者干脆用第一种方案。
修改:[butterfly]\source\css\index.styl:(注意缩进)
// search
if hexo-config('algolia_search.enable')
@import '_search/index'
@import '_search/algolia'
if hexo-config('local_search') && hexo-config('local_search.enable')
@import '_search/index'
@import '_search/local-search'
- @import '_custom/*.styl'
- @import '_custom/*.css'
然后在与该文件同级目录中新建文件夹 “_custom”,接下来,我们把我们自己编写的 css/styl 文件全部放到这里就能直接整合进 index.css 中了。
(六)使用 CDN
相信很多小伙伴为了白嫖静态服务器,都把博客部署在了国外。这样子的话,国内访问的时候难免会遇到访问慢和不稳定的问题。我们可以通过使用 CDN 来解决这个问题。
首先,使用 CDN 的前提是有自己的域名,如果要白嫖国内的 CDN 的话还需要进行备案。一切准备就绪后挑选心仪的 CDN 供应商即可。
(七)本地缓存
另一个简单有效的方案就是配置网站的本地缓存,将网站的一部分静态资源缓存在客户端上。这样客户端在访问网站时,就可以减少一部分网络请求,以此优化用户体验,同时还能减轻服务器负担。我是使用的 ServiceWorker 进行本地缓存控制。