本文内容基于 zu1k 的同名文章。在此向原作者致以诚挚的感谢。

由于本文记录我使用的方法(包括踩坑的过程),内容不会和原文完全一致。

压缩

压缩图片

由于我没有太多要处理的图片,使用 TinyPNG 进行压缩。

在 Windows 中壁纸的图片质量是 85% —— 这个冷知识是我使用 Winaero Tweaker 时发现的。客观而言这个质量是不错的。

如果你有大量图片需要压缩,可以使用 ImageMagick 进行批量处理。

压缩 HTML、CSS 和 JS

网页源码中的注释、空格和换行符会增加文件的大小,影响加载速度。

使用 gulp 可以很方便地压缩 HTML、CSS、JS 和图片。

1
2
npm install gulp -g
npm install gulp gulp-minify-css gulp-babel gulp-uglify gulp-htmlmin gulp-imagemin imagemin-jpegtran imagemin-svgo imagemin-gifsicle imagemin-optipng --save-dev

其中 -g 表示全局安装,将 gulp 添加到 PATH 中;--save-dev 表示将依赖添加到 package.jsondevDependencies 中。

在博客根目录下创建 gulpfile.js

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
var gulp = require("gulp");
var minifycss = require("gulp-minify-css");
var uglify = require("gulp-uglify");
var htmlmin = require("gulp-htmlmin");
var htmlclean = require("gulp-htmlclean");
var imagemin = require("gulp-imagemin");

// 压缩css文件
gulp.task("minify-css", function () {
return gulp
.src("./public/**/*.css")
.pipe(minifycss())
.pipe(gulp.dest("./public"));
});

// 压缩html
gulp.task("minify-html", function () {
return gulp
.src("./public/**/*.html")
.pipe(htmlclean())
.pipe(
htmlmin({
collapseWhitespace: true,
collapseBooleanAttributes: true,
removeComments: true,
removeEmptyAttributes: true,
removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: true,
minifyJS: true,
minifyCSS: true,
minifyURLs: true,
ignoreCustomFragments: [/\{\{[\s\S]*?\}\}/],
})
)
.pipe(gulp.dest("./public"));
});

// 压缩js文件
gulp.task("minify-js", function () {
return gulp
.src(["./public/**/*.js", "!./public/js/**/*min.js"])
.pipe(uglify())
.pipe(gulp.dest("./public"));
});

// 压缩图片
gulp.task("minify-images", function () {
return gulp
.src([
"./public/**/*.png",
"./public/**/*.jpg",
"./public/**/*.gif",
"./public/**/*.svg",
])
.pipe(
imagemin([
imagemin.gifsicle({ interlaced: true }),
imagemin.mozjpeg({ quality: 75, progressive: true }),
imagemin.optipng({ optimizationLevel: 5 }),
imagemin.svgo({
plugins: [{ removeViewBox: true }, { cleanupIDs: false }],
}),
])
)
.pipe(gulp.dest("./public"));
});

gulp.task(
"default",
gulp.series(
gulp.parallel("minify-html", "minify-css", "minify-js", "minify-images")
)
);

但我遇到了以下问题:

1
2
3
4
5
Error [ERR_REQUIRE_ESM]: require() of ES Module D:\archive\blog\node_modules\gulp-imagemin\index.js from D:\archive\blog\gulpfile.js not supported.
Instead change the require of index.js in D:\archive\blog\gulpfile.js to a dynamic import() which is available in all CommonJS modules.
at Object.<anonymous> (D:\archive\blog\gulpfile.js:6:16) {
code: 'ERR_REQUIRE_ESM'
}

补充一点背景知识:commonjses6 (module) 是两种不同的模块化规范,不能混用。一个项目的模块系统可以在 package.json 中指定:

1
2
3
{
"type": "module" // 'commonjs' | 'module', default is 'commonjs'
}

其区别如下:

模块系统导入导出文件扩展名特点
CommonJSrequire('your-module')module.exports = yourModule.js, .cjs运行时加载
ESMimport yourModule from 'your-module'export default yourModule.mjs静态加载

那么为什么你可以在一些项目中同时看到 requireimport 呢?因为可以用 async import 来在 commonjs 中使用 ESM 模块。(但是在 ESMrequire 这个方法是不存在的,所以不能反向操作。)

根据报错信息,gulp-imagemin 是一个只支持 ESM 的模块,因此可以将 require 改成动态 import

1
2
3
4
5
6
// const imagemin = require("gulp-imagemin");

(async () => {
const imagemin = (await import("gulp-imagemin")).default;
// do something with imagemin
})();

完成之后,每次 hexo g 之后运行 gulp 即可。

使用 jsDeliver

jsDeliver 是一个 CDN 服务,提供了免费的静态资源加速服务。

你可以通过以下链接访问 GitHub 上的任何文件:

1
https://cdn.jsdelivr.net/gh/<username>/<repo>@<branch>/<path>/

其中 <branch> 可以是分支或标签 (tag),省略的情况下则为默认分支的最新提交。

例如:

1
https://cdn.jsdelivr.net/gh/mojimoon/blog@v20250422/image/mojimoon.png

访问了 mojimoon/blog 仓库 v20250422 标签下的 image/mojimoon.png 文件。

不使用 <branch>,则每次访问都会获取最新的文件。对于图像、JS、CSS 等不会频繁更新的文件,可以指定 tag 来加快访问速度。

_config.yml 中添加以下配置:

1
2
3
cdn:
enabled: true
url: https://cdn.jsdelivr.net/gh/mojimoon/blog@v20250422

然后将各种 CSS、JS 和图片的路径替换掉:

_config.stellar.yml

1
2
3
stellar:
main_css: 'https://cdn.jsdelivr.net/gh/mojimoon/blog@v20250422/css/main.css'
main_js: 'https://cdn.jsdelivr.net/gh/mojimoon/blog@v20250422/js/main.js'

js 引用:

1
2
3
4
5
6
7
// utils.js('/js/plugins/copycode.js');

if (theme.cdn.enabled) {
utils.js(`${theme.cdn.url}/js/plugins/copycode.js`);
} else {
utils.js('/js/plugins/copycode.js');
}