普通视图

发现新文章,点击刷新页面。
昨天以前首页

迎来船新版本的Hexo+NexT

作者 Alliot
2023年9月1日 12:44

  自从 2017 年使用 Hexo+NexT 作为博客框架以来,已经过去好几个年头。就如前面那篇hexo使用Artalk评论系统 博客所言,由于 Alliot 之前对 NexT 主题与部分插件做了许多侵入式的魔改,基本没有对其做过日常的版本升级维护,因此,已经没有平滑升级的可能性。在一次插件失效的契机下,终于下定决心推倒重建。 本文记录了这一次重建的过程以及在维护模式上相比旧版本的改进。

hexo 博客的常见配置

作者 千古壹号
2020年9月21日 11:53

hexo常见命令

新建文章草稿

Hexo 提供了 draft 机制,草稿里将建立在 source/_drafts 目录下。当执行 hexo generate 时,并不会将其编译到 public 目录下,所以 hexo deploy 发布之后,草稿不会显示在页面中。

新建草稿:(草稿不会显示在页面中)

1
hexo new draft <title>

本地预览草稿:

1
$ hexo S --draft

Hexo server 提供了 --draft 参数,搭配 hexo-browsersync 这个插件,就可以一边编辑 markdown 文章,一边使用浏览器预览。

新建一篇文章

新建的文章,会自动存放在 source/_posts目录下。

新建文章:

1
hexo new  "my-article"

本地预览:

1
hexo serve

新建文件夹blog,然后初始化项目:

1
2
3
cd blog
hexo init
npm install

Hexo 自动部署和发布

我们可以在本地新建一个 xxx.md 文件放在 blog\source\_posts 目录中。然后在本地的blog目录下,执行如下命令,就可以将文章发布到服务器端了:

方式1:

1
2
3
hexo clean
hexo generate
hexo deploy

方式2:

1
2
3
hexo cl
hexo g
hexo d

方式3:

1
hexo cl && hexo g && hexo d

hexo 文章格式

文章格式是选填的,不是必须的;但最好加上尽可能多的文章格式,让文章的信息更完整。

hexo 文章的简略格式

1
2
3
4
5
6
7
8
9
---
title: 我是文章标题
date: 2020-09-19 11:30:30
author: qianguyihao
categories: 我是分类
tags:
- 标签1
- 标签2
---

hexo 文章的较完整格式

1
2
3
4
5
6
7
8
9
10
---
title: 我是文章标题
date: 2020-09-19 11:30:30
author: qianguyihao
urlname:
categories: 我是分类
tags:
- 标签1
- 标签2
---

hexo 文章模板的自定义

每次使用 hexo new "my-article"新建一篇文章时,默认只有title、date、tags这几个属性。

我们可以修改scaffolds/post.md文件,自定义文章格式的模板,我修改后的内容如下:

1
2
3
4
5
6
7
8
9
---
title: {{ title }}
date: {{ date }}
update: {{ date }}
author:
urlname:
categories:
tags:
---

hexo 文章的全部属性

参考链接:https://www.dazhuanlan.com/2019/11/30/5de154d0810af/

自定义文章的url地址

(1)修改 hexo/_config.yml 文件:

1
2
#permalink: :year/:month/:day/:title/
permalink: :urlname/

(2)然后,我们就可以单独在具体某篇文章里的头部,通过 urlname字段 自定义这篇文章的url了:

1
2
3
4
5
---
title: 我是文章标题
date: 2020-09-21 11:53:36
urlname: xxx-url
---

参考链接:

给hexo博客生成RSS订阅

(1)在 hexo 项目根目录下执行如下命令:

1
npm install hexo-generator-feed --save

(2)在 hexo 根目录下的 _config.yml 文件中添加如下配置:

1
2
3
4
5
#订阅RSS
feed:
type: atom
path: atom.xml
limit: false

(3)在 theme 目录下的 _config.yml 文件中添加如下配置:

1
rss: /atom.xml

添加上面这行之后,就可以确保在网站的菜单栏展示出“RSS”这几个字(也就是说,露出了RSS订阅的入口)。

当然,你也可以把RSS订阅的入口放在“社交图标”的位置。不同的主题,配置方式不同。比如,就拿hexo-theme-melody主题来说,它的配置方式很简单,在melody主题的 _config.yml 文件中配置如下内容:

1
2
social:
rss fa: https://qianguyihao.com/atom.xml

(4)重新编译,生成博客的静态文件:

1
hexo clean && hexo g

此时,在 public 文件夹中会自动生成一个 atom.xml 文件。

这个atom.xml 就是的 RSS 订阅文件了,以后只需要访问 qianguyihao.com/atom.xml 就可以实现 RSS 订阅了。

参考链接:

hexo-theme-melody 主题配置

官方文档:https://molunerfinn.com/hexo-theme-melody-doc/zh-Hans/

图片无法自适应的问题

解决办法:https://github.com/Molunerfinn/hexo-theme-melody/issues/285

接入 Google Adsense

配置 melody.yml文件:

1
2
3
4
5
google_adsense:
enable: true
js: //pagead2.googlesyndication.com/pagead/js/adsbygoogle.js
client: ca-pub-1601618516206303
enable_page_level_ads: true

常见问题积累

nginx 重启失败

修改nginx后,重启nginx:

1
2
3
4
5
6
7
8
9
# 修改nginx
cd /usr/local/nginx/conf
ls
vim nginx.conf

# 重启nginx
cd /usr/local/nginx/sbin
ls
./nginx -s reload

结果提示下面这个错误:

1
2
[root@iZw9 sbin]# ./nginx -s reload
nginx: [error] open() "/usr/local/nginx/logs/nginx.pid" failed (2: No such file or directory)

进入到logs目录发现确实没有nginx.pid文件。

解决办法:

使用指定nginx.conf文件的方式重启nginx:

1
/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf

此时去logs目录下查看发现nginx.pid文件已经生成了,而且也完成了自动重启的事情。

hexo+阿里云搭建博客网站

作者 千古壹号
2020年9月19日 19:00

2020-09-19折腾时间:

  • 15:15~18:00
  • 20:45~22:15
  • 23:50~00:20

经过5个小时的折腾(含笔记整理),输入公网ip之后,终于可以打开自己的博客网站了。

一、本地安装Hexo环境

1、安装 git 环境

2、安装Node.js环境

3、安装 Hexo,并初始化项目

安装 hexo:

1
npm install -g hexo-cli

新建文件夹blog,然后初始化项目:

1
2
3
cd blog
hexo init
npm install

初始化完成后,blog文件夹内包括如下内容:

在blog文件夹内安装插件:

1
2
npm install hexo-deployer-git --save
npm install hexo-server

在blog文件夹内,配置git提交的账号邮箱:

1
2
git config user.email "youremail@mail.com"
git config user.name "yourname"

4、新建一篇文章

新建文章:

1
hexo new  "my-article"

新建的文章,会自动存放在 source/_posts目录下。

然后,我们可以开始在 source/_posts/my-article.md 文件里,写 markdown 格式的文章了。

5、在本地预览项目

输入如下命令,在浏览器预览项目:

1
2
3
4
5
6
7
$ hexo server
或者
$ hexo s

INFO Validating config
INFO Start processing
INFO Hexo is running at http://localhost:4000 . Press Ctrl+C to stop.

在浏览器输入 http://localhost:4000 ,就能看到 Hexo 的默认主题下的主页了:

至此我们就完成了在本地的配置工作。

二、域名注册、服务器购买

1、域名注册

2、购买阿里云服务器 ECS

进入阿里云主页 https://www.aliyun.com/,点击“云服务器ECS ”进行购买:

购买服务器ECS时,可以选择如下配置:

  • 地域:选择离经常访问你网站的用户近一些的地域
  • 内存:1G
  • 云盘:40G
  • 网络:专有网络
  • 公网IP:包含
  • 带宽:1Mbps

按照上面的配置,2020-09-19这天的价格如下:

  • 一年:700
  • 三年:1600

我选择了三年的。

3、域名备案

域名备案时,需要先准备一个ECS服务器,我们可以直接用上面购买的服务器。

备案时间较长,请耐心等待。

三、阿里云ECS配置

重置实例密码

由于 ECS 服务器对 root 用户没有设置初始密码,因此我们需要对 root 密码进行重置:

温馨提示:记得妥善保管自己的 root 用户密码哦。并且在搭建的过程中如遇到不可挽回的局面可以考虑重置 ECS 实例,相当于重装系统。操作如下:

设置安全组

阿里云的服务器默认不开放端口号,这样使得我们在网站部署完成之后仍然无法访问。

有一个基本原因是没有开启端口号,因此我们需要新建安全组并添加 80 端口,再将安全组添加到 ECS 实例中。具体操作如下。

在控制台的 ECS 实例中点击「网络与安全–>安全组–>创建安全组–>快速添加」。在访问规则的入方向添加如下几个端口(尤其是80端口):

然后回到 ECS 服务器实例,将刚刚配置的安全组加入到实例中:

备注:安全组的出方向不用配置,默认对外都是放行的。

四、服务器端配置

此步骤是博客搭建过程中最容易出错的地方,提出以下几点建议:

  • 为了避免出错,推荐直接复制粘贴命令行代码。
  • 分清是在本地计算机上操作,还是连接服务器在服务器上操作。
  • 分清在服务器上使用 Git 用户还是使用 root 用户进行操作。

本地通过 ssh 连接服务器

我用的是Mac电脑,推荐使用 Royal TSX 软件进行ssh连接。

参考链接:在Mac上使用Royal TSX,替代 xshell 和 item2、SecureCRT,可以 SSH 也能 FTP

(如果你用的是 Windows电脑,推荐使用Xshell软件进行ssh连接。)

安装 nginx

参考链接:centos8平台编译安装nginx1.18.0

我们使用 nginx 作为 web 服务器和反向代理工具。

(1)安装 nginx 依赖环境(安装期间有提示一律选 yes):

1
2
3
4
yum install gcc-c++
yum install -y pcre pcre-devel
yum install -y zlib zlib-devel
yum install -y openssl openssl-devel

(2)下载 nginx 安装包:

1
wget -c https://nginx.org/download/nginx-1.18.0.tar.gz

将安装包解压到 /usr/local 目录下:

1
tar -zxvf nginx-1.18.0.tar.gz -C /usr/local

(3)进入 /usr/local 目录,确认 nginx 解压到该目录下:

1
cd /usr/local

进入 nginx-1.18.0 目录,会发现该目录下有一个 configure 文件,执行该配置文件:

1
2
3
cd nginx-1.18.0/
ls
./configure --prefix=/usr/local/soft/nginx --with-http_stub_status_module --with-http_ssl_module

解释:

  • –prefix 指定安装路径

  • –with-http_stub_status_module 允许查看nginx状态的模块

  • –with-http_ssl_module 支持https的模块

编译并安装 nginx:

1
2
make
make install

(4)查找nginx安装目录:

1
2
$ whereis nginx
/usr/local/nginx

进入安装目录:

1
2
3
4
$ cd /usr/local/nginx
$ ls
# 有下面这几个文件
# conf html logs sbin

由于 nginx 默认通过 80 端口访问,而 Linux 默认情况下不会开发该端口号,因此需要开放 linux 的 80 端口供外部访问:

1
/sbin/iptables -I INPUT -p tcp --dport 80 -j ACCEPT

(9)进入 nginx安装目录的sbin 目录,启动 nginx:

1
2
3
cd /usr/local/nginx
cd sbin
./nginx

没有任何消息,代表启动成功。此时输入公网 IP 即可进入 nginx 的欢迎页面了:

备注:注意要保证 nginx 服务处于 运行状态 才可以访问博客网站。nginx 相关命令如下:(在 cd /usr/local/nginx/sbin 目录下执行)

1
2
3
4
5
6
7
8
9
10
cd /usr/local/nginx/sbin

# 停止 nginx 服务
./nginx -s stop

# 启动 nginx 服务
./nginx

# 重启 nginx 服务
./nginx -s reload

配置 nginx 路由

(1)为 hexo 创建一个部署目录 /home/www/hexo

1
mkdir -p /home/www/hexo

(2)进入 /usr/local/nginx/conf 目录,并对 nginx.conf 配置文件进行相关配置:

1
2
3
cd /usr/local/nginx/conf
ls
vim nginx.conf

打开nginx.conf文件后,按 i 键由命令模式切换到编辑模式,修改三个地方:

  • 首先将最顶端的用户改为 root。
  • 其次,将 server_name 改为自己的域名。如果没有备案,可以先填写自己的公网 IP(在阿里云控制台的 ECS 实例中查看),访问时暂时用公网 IP 进行访问。
  • 最后,将location中的 root 项中的值改为 /home/www/hexo;。如果 server 中的端口号不是 80,则改为 80

修改结束之后,先按 Esc 由编辑模式切换到命令模式,再输入 :wq 命令保存并退出编辑器。

nginx.conf 修改前:

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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#user  nobody;
worker_processes 1;

#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;

#pid logs/nginx.pid;


events {
worker_connections 1024;
}


http {
include mime.types;
default_type application/octet-stream;

#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';

#access_log logs/access.log main;

sendfile on;
#tcp_nopush on;

#keepalive_timeout 0;
keepalive_timeout 65;

#gzip on;

server {
listen 80;
server_name localhost;

#charset koi8-r;

#access_log logs/host.access.log main;

location / {
root html;
index index.html index.htm;
}

#error_page 404 /404.html;

# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}

# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}

# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}

# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}


# another virtual host using mix of IP-, name-, and port-based configuration
#
#server {
# listen 8000;
# listen somename:8080;
# server_name somename alias another.alias;

# location / {
# root html;
# index index.html index.htm;
# }
#}


# HTTPS server
#
#server {
# listen 443 ssl;
# server_name localhost;

# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;

# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;

# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;

# location / {
# root html;
# index index.html index.htm;
# }
#}

}

修改后:

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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
user  root;
worker_processes 1;

#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;

#pid logs/nginx.pid;


events {
worker_connections 1024;
}


http {
include mime.types;
default_type application/octet-stream;

#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';

#access_log logs/access.log main;

sendfile on;
#tcp_nopush on;

#keepalive_timeout 0;
keepalive_timeout 65;

#gzip on;

server {
listen 80;
server_name www.qianguyihao.com;
return 301 https://www.qianguyihao.com$request_uri;

#charset koi8-r;

#access_log logs/host.access.log main;

location / {
root /home/www/hexo;
index index.html index.htm;
}

#error_page 404 /404.html;

# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}

# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}

# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}

# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}


# another virtual host using mix of IP-, name-, and port-based configuration
#
#server {
# listen 8000;
# listen somename:8080;
# server_name somename alias another.alias;

# location / {
# root html;
# index index.html index.htm;
# }
#}


# 开启 HTTPS
#
server {
listen 443 ssl;
server_name www.qianguyihao.com qianguyihao.com;

ssl_certificate /usr/local/nginx/cert/4523958_www.qianguyihao.com.pem;
ssl_certificate_key /usr/local/nginx/cert/4523958_www.qianguyihao.com.key;

ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;

ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;

location / {
root /home/www/hexo;
index index.html index.htm;
}
}

}

需要修改的位置如下:

修改nginx后,重启nginx:

1
2
3
cd /usr/local/nginx/sbin
ls
./nginx -s reload

安装 node.js

安装 node.js的命令如下:

1
2
3
cd ~
curl -sL https://rpm.nodesource.com/setup_10.x | bash -
yum install -y nodejs

过查看版本号验证是否安装成功:

1
2
node -v
npm -v

效果如下:

在服务器端创建 Git 用户

为了使我们能够在本地向服务器实现自动部署,需要在服务器端另外新建一个 Git 用户。然后使用公钥连接成功之后,就可以方便地随时进行自动部署了。

执行如下命令,在阿里云安装git环境:(有提示时,选择 yes 即可)

1
yum install git

安装结束之后,通过查看版本号验证是否安装成功:

1
2
$ git --version
git version 2.18.4

创建 Git 用户:

1
adduser git

修改 Git 用户权限为 740:

1
chmod 740 /etc/sudoers

在配置文件中增加 Git 用户。首先打开文件:

1
vim /etc/sudoers

进入文件后,后按 i 键由命令模式切换到编辑模式。如下图所示,在 root 下添加一行 Git 信息:

修改结束后,先按 Esc 由编辑模式切换到命令模式,再输入:wq 命令保存并退出编辑器。

将 Git 用户的权限改回去:

1
chmod 400 /etc/sudoers

设置 Git 用户密码:

1
2
3
4
5
$ sudo passwd git
更改用户 git 的密码 。
新的 密码:
重新输入新的 密码:
passwd:所有的身份验证令牌已经成功更新。

以上我们就完成了 Git 用户的创建,接下来我们向 Git 用户添加公钥,就像配置 Github 那样。

给服务器端的 Git 用户配置 ssh 公钥

这样做的目的就是,以后由本地向服务器提交资源,就不需要再进行身份验证了。

流程大致如下:

  • 先在本地的C:\Users\用户名.ssh目录生成公钥id_rsa.pub和私钥id_rsa
  • 然后使用 FTP 上传工具,将公钥文件id_rsa.pub上传到服务器端的 .ssh 文件夹;
  • 最后将公钥文件id_rsa.pub内容拷贝到 authorized_keys 文件中。

温馨提示:使用 ctrl + c 复制命令,然后在终端点击右键就可以直接粘贴上去了,避免手动输入的麻烦。

如果你之前配置过公钥到 Github、Gitlab 等仓库,那你直接使用之前的公钥即可。

另外,我们要注意在本地操作还是在服务器端操作;在服务器端的时候,是使用 root 用户还是使用 git 用户操作。

(1)在服务器端切换到 git 用户,在根目录下创建 .ssh文件夹:

1
2
3
su git
cd ~
mkdir .ssh

此时,命令行信息中的 # 变成了 $,且 root 变成了 git,表示我们切换成功。

(2)在本地生成生成公钥、私钥:(注意是在本地)

1
2
3
4
5
$ cd ~
$ cd .ssh
$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/smyhvae/.ssh/id_rsa):

上面的命令中,如果有询问,直接回车即可。结束之后,会在 C:\Users\用户名\.ssh 里生成两个文件:公钥文件 id_rsa.pub、私钥文件id_rsa

注意,.ssh 为隐藏文件夹,你可能需要显示隐藏文件夹之后才可以看到。

(3)在本地终端输入以下命令,为私钥设置权限:

1
2
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_rsa

(4)使用ftp工具,将本地的 id_rsa.pub 文件上传到服务器端的/home/git/.ssh目录下:

在使用ftp工具登录远程服务器时,登录项如下:

  • ip:公网ip。
  • 端口:22
  • 协议:sftp
  • 用户名:git
  • 密码:xx

注意,此时服务器端 .ssh 文件夹里还没有 authorized_keys 文件,只有 id_rsa.pub 这一个文件。

(5)回到 服务器端,以 Git 用户身份在 .ssh 文件夹内新建 authorized_keys 文件,并将公钥内容拷贝到该文件中:

1
2
3
cd ~/.ssh
cp id_rsa.pub authorized_keys
cat id_rsa.pub >> ~/.ssh/authorized_keys

修改文件权限:

1
2
chmod 600 ~/.ssh/authorized_keys
chmod 700 ~/.ssh

(6) 确保设置了正确的SELinux上下文:

1
restorecon -Rv ~/.ssh

现在我们来验证一下,在本地输入如下命令,是否能正常连接到远程服务器:(不用输入密码,就能直接连上)

1
ssh -v git@xxx.xxx.xxx.xxx(你的公网 IP)

如果显示欢迎界面,表示本地连接远程服务器的git用户时,连接成功:

但是我们一般不使用 Git 用户进行服务端操作,而是使用 root 用户。Git 用户只是作为自动部署特意新建的。

比如说,在本地输入如下命令,可以连接远程服务器的root用户:(需要输入密码)

1
ssh -v root@xxx.xxx.xxx.xxx(你的公网 IP)

在服务端配置 Git 仓库

(1)在服务器端使用 Git 用户 创建 git 仓库,并新建 post-receive 钩子文件:

1
2
3
4
5
6
7
8
9
su git
cd ~
sudo git init --bare hexo.git

# 新建文件
touch ~/hexo.git/hooks/post-receive

# 修改文件权限
chmod +x ~/hexo.git/hooks/post-receive

备注:注意ls、touch、cat、vi/vim的区别。

输入如下命令编辑文件:

1
vim ~/hexo.git/hooks/post-receive

进入文件后,后按 i 键由命令模式切换到编辑模式。输入以下命令:

1
git --work-tree=/home/www/hexo --git-dir=/home/git/hexo.git checkout -f

修改完成后,先按 Esc 由编辑模式切换到命令模式,再输入 :wq 命令保存并退出编辑器。

(2)在服务器端使用root用户,修改文件权限:

1
2
3
su root
cd ~
sudo chmod -R 777 /home/www/hexo

(3)重启 ECS 实例。

到此,我们就完成了服务端的配置。

五、hexo本地部署和发布

本地 Hexo 配置连接和域名

主要是修改 _config.yml 文件。进入本地计算机 blog 文件夹的根目录,找到 _config.yml 文件并打开。

(1)把 deploy 参数改成如下方式:(注意,xxx 的地方是填写你自己的公网 IP )

1
2
3
4
deploy:
type: git
repo: git@xxx.xxx.114.110:/home/git/hexo.git
branch: master

(2)URL 配置项需要改为自己的域名:(如果没有备案,则可以先填写公网 IP)

1
url: http://www.qianguyihao.com

Hexo 自动部署和发布

我们可以在本地新建一个 xxx.md 文件放在 blog\source\_posts 目录中。然后在本地的blog目录下,执行如下命令,就可以将文章发布到服务器端了:

方式1:

1
2
3
hexo clean
hexo generate
hexo deploy

方式2:

1
2
3
hexo cl
hexo g
hexo d

方式3:

1
hexo cl && hexo g && hexo d

此时,在浏览器中输入自己的公网 IP,你就可以打开你的博客网站了。惊不惊喜?意不意外?

备注:在浏览器中输入自己的公网 IP之后,如果网站打不开,请记得检查之前的步骤是否正确,尤其是检查一下 nginx 服务是否已经启动。

域名DNS解析

当我们的域名备案成功之后,我们就有能力使用域名登陆自己的博客了。在此之前,需要在阿里云 控制台-域名 中设置域名解析。

点击“解析”:

在DNS解析设置里同时添加两条指向公网ip的主机记录:一条@记录,一条www记录。如下:

此时,在浏览器输入www.qianguyihao.com或者qianguyihao.com,就可以打开我的博客网站了。它们都是基于http协议的,等同于http://www.qianguyihao.com

将网站域名支持https

在上面的步骤中,网站域名只支持了 http,还没有支持https。所以,当我输入https://www.qianguyihao.com时,网站是不打开的。

那要怎么让网站域名支持 https呢?我们可以为域名添加免费证书,添加证书后,网站将变成安全的 https。

整体流程如下:(图1)

整体流程如下:(图2)

具体配置步骤如下。

购买免费证书

在阿里云主页搜索 SSL证书,然后点击“立即购买”:

按照下图所示的选项进行选择,可以看到证书是免费的:

按照步骤的流程点击之后,域名解析里会自动多出下面这一条解析:

下载证书

解析完成后,马上会收到两条短信:

短信1:

1
【阿里云】尊敬的smy****@163.com:您为域名www.qianguyihao.com购买的SSL证书已签发成功,现可前往 SSL证书控制台 下载并安装至Web服务器或一键部署到阿里云云产品,详情可参考https://c.tb.cn/I3.ZW3uZ,如需人工帮助请拨打95187-2。

短信2:

1
【阿里云】尊敬的smy****@163.com:您的云盾证书服务实例:cas-cn-xx 开通成功。请登录云盾证书服务控制台查看及管理。

备注:阿里云控制台网址:https://console.aliyun.com

由于我们的 web 服务器是 ngxin,因此下载时选择 nginx:

在服务器端安装证书

(1)按照上面的步骤下载完成后,会得到一个xxx.zip压缩包,将压缩包解压后,会看到两个文件:452xxx_www.qianguyihao.com.pem452xxx_www.qianguyihao.com.key

(2)连接服务器,以 root 用户进入 nginx 配置页面:

1
cd /usr/local/nginx/

创建 cert 文件夹用来存放证书:

1
2
mkdir cert
ls

然后使用ftp工具将刚才的两个证书文件上传到 cert 文件夹。

修改 nginx 配置文件:

1
2
cd /usr/local/nginx/conf
vim nginx.conf

i 进入编辑模式,拉到最下方,开放 443 端口,并填写ssl证书的文件名:

修改结束后,先按 Esc 退出编辑模式,然后输入 :wq 保存并退出。

修改前:

# HTTPS server##server {#    listen       443 ssl;#    server_name  localhost;#    ssl_certificate      cert.pem;#    ssl_certificate_key  cert.key;#    ssl_session_cache    shared:SSL:1m;#    ssl_session_timeout  5m;#    ssl_ciphers  HIGH:!aNULL:!MD5;#    ssl_prefer_server_ciphers  on;#    location / {#        root   html;#        index  index.html index.htm;#    }

修改后:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
server {
listen 443 ssl;
server_name www.qianguyihao.com;

ssl_certificate /usr/local/nginx/cert/452xxx_www.qianguyihao.com.pem;
ssl_certificate_key /usr/local/nginx/cert/452_www.qianguyihao.com.key;

ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;

ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;

location / {
root /home/www/hexo;
index index.html index.htm;
}
}

(3)修改nginx后,重启nginx:

1
2
3
cd /usr/local/nginx/sbin
ls
./nginx -s reload

http 访问时,自动重定向到 https

继续修改 nginx 文件,修改原有端口 80 的监听,加一行配置:

1
2
3
4
server {
listen 80;
return 301 https://www.qianguyihao.com$request_uri;
}

修改之后,当用户使用 http 协议访问网站时,会自动进行 301 跳转,以 https 协议访问网站。

修改nginx后,重启nginx:

1
2
3
cd /usr/local/nginx/sbin
ls
./nginx -s reload

购买和配置付费证书

免费证书只有一年期限。一年到期后,不能再免费了:

image-20210927165112443

所以,接下来,只能购买和配置付费证书了。

(1)我按照下图的配置,选了一个最便宜的证书:

image-20210927165152188

image-20210927165221923

image-20210927165318768

(2)进入证书管理页,配置证书:

image-20210927170021805

上图中,点击“证书申请”,然后输入域名,然后点击“确定”,会进入下方的页面:

image-20210927170128710

上图中,点击“证书申请”,进入下方的页面:

image-20210927170216847

上图中,点击“下一步”,进入下方页面:

image-20210927170506086

上图中,按照步骤操作。先去域名控制台配置dns,然后回到当前页面点击“验证”,最后点击“提交审核”。

dns解析的配置信息如下:

image-20210927170716824

点击“提交审核”之后,会弹窗:

image-20210927170758859

Hexo 主题自定义

我用的是hexo-theme-melody 主题,官方文档上有详细的配置指南。

遇到的问题

Console expects a writable stream instance

问题描述:执行hexo init时报错Console expects a writable stream instance

解决办法:是Node.js版本的问题,v8.xx的版本太低了,建议升级到V10.x.x以上(我升级到了V12.18.4版本)。

参考链接:hexo与github结合

ssh连接中断的问题

Mac 连接服务器保持ssh会话:https://mp.weixin.qq.com/s/ylMPjyVnmptcEq12Gi-Nzg

想要通过 xxx.com 和 www.xxx.com 都能正常访问,怎么做

问:想要通过 xxx.com 和 www.xxx.com 都能正常访问博客网站,应该怎么做?

解决办法如下:

需要在dns域名解析中,同时添加两条指向公网ip的主机记录:一条@记录,一条www记录。如下:

添加完这两条记录后,通过 xxx.comwww.xxx.com,都可以访问你的服务器。

在支持https的情况下,如果你只添加了www记录,那么,只能通过以下网址访问:

1
2
3
www.qianguyihao.com
https://www.qianguyihao.com
http://www.qianguyihao.com

如果继续添加了@记录,还可以通过一下网址访问:

1
2
3
https://qianguyihao.com
http://qianguyihao.com
qianguyihao.com

补充:为了达到上面这个目标,nginx配置中,server_name只需要设置www.qianguyihao.com即可,不需要设置www.qianguyihao.com qianguyihao.com。不要多此一举。

参考链接:

参考链接

提到了如何将md文件进行管理。

迎来船新版本的Hexo+NexT

作者 Alliot
2023年9月1日 12:44

  自从 2017 年使用 Hexo+NexT 作为博客框架以来,已经过去好几个年头。就如前面那篇hexo使用Artalk评论系统 博客所言,由于 Alliot 之前对 NexT 主题与部分插件做了许多侵入式的魔改,基本没有对其做过日常的版本升级维护,因此,已经没有平滑升级的可能性。在一次插件失效的契机下,终于下定决心推倒重建。 本文记录了这一次重建的过程以及在维护模式上相比旧版本的改进。

Hexo博客神器——Hexo便携版

作者 Aicsuk
2022年11月24日 13:12

前言

博主最近买了台新电脑,原来装好Hexo环境的老电脑目前就没怎么用,又懒得重新换电脑部署,想着看看能不能实现两台电脑同步部署。结果研究了很久,发现网上的多端部署教程都选择将Hexo备份至Github仓库。因为我博客是部署在华为云服务器上的,感觉再备份至Github仓库的话会很麻烦,所有突发奇想看看能不能实现便携式Hexo。

终于,我找到了这款Hexo懒人包,里面包含了Node.js便携版和Git便携版,理论上任何Windows系统的电脑都能直接使用,免去了新电脑Node.js和Git的安装和配置。

懒人包简介

PortableHexo

其中,hexo文件夹是博客源文件所在文件夹,可直接将已有博客文件全部复制到此文件夹内,也可重新安装Hexo。home文件夹和support文件夹不用管。

其余批处理文件顾名思义,如果是重新安装的Hexo博客,需要执行一下配置Github部署和配置基本信息,如果是原有博客文件复制过来的就不用执行。

最后

懒人包配置好后,可将懒人包放在U盘里,直接在U盘写作部署;也可以将懒人包压缩后放到网盘里。

以后不管在哪、用哪台电脑,只要U盘在,就能随时随地写东西了。🤣

这篇文章就是在新电脑上用U盘写的。

懒人包地址:Hexo懒人包5.0版本百度网盘(提取码3n1b)

hexo使用Artalk评论系统

作者 Alliot
2022年7月24日 13:10

  前些日子逛 GitHub 时发现一个比较满足强迫症要求的评论系统 Artalk,功能完善且带有支持自托管的后台,恰逢 LeanCloud 政策变更, 忍受了 LeanCloud 好几年的资源与其他限制, 终于这次,我准备休掉它换 Artalk 了, 毕竟自建博客本就是为了不受到各种平台的限制。

Hexo笔记——解决Shoka主题评论系统表情加载失败的问题

作者 Aicsuk
2022年9月16日 16:32

近期将博客换成Hexo之后,最开始是部署在Github Pages上面,访问时一切正常。后面觉得Github Pages访问速度时快时慢,边重新部署在国内的华为云服务器上,这时问题就出来了,评论系统里面的表情图片正常情况下加载不出来,要搭梯子才行。表情加载失败

后来参考了ReverseSacle大佬关于[Shoka主题功能的一些补充介绍](Hexo-Shoka主题功能介绍补充点 | ReverseSacle-Blog = 逆转天平 = 执着过去的人,无法迈向未来)一文,并请教了ReverseSacle大佬后才了解到,shoka 主题使用的是 Valine-Admin 魔改评论系统,基本上都使用了 Jsdelivr 的资源,并由于国内的服务器无法访问资源才导致的表情加载失败。

为防止自己以后会忘记,特此记录下解决过程。

Vercel 反代 Jsdelivr 的加速链接

这一步,ReverseSacle大佬的文章中是以 Windows10 系统为例,但我习惯使用 Linux 系统,所以此次我使用 Centos 8.2 系统为例。

  • 安装 Node.js

    1
    2
    3
    4
    5
    yum install update
    yum install nodejs
    yum install npm
    npm install -g n
    n lts
  • 安装 vercel

    1
    npm install -g vercel
  • 安装完 vercel 后,输入 vercel login ,会让你选择登陆 vercel 的方式(选择的位置以 等待输入光标 为准, Enter 键确认,具体依情况选择),之后会跳出登入页面如图所示
    这里我使用的是邮箱登陆,会出现下图中的情况,这是 vercel 给你登陆邮箱发送了确认邮件,需要你在邮件中点击确认链接才能登陆邮箱登陆

  • 新建一个名为 jd_gh 文件夹 (名字自定义),进入到 jd_gh 文件夹中,新建一个 jd_gh.json 文件 (名字自定义)

    1
    2
    3
    mkdir jd_gh
    cd jd_gh
    touch jd_gh.json
  • 文本编辑器 打开 jd_gh.json 文件并输入下方反代代码

    1
    2
    3
    4
    5
    6
    {
    "version": 2,
    "routes": [
    {"src": "/(.*)","dest": "https://cdn.jsdelivr.net/$1"}
    ]
    }
  • 最后输入命令 vercel -A jd_gh.json --prod 来在 vercel 上部署

  • ++注意 what's your project's name? 这个提示,此处是提示输入你部署项目所需要的名称 (按喜好来定就行了,另外这里不支持特殊字符, - 号除外),其他的选项按下方图片提示来选择即可++{.dot}直接使用ReverseSacle大佬的图

  • 最后,进入 Vercel 官网,登入后可以看到刚刚创建的项目,点击项目,进入后记录下 DOMAINS 处的链接,也可以绑定自己的域名使用

解决评论区表情图片加载失败问题

  • MiniValine (Github) 下载 MiniValine.min.js 文件,并将 MiniValine.min.js 文件放入到 hexo 根目录的 ./themes/shoka/source/js 文件夹中

  • 打开 MiniValine.min.js 文件,找到 VERSION="4.2.2" 这一项,将 t.EUrl 后链接中的XXX替换为刚刚记录的 DOMAINS 地址或自己绑定的域名

    1
    2
    3
    4
    5
    6
    7
    8
    t.VERSION = "4.2.2",
    t.GBUrl = "https://gravatar.loli.net/avatar/",
    t.EUrl = ["https://xxxx/npm/alus@latest",
    "https://xxxx/gh/MiniValine/qq@master",
    "https://xxxx/gh/MiniValine/Bilibilis@master",
    "https://xxxx/gh/MiniValine/tieba@master",
    "https://xxxx/gh/MiniValine/twemoji@master",
    "https://xxxx/gh/MiniValine/weibo@master"]
  • 打开 hexo 根目录 ./themes/shoka/_config.yml 文件,滑倒最后,找到 valine 元素,将其参数设为 https://博客域名/js/MiniValine.min.js

  • 最后修改 ./themes/shoka/source/js/_app/utils.js文件第26~35行处

    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
    //将此代码if(str.indexOf('npm')>-1||str.indexOf('gh')>-1||str.indexOf('combine')>-1)
    //拆分为下面的代码
    if(str.indexOf('npm')>-1||str.indexOf('combine')>-1)
    return "https://cdn.jsdelivr.net/" + str

    if(str.indexOf('js')>-1)
    return str

    if(str.indexOf('gh')>-1)
    return "https://cdn.jsdelivr.net/" + str

    //代码示例
    const assetUrl = function(asset, type) {
    var str = CONFIG[asset][type]

    if(str.indexOf('npm')>-1||str.indexOf('combine')>-1)
    return "https://cdn.jsdelivr.net/" + str

    if(str.indexOf('js')>-1)
    return str

    if(str.indexOf('gh')>-1)
    return "https://cdn.jsdelivr.net/" + str

    return statics + str;
    }

叒换了博客程序——记录Hexo搭建、配置、部署到云服务器的全过程

作者 Aicsuk
2022年9月14日 15:21

最近因为疫情原因,天天在家里也无聊得很,想着没事就试着折腾一下Hexo。

刚开始还不会整Hexo博客,感觉要比Typecho要麻烦的多。经过两天的学习操作,终于建好了Hexo,本着建好了就不浪费的原则,决定以后就用Hexo了。

目前博客程序为Hexo,使用Theme.Shoka主题,部署在华为云服务器上。

现在记录一下这个Hexo博客从搭建、配置和部署到云服务器的整个过程,免得以后自己忘了。

Hexo本地安装

环境准备

  • 下载安装Node.js(Node.js 版本需不低于 10.13,Node自带npm)
  • 下载安装Git

安装Hexo

  • 在自己喜欢的位置新建Hexo文件夹
  • 进入新建的Hexo文件夹,右键点击打开Git Bash Here
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #在Hexo目录下安装Hexo
    npm install -g hexo-cli
    #检测Hexo是否安装成功
    hexo -v
    #初始化Hexo,并新建blog文件夹
    hexo init blog
    #转到刚初始化的blog文件夹下,安装npm依赖项,并生成静态文件
    cd blog
    npm install
    hexo g
    #启动Hexo服务器
    hexo s
  • 访问http://localhost:4000,出现Hexo页面

安装Shoka主题

  • 安装主题

    1
    2
    # cd your-blog
    git clone https://github.com/amehime/hexo-theme-shoka.git ./themes/shoka
  • 安装主题依赖插件

  • 修改Hexo博客配置文件_config.yml

    1
    theme: Shoka
  • 生成静态文件并发布

    1
    2
    hexo g
    hexo s
  • 访问http://localhost:4000 进行预览,没问题的情况下就可以将博客部署到服务器上了。

部署到云服务器

  • 在自己的电脑上生成 Git 密钥

    1
    ssh-keygen -C "your@mail.com"

    一路回车,这时你应该可以在 ~/.ssh/ 目录下看到两个刚刚生成好的密钥文件:
    1. 公钥:id_rsa.pub
    2. 私钥:id_rsa
    我们一会需要把公钥的内容拷贝到服务器上

  • 服务器环境配置
    一般刚重装完系统的云服务器非常纯净,什么也没有,所以我们要一点点安装我们所需的内容
    1. Git
    2. Nginx

  • Git的安装和配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    #首先需要安装包的依赖
    yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel
    yum install gcc perl-ExtUtils-MakeMaker
    #进入指定目录(这里选择 `usr/local/src`)选择最新版本 [Git](https://mirrors.edge.kernel.org/pub/software/scm/git/) (这里使用 `2.37.3`)下载并解压
    cd /usr/local/src
    wget https://mirrors.edge.kernel.org/pub/software/scm/git/git-2.37.3.tar.gz
    tar -zxvf git-2.37.3.tar.gz
    #解压出来的 Git 文件都是源文件,我们需要进行编译,进入 Git 解压目录,进行编译和安装, 安装位置(这里选择 `usr/local/git`), 整个过程可能需要一定等待。
    cd git-2.37.3
    make prefix=/usr/local/git all
    make prefix=/usr/local/git install
    #安装好后,我们需要配置环境变量,打开环境变量配置文件:
    vim /etc/profile
    #在文件底部添加 Git 安装目录信息。
    PATH=$PATH:/usr/local/git/bin
    export PATH
    #刷新环境变量,使之生效
    source /etc/profile
    #此时 Git 应该已经安装完成,可以查看 Git 版本号是否和你指定的版本一样:
    git --version
  • Git 新用户与配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #创建 git 用户和密码
    adduser git
    passwd git
    #将 git 用户添加到 sudoers 文件中
    chmod 740 /etc/sudoers
    vim /etc/sudoers
    #在Allow root to run any commands anywhere下面添加 git 用户内容, 保存并退出
    git ALL=(ALL) ALL
    #修改回 sudoers 文件权限
    chmod 400 /etc/sudoers
  • 测试
    通过Git Bash Here将上面本地生成的 id_rsa.pub 公钥内容拷贝到远端服务器, 这个命令会默认在远端服务器 git 用户主目录下生成 authorized_keys 文件 (~/.ssh/authorized_keys), 其中 server_ip 为公网 IP,不是内部 IP,别拷贝错了

    1
    ssh-copy-id -i ~/.ssh/id_rsa.pub git@server_ip

    此时可以通过 ssh 命令(加上 -v 命令,可以输出详细 log)测试连接

    1
    ssh -v git@server_ip

博客网站目录配置

  • 创建博客网站目录位置
    1
    2
    3
    4
    #为博客网站创建根目录(这里选择 `/home/hexo`)
    mkdir /home/hexo
    #赋予 git 用户权限
    chown git:git -R /home/hexo
  • 自动化配置
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
      #指定目录位置(这里选择 git 用户主目录 `/home/git`)创建一个名为 `blog.git` 的 `bare repo`
    cd /home/git
    git init --bare blog.git
    #同样赋予 git 用户相应权限
    chown git:git -R blog.git
    #使用自动化配置,自然是要用到 Git 的钩子函数,这里我们需要 `post-receive`,在博客 hooks 目录下新建该文件:
    vim blog.git/hooks/post-receive
    #然后添加如下内容(注意目录匹配),保存并退出:
    #!/bin/sh
    git --work-tree=/home/hexo --git-dir=/home/git/blog.git checkout -f
    #最后,赋予这个文件可执行权限
    chmod +x /home/git/blog.git/hooks/post-receive
    #接下来,创建个链接,以防后续 deploy 过程出错
    sudo ln -s /usr/local/git/bin/git-receive-pack /usr/bin/git-receive-pack

Nginx 安装和配置

  • 安装

    1
    2
    yum install -y nginx
    systemctl start nginx.service

    这时,在浏览器中输入公网 IP 地址,应该可以看到 Nginx 默认的欢迎界面

  • 配置

    这里配置 Nginx,将所有 Http 请求都重定向为 Https 请求,这就需要我们有 SSL 证书。
    通过 scp 命令将 SSL 证书拷贝到远端服务器, 正常应该将 Nginx 的证书存放在 /etc/nginx/cert 目录下,这里选择存放在 /home/ssl_cert 下(如果目录不存在,请自行创建)

    1
    2
    scp ~/路径/证书.key root@server_ip:/home/ssl_cert
    scp ~/路径/证书.pem root@server_ip:/home/ssl_cert

    然后打开 Nginx 的配置文件进行整体配置

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
server{
listen 80;
server_name dayarch.top; # 个人域名
rewrite ^(.*)$ https://$server_name$1 permanent; # 重定向
}

server {
listen 443;
server_name dayarch.top; # 个人域名
ssl on;
ssl_certificate /路径/证书.pem; # .pem 证书
ssl_certificate_key /路径/证书.key; # .key 证书
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;

location / {
root /home/hexo; # 博客网站主目录
index index.php index.html index.htm;
}

error_page 404 /404.html;
location = /404.html {
root /usr/share/nginx/html;
}

error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}

通过 nginx -t 命令进行检查,一切正常会输出如下结果:

1
2
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

重启 Nginx 服务

1
systemctl restart nginx.service

至此,所有的准备工作都做完了,接下来,我们需要做一些博客配置

本地博客配置修改

我们需要将远端服务器的 Git 仓库信息配置到 Hexo 站点配置文件(_config.yml)中

1
2
3
4
deploy:
- type: git
repo: git@server_ip:/home/git/blog.git
branch: master

陆续执行 hexo 的命令进行部署

1
2
3
hexo clean
hexo g
hexo d

至此,距离成功,我们只差最后一步

域名解析

配置好域名解析,将其指向云服务器的公网地址即可。

Hexo 常见问题解决方案

作者 anran758
2020年9月27日 21:12

记录 Hexo 升级或使用时遇到的问题和一些解决方案。

TypeError: config._d.getTime is not a function

经过排查,本次发生错误是由 hexo-related-popular-posts 引发,在该库源码中使用 moment 初始化 list.date 导致了错误。 list.date 通过打印值可以看到是一个 moment 对象,但这个 moment 对象并不规范或者说可能在某处修改了这个 moment 对象的值。

moment 内部初始化有一段逻辑是:

1
this._d = new Date(config._d != null ? config._d.getTime() : NaN);

这个 config 就是 moment(list.date) 传入的 list.date 的值。config._d 是一个时间类型的字符串,并不是 Date 类型,因此没有 getTime 的方法。

临时解决方法有两种,一是将 theme/next/_config.yml 中的 related_posts.params.isDate 设为 false,也就是推荐列表中不展示时间。

二是修改源码,做一层错误处理。从 node_modules 中打开文件(\node_modules\hexo-related-popular-posts\lib\list-json.js), 在编辑器中查找以下代码:

1
2
3
if (inOptions.isDate && list.date != '') {
ret.date = moment(list.date).format(config.date_format || 'YYYY-MM-DD')
}

修改为:

1
2
3
4
5
6
7
if (inOptions.isDate && list.date != '') {
try {
ret.date = moment(list.date).format(config.date_format || 'YYYY-MM-DD')
} catch(ex) {
ret.date = moment(list.date._d).format(config.date_format || 'YYYY-MM-DD')
}
}

上述只是临时的解决方案,由于不好确定是哪一方的原因,也不想继续耗费太多精力在上面。

错误日志如下,以供参考:

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
Unhandled rejection Template render error: (C:\Users\user\Desktop\project\blog\themes\next\layout\post.njk)
Template render error: (C:\Users\user\Desktop\project\blog\themes\next\layout\post.njk)
Template render error: (C:\Users\user\Desktop\project\blog\themes\next\layout\post.njk) [Line 19, Column 14]
Template render error: (C:\Users\user\Desktop\project\blog\themes\next\layout\post.njk)
Template render error: (C:\Users\user\Desktop\project\blog\themes\next\layout\_partials\head\head-unique.njk) [Line 10, Column 23]
Template render error: (C:\Users\user\Desktop\project\blog\themes\next\layout\post.njk) [Line 3, Column 3]
Template render error: (C:\Users\user\Desktop\project\blog\themes\next\layout\post.njk)
Template render error: (C:\Users\user\Desktop\project\blog\themes\next\layout\_partials\header\index.njk) [Line 6, Column 15]
Template render error: (C:\Users\user\Desktop\project\blog\themes\next\layout\post.njk)
Template render error: (C:\Users\user\Desktop\project\blog\themes\next\layout\_partials\header\sub-menu.njk) [Line 2, Column 29]
Template render error: (C:\Users\user\Desktop\project\blog\themes\next\layout\post.njk)
Template render error: (C:\Users\user\Desktop\project\blog\themes\next\layout\_partials\header\sub-menu.njk)
Template render error: (C:\Users\user\Desktop\project\blog\themes\next\layout\post.njk) [Line 5, Column 3]
Template render error: (C:\Users\user\Desktop\project\blog\themes\next\layout\post.njk) [Line 9, Column 12]
Template render error: (C:\Users\user\Desktop\project\blog\themes\next\layout\_macro\post.njk) [Line 214, Column 16]
Template render error: (C:\Users\user\Desktop\project\blog\themes\next\layout\_partials\post\post-related.njk)
TypeError: config._d.getTime is not a function
at Object._prettifyError (C:\Users\user\Desktop\project\blog\node_modules\nunjucks\src\lib.js:36:11)
at C:\Users\user\Desktop\project\blog\node_modules\nunjucks\src\environment.js:561:19
at Template.root [as rootRenderFunc] (eval at _compile (C:\Users\user\Desktop\project\blog\node_modules\nunjucks\src\environment.js:631:18), <anonymous>:45:3)
at Template.render (C:\Users\user\Desktop\project\blog\node_modules\nunjucks\src\environment.js:550:10)
at C:\Users\user\Desktop\project\blog\themes\next\scripts\renderer.js:35:29
at _View._compiled.locals [as _compiled] (C:\Users\user\Desktop\project\blog\node_modules\hexo\lib\theme\view.js:136:50)
at _View.render (C:\Users\user\Desktop\project\blog\node_modules\hexo\lib\theme\view.js:39:17)
at C:\Users\user\Desktop\project\blog\node_modules\hexo\lib\hexo\index.js:64:21
at tryCatcher (C:\Users\user\Desktop\project\blog\node_modules\bluebird\js\release\util.js:16:23)
at C:\Users\user\Desktop\project\blog\node_modules\bluebird\js\release\method.js:15:34
at RouteStream._read (C:\Users\user\Desktop\project\blog\node_modules\hexo\lib\hexo\router.js:47:5)
at RouteStream.Readable.read (_stream_readable.js:470:10)
at resume_ (_stream_readable.js:949:12)
at process._tickCallback (internal/process/next_tick.js:63:19)

Hexo blog 的升级与同步方案

作者 anran758
2019年11月2日 09:44

前一篇我们介绍了如何使用 Hexo 框架及 Next 主题搭建博客。这次来聊聊如何安全的更新博客与主题的版本。

next theme


早期写博客时笔者就有考虑过使用 git 来做版本控制,那时 github 私人仓库还没有免费开放,国内虽然有 coding 和码云这些平台有开放少量的私人仓库,但由于懒得折腾就选了最方便同步的 OneDrive(因为它只需将文件夹移入就可以实现跨设备共享)。

后来笔者因为工作的原因,需要在多设备中频繁切换,这种简单同步方式就会暴露出一些问题。比如说,在设备 A 想对博客做一些自定义的修改,其中可能会动到依赖,但此时设备 B 的文件正在同步,那这样可能会导致文件不一致的问题。可能会将旧的文件重新同步过来,这可能会导致程序报错,还不易于排查。

冲突文件合并失败会额外添加如 index-anran758's MacBook Pro.js 之类的同名文件,并且发生冲突时是隐式的,你甚至不知道发生了冲突,这种体验使用不太友好。

因此 OneDrive 的同步方式适用于改动不会太大的文件。


如果你对 git 版本控制比较熟悉的话,那可以通过 git 对 blog 进行版本控制。

使用源码托管平台的话就如上文所说主要有这么几种选择:

国内的 gitee(码云)coding 是一个不错的选择,代码的上传于下载速度也比较可观。国外可以使用 github,github 的私人仓库是今年才开放无限制免费创建仓库数量的,缺点由于众所周知的问题,有时可能拉代码速度较慢。

笔者使用的是 github 作为源码托管,下文将要介绍的方法对于 git 仓库是通用,因此根据自身的喜好选择对应的平台。

博客托管

托管 blog 源码的步骤如下:

  1. 找到对应的平台,创建私人仓库(注意是 Private,不要将自己的私人配置也开源咯)。

  2. 仓库创建完毕后,得到仓库的地址。打开命令行,进入 /blog 目录下并输入命令:

    1
    2
    3
    4
    5
    6
    # 初始化 git 项目
    git init

    # 添加一个名为 origin 的 remote
    # your_repo_path 是你创建仓库得到的仓库地址
    git remote add origin your_repo_path
  3. 由于 /theme/next 本身也是一个仓库,git 无法提交嵌套仓库的文件夹,因此需要在 .gitignore 添加配置,忽略该文件夹

    1
    2
    # 其他忽略规则...
    themes/next/
  4. 提交代码

    1
    2
    3
    4
    5
    6
    # 提交代码
    git add .
    git commit -m "new: blog 数据开始进行版本控制"

    # 设置上游(-u)并推送至远程的 master 分支
    git push -u origin master
  5. 这样我们就完成了博客的源码托管。

主题托管

Next theme 官网介绍的安装方式如下:

1
2
3
4
5
# 进入 blog 目录
cd blog

# 言下之意就是将该库克隆到 themes 目录下的 next 文件夹中
git clone https://github.com/theme-next/hexo-theme-next themes/next

Next theme 7.0+ 版本中,主题嵌入了检查版本更新的代码,每当运行本地服务器时,都会进行检查版本号的更新。当有新的版本发布时会在命令行输出警告:

1
2
3
WARN  Your theme NexT is outdated. Current version: v7.4.2, latest version: v7.5.0
WARN Visit https://github.com/theme-next/hexo-theme-next/releases for more information.

这时你想体验 Next 的新特性的话可能会有点麻烦,因为原先我们在旧版本上修改了配置,或添加了一些自定义的布局。这将会造成代码冲突。

因此我们需要独立开两条分支:

  • master 分支是官方发布的正式版本,我们不去修改 master 分支的中的任何文件。
  • 另一条是我们自己创建的新分支,笔者命名为 customize, 言下之意为该分支含有我们自定义的修改,包括私人配置等。

除此之外,由于主题配置文件(theme/next/_config.yml)中含有某些应用的 appid 或者 secret,这些配置不应该被其他人随意看到以防冒名滥用。因此我们应该将该项目额外添加一个 remote 来保存我们的私人配置。 具体操作如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 此时已经下载到了主题文件夹

# 创建并切换新分支
git checkout -B customize

# 进行主题配置或其他修改操作

# 提交改动(未推送)
git add .
git commit -m "chg: 修改为自定义配置"

# 添加一个名为 userRepo(名字可以自己定义,只要自己能搞清是哪个来源即可) 的新 remote,
git remote add userRepo git@github.com:anran758/hexo-xxx-next.git

# 设置上游(即以后使用 git pull/status 时默认拉取 userRepo 源的 customize 分支),并推送指定 remote
git push -u userRepo customize

如此就完成了代码的追踪,以后使用 next 主题就不是从 hexo-theme-next 中获取了,而是我们自己的私人仓库 hexo-xxx-next 中获取,安装方式是一样的。

版本升级

Next

前文说过我们将源码托管的需求之一就是为了解决代码合并的问题,为了体验新版本的特性,我们需要将新版本的代码合并进我们的分支:

1
2
3
4
5
6
7
8
9
10
11
12
13
# 从 origin/master 获取最新版本的代码
# 理论上我们不修改 master 分支的代码不会发生冲突
git fetch origin
git pull --no-commit origin master

# 切换至 customize 分支
git checkout customize

# 检查本地是否有文件改动,有的话需要进行 commit 提交或者使用 git stash 藏起来
git status

# 合并代码
git merge master

我们最起码修改过 _config.yml,因此会发生冲突也不奇怪,有冲突咱们就解决冲突。

如果你使用 vscode 进行编码,侧边栏有一个源代码管理,打开它可以看到冲突的文件。

打开冲突的文件,判断冲突项确定要保留(删除)的代码,解决冲突后,提交到缓存区(git add .(file))。缓冲区有本次升级所涉及的代码,可以大致预览一下本次的更新都做了什么事

1
2
3
4
5
6
7
8
9
10
11
12
13
# 将缓冲区的文件提交至 commit
git commit -m "Merge release v(version) into customize branch"

# 提交代码
git push
# Counting objects: 99, done.
# Delta compression using up to 4 threads.
# Compressing objects: 100% (57/57), done.
# Writing objects: 100% (99/99), 12.86 KiB | 346.00 KiB/s, done.
# Total 99 (delta 71), reused 64 (delta 42)
# remote: Resolving deltas: 100% (71/71), completed with 41 local objects.
# To github.com:anran758/hexo-xxx-next.git
# 4a70c18..54805a2 customize -> customize

升级完后运行本地服务器最后会输出一条:

1
INFO  Congratulations! Your are using the latest version of theme NexT.

Hexo

若最新版本的 Hexo 引入了你想要的新功能,你想更新 Hexo 版本的话,首先确定版本号变动的是哪一位。

package.json 的版本号格式是数字由点分隔,如 主版本号.功能版本号.补丁版本号。若更新是主(大)版本号的话,则需要先修改 dependencies 依赖中 hexo 的主版本号,再输入 npm update

以下是 hexo@v3 更新为 hexo@v4 的示例:

1
2
3
4
5
6
7
{
// ...
"dependencies": {
+ "hexo": "^4.0.0",
- "hexo": "^3.9.0",
}
}

命令行输入:

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
$ npx hexo -v
hexo: 3.9.0
hexo-cli: 2.0.0
os: Darwin 17.7.0 darwin x64
node: 12.13.1
v8: 7.7.299.13-node.16
uv: 1.33.1
zlib: 1.2.11
brotli: 1.0.7
ares: 1.15.0
modules: 72
nghttp2: 1.39.2
napi: 5
llhttp: 1.1.4
http_parser: 2.8.0
openssl: 1.1.1d
cldr: 35.1
icu: 64.2
tz: 2019c
unicode: 12.1

$ npm update
+ hexo@4.2.0
added 71 packages from 90 contributors, updated 14 packages and moved 5 packages in 12.513s

$ npx hexo -v
hexo: 4.2.0
hexo-cli: 3.1.0
os: Darwin 17.7.0 darwin x64
node: 12.13.1
v8: 7.7.299.13-node.16
uv: 1.33.1
zlib: 1.2.11
brotli: 1.0.7
ares: 1.15.0
modules: 72
nghttp2: 1.39.2
napi: 5
llhttp: 1.1.4
http_parser: 2.8.0
openssl: 1.1.1d
cldr: 35.1
icu: 64.2
tz: 2019c
unicode: 12.1

若只是后面两位版本号有变更的话,仅需输入 npm update 即可。

总结

单单从升级版本来合并代码的角度来看,实际上本地 commit 也可以做这种事,将 commit 储存在本地(.git)中不提交远端也是没有问题的,OneDrive也可以完成同步。

但从安全和可调试的角度来看,OneDrive的同步方式存在一定风险(懒的代价)。使用 git 版本控制可以清晰看到每一次提交的修改,不会多出奇奇怪怪的东西。必要的时候还可以进行回滚,相对来说更安全。但这种方案需要使用者了解一定的 git 知识。

从操作步骤来看,使用的 git 同步方案会产生多个仓库,这些仓库一般是拥有权限的人才能查看(修改)源码。比如完成了本文中两个仓库源码同步后,在另一台设备初次同步的步骤是:

  1. 通过 git clone 下载 blog 本体。
  2. 通过 git clone 下载私人仓库 next theme/theme 目录下。
  3. 进入两个仓库内安装对应的依赖

以上可以在 blog 项目下的 package.json 设置 scripts,通过一条命令来完成这些事。

由此我们可以看到,相比 OneDrive 的懒人方案,git 方案的操作步骤会更繁琐。更新方式也从自动更新变成手动更新。

两者种方案各有利弊,具体采用什么方案就看朋友们的习惯啦~


本文涉及到的 git 命令都是可以在 git 速查方案 查找相应的解释。

从搭建到部署,快速构建一个私人博客

作者 anran758
2019年8月19日 00:33

有时候我们希望有一个受控的博客,来记录或分享一些东西。这个博客的主题内容由你自己来决定,可以是技术分享(编程、汉化分享等),也可以是生活感想。

本文将介绍一个可以迅速搭建并部署的受控博客。阅读本文前,希望你对以下知识点有所了解:

  • git(版本控制) 的基础使用
  • markdown 的使用

为什么要搭建博客

在线类博客有很多选择,为什么我们需要从零搭建新的博客呢?自己搭建的博客有什么好处吗?

首先,前文所提的 “博客受控”,指的就是能够自己控制的博客的样式、内容等,自己想怎么改就怎么改。

内容受控是指我们知道在线类的博客是受平台限制的,这意味着你所发表的内容是需要受审才能发出的,一些敏感的技术词汇,该篇文章都可能会被和谐或被删除。但在自己搭建博客就没有这样的问题,最起码能保留源文件。

其二,博客的样式是受控的。像著名在线博客CSDN上一些博主的文章确实是有学习参考的价值,但问题的是该站广告是在是太多了,字体和排版的阅读体验并不太好。但如果是自己搭建的博客的话,就可以自己着手优化这些问题。

但博客的搭建还需要我们从各方面考虑利弊。平台类博客会有相应的推荐系统,会对同类型文章相互引流,在 SEO 方面会做得比我们好。

个人搭建的博客,刚起步时的浏览量并不高,但是可以通过SEO等方式来逐步增加自己网站的权重。或者提高博客的质量和干货,读者认为文章有价值,自然会收藏起来形成熟客。

那么博客能写什么东西呢?在日常生活中,有很多知识点是呈碎片状,写博客的本质上就是对自己知识的一种梳理,然后再将这些知识分享出来,可能会有对这方面知识有疑惑,或者想找到解决方案,自身分享出来的东西能给读者做一定的参考。同时这也会是一个良性循环,因为分享的同时,你可能也需要去查询一些资料,同时也可以找到别人遇到过并分享出来的解决方案,是一个相互收益的过程。

我们的基本需求是梳理与分享,那么更应该把注意力放在内容本身,网站布局的排版样式等则是增加读者阅读体验的问题。因此我们可以使用现成的博客框架快速完成这些事。

博客框架有很多种选择,笔者选择的是 Hexo,因为它足够便捷优雅。

start

Hexo 依赖 Node.jsNPM包管理,Node.js 安装后一般会自带NPM

我们打开终端(Windows PowerShell / cmd.exebashmacOS 里的终端),输入以下命令:

1
2
3
4
5
6
7
8
9
10
# 检查 npm 是否安装成功
npm -v

# 安装 hexo cli,
# 如果安装速度过慢的话,可以安装国内的淘宝镜像
# 在命令行输入 ` npm install -g cnpm --registry=https://registry.npm.taobao.org`
npm install -g hexo-cli

# 检查 hexo 是否安装成功,并查看版本
hexo -v

依赖安装成功后,我们可以在命令行输入 hexo help 查看使用方式(描述是英文,示例部分笔者将其转为中文):

Usage: hexo <command>

commanddescription
help获取命令的帮助
init创建一个新的 Hexo 文件夹
version显示版本信息

使用 hexo help [command] 可以查看更多的信息, 如:

1
2
3
4
5
6
7
8
9
10
11
12
hexo help init
# Usage: hexo init [destination]

# Description(描述):
# 在指定的路径或当前目录中创建一个新的Hexo文件夹.

# Arguments(参数):
# destination 文件夹路径。 如果未指定,则在当前文件夹中初始化

# Options(选项):
# --no-clone 复制文件而不是从GitHub克隆
# --no-install 跳过 npm 依赖安装(默认初始化会自动装依赖)

全局选项:

optionsdescription
--config指定配置文件而不是使用默认的 _config.yml
--cwd指定 CWD
--debug显示终端中的所有详细消息
--draft显示草稿帖子
--safe禁用所有插件和脚本
--silent在控制台上隐藏输出

在官网 commands 中可以找到全部完整的解释。

建站

在终端上,我们可以看到有一个 init 的命令,我们可以使用这个命令来初始化 hexo 项目,但再建站之前我们需要先决定在哪里存放博客源代码。

我推荐使用如微软的 OneDrive(win10 系统自带)之类的云文件夹。你可以白嫖它 5G 的云储存空间。当你在设备A下修改了文件,它会自动同步到云端上。切换回设备B并登录账号后,它又会自动从云端下载数据,是一个便捷的方式。

但值得注意的是 OneDrive 毕竟是国外服务,由于众所周知的原因可能需要科学上网才能使用。该方式只是数据备份与同步的问题,不使用它也不会影响下文的构建。

1
2
3
4
5
6
7
8
9
10
11
# 如果你是 unix 系统的话,可以使用该命令查看当前路径
pwd
# /Users/anran/OneDrive

# 初始化文件夹名为 blog
hexo init blog
# INFO Cloning hexo-starter https://github.com/hexojs/hexo-starter.git
# other install info ...

# 进入文件夹
cd blog

安装完成后目录如下:

1
2
3
4
5
6
7
8
9
.
├── _config.yml (网站的配置信息)
├── package.json (应用依赖信息)
├── node_modules (依赖包)
├── scaffolds (模板文件)
├── source (资源文件夹是存放用户资源的地方)
| ├── _drafts (草稿文件夹,刚初始化时可能不存在)
| └── _posts (文章/帖子源码列表)
└── themes (主题)

配置

建站完成后我们需要进行 配置hexo 中主要有两项配置。一项是站点配置文件,路径为 /_config.yml。另一项是主题配置文件,路径是/themes/(下载的主题)/_config.yml

我们可以先在站点配置文件修改以下基础选项:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Hexo Configuration

# 网站主标题,SEO元素之一
title: blog

#网站副标题,可选
subtitle:

# 网站描述, SEO元素之一,用于告诉搜索引擎关于这个站点的描述
description: 分享生活、分享技术

# 网站的关键词,如:
keywords: Front end

# 网站作者
author: anran758

# 网站使用的语言, 由于 Hexo 具备多语言配置,默认为英文,我们需要修改回中文语言
language: zh-CN

启动

初始化项目后默认会安装相关的依赖,接着在命令行输入如下命令来运行博客

1
2
3
4
5
6
7
8
# 启动服务,默认端口为 4000,启动服务后可以在浏览器输入 `http://localhost:4000` 查看效果
hexo server

# or 简写方式
hexo s

# 还可以使用 -p, 指定 9000 端口
hexo s -p 9000

写作步骤

我们一般通过命令行来操作博客:

比如创建文章的方式如下: hexo new [layout] <title>

layout是指定布局,Hexo默认有postpagedraft 三种布局,它们分别对应不同的路径。我们也可以自定义布局,但实际页面会和post相同,都将储存到source/_posts文件夹。

按照我个人的写作习惯,通常写作步骤是:

  1. 创建草稿(drafts)
  2. 在草稿上进行写作
  3. 整理细节并在本地服务器上查看效果(server)
  4. 发布至正式的帖子上
  5. 生成静态文件并部署(后续讲)

创建草稿(drafts)

1
2
$ hexo new draft "My first post"
# INFO Created: ~/blog/source/_drafts/My-first-post.md

在初次创建草稿会生成一个名为 _drafts 的草稿文件夹,接着该文件夹下有一个我们刚刚创建的草稿,名为 My-first-post.mdmarkdown 文件,文件内容如下:

1
2
3
4
---
title: My first post
tags:
---

在本地服务器查看草稿(drafts)

我们可以启动本地服务器一边写作一边预览,但默认情况下草稿是不会被展示出来的,如果你想查看草稿的话,可以输入以下命令:

1
2
3
4
5
$ hexo s -p 9000 --draft
# INFO Start processing
# INFO Hexo is running at http://localhost:9000 . Press Ctrl+C to stop.

# 如果需要退出服务器,按住 control + c

发布草稿(publish)

如果我们在本地服务器上校队完草稿细节后,可以将草稿发布为文章,否则在后续生成博客静态文件时不会被打包出来:

1
2
3
4
# hexo publish [layout] <filename>
# 将草稿发布为文章
$ hexo publish post My-first-post
# INFO Published: ~/blog/source/_posts/My-first-post.md

输入命令后你可以发现发布的文章被转移到了source/_posts/上,这样就完成了本地的文章发布。

生成静态文件(generate)

Hexo框架的一项工作就是将源文件 markdown 最后生成为 HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 生成文件
$ hexo generate
# INFO Start processing
# INFO Files loaded in 275 ms
# INFO Generated: 2019/08/11/My-first-post/index.html
# INFO 1 files generated in 152 ms

# 简写形式
$ hexo g

# 监控文件变化,并生成静态文件
$ hexo g --watch

# 生成文件并部署(部署后面单独章节来讲解)
$ hexo g -d

主题

我们熟悉完博客系统的操作后,接下来就是美化博客。Hexo 支持主题,我们可以根据官网的创建主题教程自己来设计,也可以直接在主题商城 中找现成的主题。这里以笔者推荐的主题 Next 为例:

theme next

笔者一开始使用 next 主题时,版本才 5.x,当时仍有很多博客所需的东西没有集成。如今回头一看,发现 next 升级了好几个大版本。github 主题仓库也迁移至了 https://github.com/theme-next 里,乃至文档都有两个不同的版本。

新文档是采用它自身主题的一个scheme来建成,是全英文文档,可以保证信息资料是最新的。旧文档布局便于阅读,同时是中文文档,大多参数也能在该文档找到,但毕竟没有再过多的维护,建议还是以最新文档为参考。

安装主题可以通过git clone克隆至blog/theme/下:

1
2
3
4
5
6
7
8
$ pwd
# /Users/anran/OneDrive/Blog

# 启动主题前需要清除缓存与已部署的文件
$ hexo clean

# clone 主题
$ git clone https://github.com/iissnan/hexo-theme-next themes/next

接着在 站点配置文件(/_config.yml) 中启动 theme。再打开主题配置文件(/themes/next/_config.yml)选择 Scheme:

1
2
3
4
5
6
7
8
9
# _config.yml
- theme: landscape
+ theme: next

# /themes/next/_config.yml
# 提供三种模式
#scheme: Muse
#scheme: Mist
scheme: Pisces

评论、订阅、数据统计、SEO 等部分功能配置已经集成至 next 主题配置中,但大多还需要额外添加依赖还需要根据文档来配置。next 在主题配置中集成了由于配置自定义项过多,读者可以根据自己所需添加相应的统计、SEO 相关的 app key 等就不进一步展开讲。

部署

我们使用git进行部署,可以将网站部署至私人服务器、也可以部署到免费的github pages上。本文将介绍部署至github的方法,如果你还没有github账号的话,那你需要先注册一个账号

步骤如下:

  1. 访问github.com,点击sign up注册账号。

  2. 进入注册页,输入账号密码和邮箱,输入验证码!

  3. 选择免费用户

  4. 接着是关于github推荐服务的调查,当然你也可以跳过它.

  5. 验证完毕后,它会提示你创建一个仓库,这里我们先创建一个blog

  6. 复制仓库链接,copy 至 站点配置文件(/_config.yml)里。同时安装hexo-deployer-git的依赖:

    1
    npm install hexo-deployer-git --save
    1
    2
    3
    4
    5
    6
    7
    url: https://yourname.github.io/blog   # 修改为 github io 的地址
    root: /blog/ # 要将资源映射到仓库名

    deploy:
    type: git
    repo: https://github.com/yourname/blog.git # blog 的 git 地址
    branch: gh-pages # 发布至 gp-pages 分支,如果该分支不存在,就会自动创建它
  7. 接着开始部署。如果你还没配置git账号的话,它会提示你输入账号密码,输入正确的账号密码后就部署成功了。

    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
    # 或者使用`hexo d -g`, 两者是等价的效果
    hexo g -d

    # *** Please tell me who you are.

    # Run
    # git config --global user.email "you@example.com"
    # git config --global user.name "Your Name"

    # to set your account's default identity.
    # Omit --global to set the identity only in this repository.

    # fatal: unable to auto-detect email address (got '29625@DESKTOP-0R7P8H4.(none)')
    # Logon failed, use ctrl+c to cancel basic credential prompt.
    # Username for 'https://github.com': anran758
    INFO Start processing
    INFO Files loaded in 621 ms
    INFO 0 files generated in 424 ms
    INFO Deploying: git
    INFO Clearing .deploy_git folder...
    INFO Copying files from public folder...
    INFO Copying files from extend dirs...

    INFO Congratulations! Your are using the latest version of theme NexT.
    Enumerating objects: 131, done.
    Counting objects: 100% (131/131), done.
    Delta compression using up to 8 threads
    Compressing objects: 100% (91/91), done.
    Writing objects: 100% (131/131), 257.72 KiB | 2.48 MiB/s, done.
    Total 131 (delta 43), reused 0 (delta 0)
    remote: Resolving deltas: 100% (43/43), done.
    To https://github.com/yourname/blog.git
    * [new branch] HEAD -> gh-pages
    Branch 'master' set up to track remote branch 'gh-pages' from 'https://github.com/yourname/blog.git'.

    # 如果没有配置全局 git 账号的话可以先配置,不然下次部署还是会提示你输入账号密码
    git config --global user.email "you@example.com"
    git config --global user.name "Your Name"
  8. 接着在我们创建的blog下进入settings项,设置 github pagesgh-pages 也就是之前在配置里设置的分支即可。这样就可以在线上查看我们部署的状况啦~

优化与扩展

下面介绍一下文档中没有提到的相关问题与扩展。

本地搜索

next 有内置本地搜索的配置项,但文档上说明需要额外安装 hexo-generator-searchdb 这个依赖。但该项目现在已经被归档了,它还存在一些问题没有修复。你可以使用 hexo-generator-search 来代替它。接者在站点配置文件添加如下配置:

1
2
3
4
5
6
7
8
# Expansion: hexo-generator-search
# 站内搜索
# https://github.com/wzpan/hexo-generator-search
search:
path: search.xml
field: post
format: html
limit: 10000

在使用本地搜索功能时,你可能会遇到以下错误:

1
2
3
4
This page contains the following errors:
error on line 86 at column 35: Input is not proper UTF-8, indicate encoding !
Bytes: 0x08 0xE8 0xB7 0x9F
Below is a rendering of the page up to the first error.

出现这种错误原因大多是因为搜狗输入法带来的特殊字符串,我们在源码中替换它即可。打开编辑器(比如vscode),在全局搜索错误信息Bytes 第一个字节 /x08 替换为空。

github emoji

如果你希望在博客中支持 emoji 的话,你可以安装 hexo-filter-github-emojis

1
2
3
4
5
6
7
8
# Use Github Emojis
# Docs: https://github.com/crimx/hexo-filter-github-emojis
githubEmojis:
enable: true
className: github-emoji
unicode: false
styles:
localEmojis:

sitemap

为了让搜索引擎能找到我们的网站,我还需要给搜索引擎的网络蜘蛛提供站点地图文件

1
2
# hexo sitemap 生成器以及百度的 sitemap 生成器
npm install hexo-generator-sitemap hexo-generator-baidu-sitemap --save

依赖安装完后在站点配置文件中添加如下配置:

1
2
3
4
5
6
7
8
9
10
11
# Expansion: hexo-generator-sitemap
# generate sitemap.
# https://github.com/hexojs/hexo-generator-sitemap
sitemap:
path: sitemap.xml

# Expansion: hexo-generator-baidu-sitemap
# 针对百度进行优化的 sitemap,作者还是建议手动提交至百度会比较好
# https://github.com/coneycode/hexo-generator-baidu-sitemap
baidusitemap:
path: baidusitemap.xml

设置无分页的归档

如果你期望将归档目录在一页中全部加载出来,那么你可以添加如下配置:

1
2
3
4
5
# hexo-generator-archive
# 该插件默认内置于 hexo 中,只需参考文档添加配置即可
# https://github.com/hexojs/hexo-generator-archive
archive_generator:
per_page: 0

图片的引入

hexo 中引用图片主要有两种方式:

  • 在本地通过资源文件夹引入
  • 使用图床

在本地资源的引入,需要修改 _config.yml 的配置:

1
post_asset_folder: true

设置完选项后,以后每次使用 hexo new [layout] <title> 后就会生成一个同名的文件夹。然后可以使用 `

` 来引入图片资源:
1
2
3
4
<!-- 例如插入一个 banner 图,hexo 会自动寻找同名文件夹下的文件 -->
{% asset_img banner.png banner %}

这里是一段示例内容。

该方法的缺点是需要占用本地资源,如果你是使用 git 进行部署,因为使 .git 文件变大(即便删除了该文件,它还会存在 git 的 commit 信息中)。

第二种方式可以使用图床,免费图床有个问题就是服务可能会不稳定,风险不由自己掌控,相对没那么保险。但是它能节省空间,甚至在网络传输上下载速度更快。如果使用图床的话,可以尝试新浪微博图床,将插件下载至 chrome,登录后即可上传得到相应的 url.

README

默认情况下,将源码生成部署至服务器会将上一次生成的数据覆盖掉。如果你期望在 github上保留一个 README.md 给读者看说明的话,可以通过 _config.yml 来设置它:

1
skip_render: ['images/loading.gif', 'README.md']

外链音乐播放器插件

网易云音乐提供了一个外链音乐播放器,可以插入博客中,样式以及播放的歌单都是通过url控制的。我们稍微封装一下,添加如下代码:

/next/_config.yml
1
2
3
4
5
6
7
8
9
10
11
12
# 网易云音乐插件
# 控制台: https://music.163.com/#/outchain/0/{% music.id %}/m/use/html
# 网易云音乐插件默认提供三种模式,不同模式设有不同宽高,样式也可能会略有不同。
# 如果你想调整默认的宽高的话,可以设置 width | height 覆盖原先 modal 的宽度
# modal: 1(310 X 430) | 2(310 X 90) | 3(278 | 32)
music:
enable: true
id: 102842761 # 网易云分享的ID
autoplay: false # 是否开启自动播放
modal: 2 # 模式, 默认为 modal 2
# width: 310 # 宽度, 默认为 modal 2
# height: 90 # 高度, 默认为 modal 2

添加 netease-cloud-music.swig 模板:

/next/layout/_partials/sidebar/netease-cloud-music.swig
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
{##
# extend layout: 网易云音乐外链播放器
# @author anran758
#}
{%- if theme.music and theme.music.enable %}
{# default size #}
{%- set music_model = theme.music.modal or 2 %}
{%- set music_width = 310 %}
{%- set music_height = 90 %}
{%- set music_padding = 20 %}

{# default config #}
{%- set music_id = theme.music.id or 102842761 %}
{%- set music_auto = 0 %}
{%- if theme.music.autoplay %}
{%- set music_auto = 1 %}
{%- endif %}

{%- if theme.music.width %}
{%- set music_width = theme.music.width %}
{%- elif music_model === 1 or music_model === 2 %}
{%- set music_width = 310 %}
{%- elif music_model === 3 %}
{%- set music_width = 278 %}
{%- endif %}

{%- if theme.music.height %}
{%- set music_height = theme.music.height %}
{%- elif music_model === 1 %}
{%- set music_height = 430 %}
{%- elif music_model === 2 %}
{%- set music_height = 90 %}
{%- elif music_model === 3 %}
{%- set music_height = 32 %}
{%- endif %}

<iframe
frameborder="no"
border="0"
marginwidth="0"
marginheight="0"
width="{{ music_width + music_padding}}"
height="{{ music_height + music_padding }}"
src="//music.163.com/outchain/player?type=0&id={{ music_id }}&auto={{ music_auto }}&height={{ music_height }}"
style="margin: 10px 0 50px;"
></iframe>
{%- endif %}

layout/_macro/sidebar.swig 中插入模板:

layout/_macro/sidebar.swig
1
2
3
4
5
6
7
8
<div class="site-overview-wrap sidebar-panel">
{{ partial('_partials/sidebar/site-overview.swig', {}, {cache: theme.cache.enable}) }}

<!-- 插入下列代码 -->
{{ partial('_partials/sidebar/netease-cloud-music.swig', {}, {cache: theme.cache.enable}) }}

{{- next_inject('sidebar') }}
</div>

不过值得注意的是,虽然插件能用,但由于博客渲染的是多页面,如果是跳到了别的页面,原先播放状态就会被破坏,从用户体验来看,这个功能并不太实用。


Hexo 的介绍就说到这里了,虽然还有一些技巧相关的内容,如果有读者感兴趣的话到时候再深入讲吧~

如何优化 Hexo(静态博客)

2017年7月17日 00:00

hexo

是 Hexo + NexT 让我重拾笔杆子,感谢开发者们和维护者们。

🤖 YAML 教程

YAML 语言(/ˈjæməl/ )的基本规则:

  • 大小写敏感。
  • 使用缩进表示层级关系。
  • 缩进时不允许使用 Tab 键,只允许使用空格。
  • 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可。
  • # 表示注释,从这个字符一直到行尾,都会被解析器忽略。

🔧 优化 URL

默认的 URL 是 https://tingtalk.me/2019/08/17/Hexo使用技巧

  • 层级太深:斜杠太多不利于搜索引擎的抓取。
  • 包含中文:URL 只能使用英文、数字和连字符(hyphen)-。如果包含中文,分享出现的链接可能是 https://tingtalk.me/2019/08/17/Hexo%E4%BD%BF%E7%94%A8%E6%8A%80%E5%B7%A7,中文强制被转码成十六进制编码,又臭又长。

URL 很重要,确立 URL 之前要深思熟虑,一旦新文章发出后,请不要随意修改。

📂 以文件名称为 URL

  1. 修改站点配置文件 _config.ymlpermalink(永久链接)为 :name/

    # URLpermalink: :name/ 
  2. 把 Markdown 文档命名为 hexo-tips.md

    ---title: Hexo Tips  date: 2019-08-17  categories: 博客   ---让 Hexo 更优雅的小技巧。<!-- more -->## Permalink - 不要用中文- 大写字母用小写字母代替- 删除所有特殊字符,只用连字符;连字符代替空格- 尽可能简短,删除 the、a、an、for、and、if 、or 等虚词
  3. 优化之后的 URL 是 https://tingtalk.me/hexo-tips,简短有力,清晰明了。

⚙ 在 Front Matter 定义

  1. 不用修改站点配置文件 _config.ymlpermalink(永久链接)permalink: :year/:month/:day/:title/

  2. 每次在文章的 Front Matter 中加上 permalink 字段,例如 hexo-tips/,就会 覆盖文章网址,无视站点配置文件的 permalink 设置。

    ---title: Hexo Tips  date: 2019-08-17  categories: 博客  permalink: hexo-tips/---如果 Hexo 版本在 5.0 以上,hexo-tips 后面一定要加上斜线 /。<!-- more -->正文。
  3. 优化之后的 URL 是 https://tingtalk.me/hexo-tips。Front Matter 的 permalink 具有最高优先级,所以文件名是否一样,是否有中文,都没有关系。

以上 2 种设定 permalink 的方法,都可以在 _posts 创建分类(category)文件夹,例如把 hexo-tips.md 放在 _posts/website,方便管理文章。但 URL 中又不会包含 category,保持 URL 的简洁可爱。

不推荐使用插件 hexo-abbrlink 生成唯一永久链接,一串无意义的数字让 URL 变得不可读且不方便记忆。而且每次分享文章时,都要打开博客才能把网址复制出来。

🔗 关联阅读

🔧 优化分类

  1. 站点 _config.ymlcategory_map 增加一个 博客: blog 的分类

    ---category_map:  教程: tutorials  日志: diaries  生活: life  科学上网: bypass-gfw  数字生活: digital-life  排版: typography  博客: blog
  2. 在文章 Front Mattercategories: 直接用中文分类名 博客,就可以映射到 https://tingtalk.me/categories/blog/

    ---title: Hexo Tips  date: 2019-08-17  categories: 博客  ---

如果不在 category_map 定义 博客: blog,分享出去的链接就会是 https://tingtalk.me/categories/%E5%8D%9A%E5%AE%A2/,不雅观。

🐞 半角标点

如何显示正确的英文半角标点符号,不被错误显示成中文全角标点符号,请在站点配置文件加上如下语句:

# Fix issue: halfwidth quotation marks rendered to fullwidth## Reference: https://github.com/hexojs/hexo/issues/1981#issuecomment-229309844marked:  smartypants: false

🔒 文章加密

你可能需要写一些私密的博客,通过密码验证的方式让人不能随意浏览。为了解决这个问题, 让我们有请 hexo-blog-encrypt

但是解密速度好像差强人意,可能是因为我的电脑和手机性能不足的原因。

💾 托管服务器

🔺 Vercel

注册前,请把 GitHub 的 Primary email address 改为非 QQ 邮箱,GitLab 或 Bitbucket 同理,否则 Error:Sorry, we are unable to complete your signup.

👉 Netlify

2020 年 10 月超限了,只好切换到 Vercel。

重定向:在 hexo 分支 source 下新建 netlify.toml 文件:

[[redirects]]  from = "https://tingtalk.netlify.com/*"  to = "https://tingtalk.me/:splat"  status = 301  force = true

部署之后,tingtalk.netlify.com 即可重定向至 tingtalk.me,有利于 SEO。

🗺️ 站点地图

  1. 安装 hexo-generator-seo-friendly-sitemap
  2. Google Search Console 提交找点地图:https://tingtalk.me/sitemap.xml

🔍 Local Search

hexo-generator-searchdb: Seach data generator plugin for Hexo.

📰 RSS

hexo-generator-feed: Feed generator for Hexo.

🖼️ 把图片放在 _posts

hexo-asset-link: Convert base-relative asset links to root-relative ones, so that user can insert assets like images in markdown way.

教程:如何为 Hexo 博文加入图片

💚 修改 NexT

🖼️ 图片居中

最新的版本(Mimi)已默认居中,不必做以下设置。

  1. hexo-site\source 新建一个名为 _data 的文件夹。
  2. hexo-site\themes/next/source/css/_schemes/Mist_posts-expand.styl 复制到 _data,并把名字修改为 styles.styl
  3. 打开 _datastyles.styl,修改以下代码:
    .post-body img {   margin: 0 auto; }
  4. 打开主题配置文件 hexo-site\themes/next/_config.yml,取消对 styles.styl 的注释:
    custom_file_path:  #head: source/_data/head.njk  #header: source/_data/header.njk  #sidebar: source/_data/sidebar.njk  #postMeta: source/_data/post-meta.njk  #postBodyEnd: source/_data/post-body-end.njk  #footer: source/_data/footer.njk  #bodyEnd: source/_data/body-end.njk  #variable: source/_data/variables.styl  #mixin: source/_data/mixins.styl  style: source/_data/styles.styl

📖 阅读时长

hexo-symbols-count-time: Symbols count and time to read of articles plugin for Hexo.

⚡️ quicklink

quicklink: Faster subsequent page-loads by prefetching in-viewport links during idle time

在 Front-matter 中写法是:

quicklink: enable

🗞 Google AdSense

AdSense 代码:

<script data-ad-client="ca-pub-5917720111786469" async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>

参考资料:在 NexT 主题中接入 Google AdSense | Code Life

📡 连接 GitHub

先下载并安装 Git,然后 Win + S 打开搜索,输入 Git Bash,或者在电脑任意位置右键打开 Git Bash,然后根据 GitHub 账号,修改下面的命令并复制到 Git Bash,Enter:

git config --global user.name "ting-talk"git config --global user.email "******@gmail.com"ssh-keygen -t rsa -C "******@gmail.com"

出现:

Generating public/private rsa key pair.Enter file in which to save the key (/c/Users/***/.ssh/id_rsa):

不用处理,直接 Enter:

Created directory '/c/Users/***/.ssh'.Enter passphrase (empty for no passphrase):

不用处理,直接 Enter:

Enter same passphrase again:

不用处理,直接 Enter:

Your identification has been saved in /c/Users/***/.ssh/id_rsaYour public key has been saved in /c/Users/***/.ssh/id_rsa.pubThe key fingerprint is:SHA256:FehU/******gwvkE+kkm7******96CaYSoFo+****** ******@gmail.comThe key's randomart image is:+---[RSA 3072]----+|         +o..+   ||     . .o..o* + .||.. o . ..+ *o.+ o||E.o + . S ooo    ||.o o . . .o o    ||   .  o.o.o      ||    .. .oo       |+----[SHA256]-----+

登录 GitHub,依次点击右上角的头像 - Settings - SSH and GPG keys - New SSH key

Title 自定义即可。

Git Bash 输入:

cat ~/.ssh/id_rsa.pub

左键复制结果,粘贴在 Key 里,最后点击 Add SSH key

Git Bash 输入:

ssh -T git@github.com

Enter:

The authenticity of host 'github.com (13.229.188.59)' can't be established.RSA key fingerprint is SHA256:nThbg6******WGl7E1IGOCspRomTxdCARLviKw6E5SY8.Are you sure you want to continue connecting (yes/no/[fingerprint])? 

输入 yes,Enter:

Hi ting-talk! You've successfully authenticated, but GitHub does not provide shell access.

如果有你的 GitHub 用户名(Hi ting-talk!),则代表与 GitHub 连接成功。

More Tips不想使用全局用户?教你为 Hexo 博客单独配置指定的 git 用户 | Hui-Shao's Blog

🚀 推送到 GitHub

在博客文件夹,右键打开 Git Bash,复制以下命令(可能要删除主题的 .git):

git init

添加远程仓库:

git remote add origin git@github.com:ting-talk/blog.git

克隆远程仓库:

git clone git@github.com:ting-talk/blog.git

推送:

git add .git commit -m "first push"git push origin master

嫌麻烦的话,就借助脚本推送更新吧。

脚本一

  1. 在博客文件里,右键新建文本文档;
  2. 输入 git add . && git commit -m '更新' && git push origin master,保存,退出;
  3. 把后缀 .txt 改为 .gh,文件名自己定义,例如 git-push.sh

脚本二

  • hexo.sh:此脚本可以很方便执行各种 hexo 命令,开启后会一直保持会话,随时输入简短的命令去执行一系列操作,提高效率。

本地分支强制覆盖远程分支:

git push origin master --force

🎸 博客搭建

🍊 Gridea

一个静态博客写作客户端:适合喜欢安安静静写博客的人。

👨‍💻 Easy Hexo

轻松入门 Hexo:适合喜欢折腾博客的人。

累积布局偏移优化 CLS 完全指南

作者 折影轻梦
2023年9月16日 08:00

什么是布局偏移

一个十几秒的短视频解释清楚。

更详细的解释是:布局偏移指的是在网页上发生突然变化时,页面中的内容位置发生意外移动的现象。这种情况常常让人感到困扰,因为它会导致阅读中断或误操作。布局偏移通常是由于资源异步加载或动态添加到页面上的 DOM 元素导致的。可能的原因包括具有未知尺寸的图像或视频、字体与其备用字体渲染大小不同,或者第三方广告或小部件动态调整大小。

难受的是,网站在开发过程中的功能通常与用户体验有很大不同。个性化或第三方内容在开发中的行为通常与生产环境中不同,测试图像通常已经存在于开发者的浏览器缓存中,本地运行的 API 调用通常非常快,延迟几乎不可察觉。

什么是 CLS

累积布局偏移 CLS(Cumulative Layout Shift)是一个指标。

是对页面整个生命周期中发生的每个意外布局变化的最大布局变化分数的度量。

CLS 通过测量实际用户遇到布局偏移的频率来帮助解决布局偏移问题。它可以帮助开发者了解布局偏移在真实用户中发生的情况,从而采取相应的措施进行修复。

为什么要优化 CLS

布局偏移是一个非常影响用户体验的问题,通过上面那一个简短的视频也能理解。

布局偏移通常会导致意外点击、页面方向的迷失,最终导致用户受挫。用户往往不会逗留太久。有时也会使用户不按照预计的产品流程走。

通常优化好布局偏移能够很好的提高用户粘性、用户停留时间等指标。

Yahoo! JAPAN News 通过降低 CLS 0.2 分,得到如下成果。

如何降低 CLS

图片等媒体元素占位

在图像、视频等媒体资源元素中始终包含宽度和高度大小属性。或用 CSS 中的 min-heightaspect-ratio 或类似的方式保留所需的空间。

aspect-ratio

可以用来直接指定当前元素的比例。

https://developer.mozilla.org/zh-CN/docs/Web/CSS/aspect-ratio

对浏览器的支持:

padding-bottom

如果考虑浏览器支持问题仍然可以考虑使用目前一个被广泛接受的基解决方案 “Padding-Top Hack”。这个解决方案需要一个父元素和一个绝对型的子元素。然后计算出长宽比的百分比来设置为 padding-top。例如:

1
2
3
<div class="container">  <img class="media" src="..." alt="..."></div>
1
2
3
4
5
6
7
8
9
10
.container {  position: relative;  width: 100%;  padding-top: 56.25%; /* 16:9 Aspect Ratio */}.media {  position: absolute;  top: 0;}

使用不易产生偏移的 CSS

其中 transfrom 表现很好,以下举几个例子。
用例可以在这里找到:https://play.tailwindcss.com/26PxFA6UVI

zoom VS transform: scale

zoom 会撑大页面并向右偏移时,transform: scale 只是在原地放大。

margin VS transform: translate

margin 造成父元素变大,transform: translate 只是让当前元素移动。

border VS box-shadow

border 会撑起父元素,而 box-shadow 并不会。

小心你的懒加载

懒加载会引起布局的偏移,如果你在有懒加载长列表的里进行跳转,请小心!
无动画进行跳转,能够一定程度上避免该问题。

小心使用 transition: all

在页面首次加载或者跳转页面时,transition: all 可能会导致元素的 padding 等从参数为 0 开始渲染,照成页面的抖动。

这都是痛:
Commit:表格以及友情链接图标抖动
Commit:修复导航栏抖动问题

标签顺序导致的偏移问题

由于在移动端上优先展示主要内容,因此侧边栏的 markup 位于主要内容的后面;而在更大的屏幕上,则通过设置 CSS order 的方式进行排序,将主要内容移到中间(即第二列),伪代码如下:

1
2
3
4
5
6
7
8
9
export default function MainLayout(props) {  return (    <Container>      <Main className={css`@media screen and (min-width: breakpoint) { order: 0 }`} />      <Left className={css`@media screen and (min-width: breakpoint) { order: -1 }`} />      <Right className={css`@media screen and (min-width: breakpoint) { order: 1 }`} />    </Container>  )}

浏览器在首次绘制时并没有完整解析 DOM、只知道 <Main /> 的存在、但不知道 <Left /> 或者 <Right /> 的存在,才因此将 <Main /> 渲染进第一列而不是第二列;直到第二次绘制时,浏览器才将 <Main /> 渲染进第二列、将 <Left /> 渲染进第一列。

Chrome 并不是一次完整解析 HTML 的,在以下两种情况下,Chrome 会暂停解析、开始渲染和绘制:

  1. Chrome 解析器在读取了 65535 字节的 HTML 后暂停
  2. Chrome 在遇到 <script> 标签后,会继续读取约 50 个「Token」之后暂停

详细了解请看:优化博客的累计布局偏移(CLS)问题

网页跳转与前进后退缓存

默认情况下,所有浏览器都使用 bfcache,但由于各种原因,有些站点不适合使用 bfcache。有关如何测试和识别阻止 bfcache 使用的任何问题的更多详细信息,请阅读 bfcache 文章

在你离开后,bfcache 将页面保存在浏览器内存中很短的一段时间,所以如果你返回它们,那么它们将完全恢复为你离开时的样子。这意味着完全加载的页面立即可用,而不会出现任何变化。

现在的 SPA 应用也能很轻易的保证路由跳转页面布局的一致性。记住始终保持你的目录和导航栏在页面的固定位置。

字体

在下载和渲染网络字体之前,通常有两种处理方式:

  1. 使用网络字体替代备用字体(FOUT——未样式化文本的闪烁)。
  2. 使用备用字体显示“不可见”文本,直到网络字体可用并且文本可见(FOIT——不可见文本的闪烁)。

着两种方式都可能导致布局变化。即使文本是不可见的,它仍然使用备用字体进行布局。这意味着使用该字体的文本块以及周围的内容在网络字体加载时会发生布局变化,与 FOUT 的可见字体完全相同。

以下方法可以帮助你最小化这种问题:

  1. 使用 font-display: optional 可以避免重新布局,因为只有在初始布局时网络字体可用时才会使用它。
  2. 使用匹配度高的备用字体。例如,使用 font-family: "Google Sans", sans-serif; 将确保在加载"Google Sans"字体时使用浏览器的无衬线备用字体。如果只使用 font-family: "Google Sans" 而不指定备用字体,将使用默认字体,而在 Chrome 上默认字体是"Times",它是比默认无衬线字体的匹配度更差。
  3. 使用新的 size-adjustascent-overridedescent-overrideline-gap-override API 来尽量减小备用字体和网络字体之间的大小差异,详细信息请参阅“Improved font fallbacks”文章。
  4. 使用 Font Loading API 可以减少获取所需字体的时间。
  5. 使用 <link rel=preload> 尽早加载关键的网络字体。预加载的字体有更高的机会达到首次绘制,这样就不会发生布局变化。
  6. 阅读有关字体最佳实践的“Best practices for fonts”文章。

使用真正的骨架屏

骨架屏好坏示例

测量 CLS 分数

生产阶段

实验阶段

Lighthouse in DevTools

能够针对移动设备和桌面设备生成网页的实际性能报告,并能够提供关于如何改进相应网页的建议。

在本地开发期间从 DevTools 运行 Lighthouse 非常方便。

PageSpeed Insights

应该就是在线版的 Lighthouse。

Performance in DevTools

性能选项卡在 Chrome 的 DevTools 配置文件的所有页面行为在一段时间内记录。时间轴上会出现一个标记为“Experience”的图层,突出显示布局的变化和发生变化的元素。

Web Vitals extension

最好将 Web vital 扩展视为查找性能问题的抽查工具,而不是全面的调试工具——这是 Chrome 的 DevTools 中的性能选项卡的工作。

结语

作为一个对自己项目有较高要求的人,平常几乎都会接触到布局偏移优化或者 Lighthouse,只不过之前自己瞎折腾的时候还没有 CLS 这个概念,现在算是对 CLS 有了较为清晰的概念了。
CLS 作为一个非常基础的优化指标,在用户体验上非常重要,任何项目都应该针对 CLS 做优化。

如有勘误,请及时指出,感谢!

参考

  1. https://web.dev/cls/
  2. https://web.dev/optimize-cls
  3. https://developers.google.com/publisher-tag/guides/minimize-layout-shift
  4. https://web.dev/yahoo-japan-news/
  5. https://addyosmani.com/blog/infinite-scroll-without-layout-shifts/
  6. https://blog.skk.moe/post/fix-blog-cls/
  7. https://developer.mozilla.org/en-US/docs/Web/CSS/aspect-ratio

博客带给我什么?——博客重建7周年

作者 林海草原
2024年1月2日 19:24

自2016年12月29日博客重建以来,至今已走过7个年头。有句话叫“七年之痒”,博客重建7年后,写博客的热情因极度繁忙的工作而有所减退——本来想在2023年12月29日将这篇文章发出来,无奈闲暇时间太少,断断续续写到现在。然而,即便如此,我依然没有放弃长文写作。宁愿不写,我也不愿意将博客完全变成微博。如果没有这个信念,我也不会在2016年底选择重建博客。既然重建,那就把这个信念坚持到底。

博客带给我精神层面的提升

接受曾经的自己

博客重建伊始,我想督促自己戒掉智能手机成瘾,记录相应的心路历程。最终,博客建立的比较成功,但戒掉智能手机成瘾却失败了。

2018年,我开始记录自己的成长经历,名为《人生前三十年》。这个连载在2020年暂时停更,原因是这种记录方式并没有凸显我和家庭成员的性格成因,以及带给我的无穷伤害。我需要换一种方式去记录这一切,但由于工作的忙碌而无暇顾及。

我为何要去写《人生前三十年》呢?起因在2017年,我陷入有点严重的抑郁状态。当时的我,不知道问题的起源,受制于物质条件,我无法去进行昂贵的专业心理咨询。天无绝人之路,因缘和合之下,经过有相似经历之人的点拨,后购买心理问卷调查,我终于得以了解到,自己抑郁,以及一系列性格和行为缺陷及障碍的根源,完全来自于原生家庭。经过总结和思考,我决定以《人生前三十年》的名字将这一切记录下来。虽然文章没有写出自己想要的样子,但写作的过程极大缓解了我的痛苦,减轻了抑郁的折磨。

2019年6月,我去了当时赫赫有名的建立在安徽宣城的净土宗寺院“弘愿寺”。三天后,我离开寺院,此时我基本走出抑郁,能够正常工作和生活。从此以后,自己的性格有极大改善,虽然目前仍有缺陷——比如自己依然喜好争执——但已经和过去的自己完全不同,几乎已经彻底脱胎换骨。重建后的博客,记录了这整个历程。

这便是博客重建带给我的巨大帮助之一。精神层面的提升,对我非常重要,彻底改变了我的人生走向。如果没有通过在博客上写作,进而发生这些改变,也许我已被埋在黄土之下。

陪伴自己成长

在博客的“关于”页面,我列出了自己使用独立博客的历史。里面提到,2013年9月16日博客因主机垮掉而倒闭之时,有个唯一的数据库备份。博文数据现在完整地放在wordpress.com上,但我从来没有去回顾。直到前两个月,我在进行测试时(下文会提到我在测试什么),将数据又恢复了一次,保存在了测试站上。工作之余稀少的休息时间,我间歇性的将以前的文章通读了一遍。

以前的文章,与现在的对比非常明显。不仅透露出曾经的幼稚,还凸显出来因原生家庭环境影响而出现的性格问题,及进而导致的语言表达问题。另外,观察世界、思考问题及写作方面的思维,已在接受学校教育之后被固化,这大大限制了我从多角度、多方面去观察世界和自身,这种情况在文章里同样表现的非常明显。

所幸的是,我终于在2018年以后认识到了这些问题。在摆脱原生家庭影响方面,我做的还算是成功;摆脱思维固化方面,仍在努力挣扎。我知道,在背后那只“手”的操纵下,想做到摆脱思维固化是非常难的。但既然已经意识到这个问题了,我必须去解决掉它。

在这里,我把其中一个事情单独拎出来说说。以后我也许单独撰文回顾这件事,因此本文中我只用寥寥数语讲述一下,希望您不要把焦点全部放在这件事上。2010年时,我喜欢过一个女生,暧昧了两个月以后,她拒绝了我。大半年以后我才走出来,因为她,我写了五篇文章。现在回头看看,当初的情执,反映的问题恰恰是原生家庭环境塑造了我缺乏关爱、没有安全感、缺乏调节情绪的能力和控制欲强的性格。这个女生在2021年结婚生子,她的老公不是我,而我也从这恶劣的性格中解脱了出来。

这些成长的过程,被我用博客记录了下来。博客的存在,陪伴了我的成长。

只是2016年之前的数据,我永远都不会再公开出来。存储这些文章的wordpress.com站点,被我设置成了私密。

反抗思想的“被迫”退化

在《警惕背后的那只手——读和菜头〈重开博客〉有感》这篇文章中,我提到,背后的那只“手”在操纵着我们能够从纸质材料和互联网中获取的一切信息类型和内容,更是操纵我们只能获取他们编撰或是杜撰的一切知识、思想和情绪。在他们的操纵下,绝大多数人会愈发心浮气躁,进而丧失逻辑思维和思考能力。即便是热爱写作的人,除了会发生前文提到的观察世界、思考问题和写作方面的思维被禁锢的问题之外,还存在这些能力的退化,首先表现出的便是阅读和写作长文能力的丧失。

大秦从未消亡,法家的理论体系对治理我们的人来说从未“过时”。对治理我们的人来说,我们出现这些恶性变化对他们和他们的后人绝对利好;对我们来说,这导致我们失去了最基本的学习能力,进而会丧失重要的生活能力,沦为一个丢失灵魂的行尸走肉。

有一些被操纵的人,意识不到这些不说,反而仗着手里的话语权去替那只“手”辩护,再试图让意志不坚定或没有主观意志的人堕入更深层的思想地狱。

如果换在过去,受原生家庭影响,我是个讨好型人格,没有任何主见,别人说什么我都相信,我能想象到自己早已踏上通往奴役之路的样子。通过不断的思考、观察和写作,如今虽然也在这条路上,但行走缓慢,希望永远不会走到终点。

博客带给我技术上的进步

折腾,还是折腾

我曾多次在博客上说“多思考,少折腾”,但只要有闲暇时间,我便收不住这颗折腾的心。

这些年,注册过数不清的BSP,折腾过独立搭建Typecho、Zblog PHP、MovableType、Flatpress(文本数据库)、Ghost、PivotX(已停止开发)、Farbox 2.0,以及已经记不住名字的程序。前些日子,我利用一个随时可能跑路的个人主机商的月付版高配VPS折腾了消耗运行内存很严重的Halo程序。有的程序折腾的掉头发,有的则能做到熟练使用。

我已熟练掌握如何利用Netlify、Vercel和CloudFlare Pages在线编译Jekyll、Hexo和Hugo,而不是本地生成html再上传。

我在自己的VPS上用过Ubuntu、Debian、Centos和AlmaLinux操作系统,在VPS上用过纯命令行操作的LAMP和2023年发生挂马事件的LNMP,也用过宝塔、1Panel、AMH、WDCP、WebAdmin等服务器控制面板。

现在,我将目标放在使用Litespeed环境、Mariadb数据库的CyberPanel面板。我的两台VPS分别在跑OpenLitespeed和已开通Starter Plan(免费)的Litespeed Enterprise。

我曾发布过3个Typecho主题,分别是DiaryWriteSimple,修改并发布了Typecho的目录树插件

我曾魔改几个WordPress主题,包括现在自己在用、啊呜喵在用的,以及几个在测试站上欣赏的。手中还有一个花3块钱购买的盗版付费WordPress主题(原价59美元,促销价29美元,这两个价格均为一次性买断,源码授权协议为GPL v2),由于不是正常购买的,所以没有在这个博客中使用,只是在测试站玩了一下。

我还曾无偿帮助过几位博友建立、维护自己的博客。

在折腾的过程中,虽然远达不到精通的程度,但还是了解了不少东西,促使我能够基本独立进行博客的建立和维护,还能帮助博友解决一些常见的基础问题。在技术层面之外,与人心有关的种种,我也深刻领悟了——我在求助技术问题时,曾被少部分博主嘲讽,特别是折腾Bitcron期间;当思想本可以碰撞出火花时,极个别博主却不想真心讨论问题,只想让你接受,只想教育你,只想证明你是错的,在找不到理由时,便直接进行人身攻击。可又能怎么样?始终没能阻止我技术和思想的成长。

折腾是我的爱好,但我不会将它变成职业。有位WordPress免费主题开发者的前车之鉴便是如此。

博客运营的备用选择

经过折腾,我可以做到不拘泥于某个特定的服务,某个特定的技术去维护博客。假如,提供服务的主机商倒闭了,或服务质量大幅度下降,可以立刻迁移;某个著名的服务器控制面板加入了后门(懂得都懂),可以立刻使用其他的面板;博客程序能做到无缝切换,不损失任何数据……

为了博客能顺利的维护下去,我准备了备选方案。

前面提到,我为了测试而恢复了旧的博客数据。我测试的,正是上文提到的Litespeed Enterprise。我花费0元购买了Litespeed Enterprise的Starter Plan,复刻了与目前所用虚拟主机完全一致的服务质量和使用体验。如果目前的虚拟主机不再使用,我可以在自己的VPS上独立托管这个博客。

对于使用Litespeed Enterprise的虚拟主机,或者专业的WordPress Hosting,也有备选,虽然花销会比目前使用的虚拟主机高,但依然低于使用VPS的费用。

等待天明

影视节目制作人季业曾说过这样一段话:

如果天总也不亮,那就摸黑过生活;如果发出声音是危险的,那就保持沉默;如果自觉无力发光,那就别去照亮别人。但是——但是:不要习惯了黑暗就为黑暗辩护;不要为自己的苟且而得意洋洋;不要嘲讽那些比自己更勇敢、更有热量的人们。可以卑微如尘土,不可扭曲如蛆虫。

摸黑生存并不可怕,可怕的是为黑暗辩护;同样可怕的是,身处黑暗却不自知,以至于双目失明。

我想起这样两类人:

第一类人,代表之一便是斯维拉娜·亚历塞维奇在《二手时代》中记录的,那些在罪恶的时代结束之后反而仓皇失措的人。

第二类人,代表之一则是东晋、姚秦时期著名高僧鸠摩罗什。从公元382年开始,他经历了人生至暗的20余年,但他依然没有放弃信仰和信念,厚积薄发,最终成为一代高僧,译经三十五部,广为流传到今天。

我正在向鸠摩罗什及以他为代表的第二类人学习。在至暗时刻,我一直试图点燃烛光,哪怕再微弱,也要照亮内心。如果能唤醒他人,那便是功德无量。我相信,天亮之前是最黑暗的时刻,熬过这一刻便是黎明的曙光。我会耐心守护心中的烛火,拼尽全力等待天明。

❌
❌