本博客基于Hexo 框架与Butterfly 主题。
安装Hexo框架与Butterfly主题安装Hexo的命令行,这里选择全局安装,因为后面需要多次使用到
安装好Hexo的CLI后接下来就是初始化你的站点啦,在合适的位置建立博客站点文件夹,名字随意,我用blog
文件夹
1 2 3 hexo init <folder> cd <folder>npm install
PS:这里会使用npm
安装需要的包,鉴于国内网络环境,自行安装cnpm
或者yarn
工具
到这基本的Hexo博客框架已经搭建好了,可以用npx hexo g && npx hexo s
命令启动一个本地server来查看网站啦
接下来安装Butterfly主题
1 npm install hexo-theme-butterfly
网上有的教程使用git clone
直接将主题clone到theme文件夹下,并且随后的美化、优化环节会去修改主题源码,这样后面就无法直接升级主题了,需要对修改进行合并,所以这了不使用常用的方法。有一点需要注意npm
安装方法需要Hexo版本5.0.0以上,并且不会在themes
目录下生成文件。
配置文件说明由于采用了npm
的安装方式,无法直接修改主题文件,所以不熟悉的人可能在这卡很久。Hexo的配置文件为_config.yml
,Butterfly的配置文件为_config.butterfly.yml
,这两个文件都需要放在博客根目录。Hexo的配置在官网文档 可以查看,而Butterfly的详细配置就很隐蔽了,官网也并不是很容易找到,其实Butterfly作者有写默认的配置模板node_modules/hexo-theme-butterfly/_config.yml
,需要什么可以直接去里面找但是不要修改
常规配置 _config.yml此文件是Hexo的配置文件,会自动生成。标题等的按个人情况填写,不明白的查阅官网文档 即可,建议以下三个字段按如下填写
1 2 3 4 language: zh-CN timezone: Asia/Shanghai theme: butterfly
_config.butterfly.yml这就是Butterfly主题的配置文件了,需要自己手动创建。我只配置了如下基本字段
favicon: 网站图标 index_img: 首页大图,可以设置为false
来关闭 这里的图片文件路径可以是url也可以是文件路径
markdown渲染引擎this section updated at 2022-7-30
官方推荐的markdown-it插件是hexo-renderer-markdown-it
,使用下来发现这个的toc是无法跳转的,所以用以下的第三方render
1 yarn add @upupming/hexo-renderer-markdown-it-plus
关于这个问题提交了discussion 给butterfly
侧边栏配置侧边栏的配置位于_config.butterfly.yml
的aside
字段,可以把需要的写入自己新建的主题配置文件完成修改
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 aside: enable: true hide: false button: true mobile: true position: right card_author: enable: true description: button: enable: true icon: fab fa-github text: Follow Me link: https://github.com/xxxxxx card_announcement: enable: true content: This is my Blog card_recent_post: enable: true limit: 5 sort: date sort_order: card_categories: enable: true limit: 8 expand: none sort_order: card_tags: enable: true limit: 40 color: false sort_order: card_archives: enable: true type: monthly format: MMMM YYYY order: -1 limit: 8 sort_order: card_webinfo: enable: true post_count: true last_push_date: true sort_order:
社交媒体配置侧边栏的配置位于_config.butterfly.yml
的social
字段,可以添加多个
1 2 3 social: fas fa-envelope: mailto:xxxx@mail.com || Email fas fa-envelope: mailto:xxxx@mail.com || Email
作者头像侧边栏的配置位于_config.butterfly.yml
的avatar
字段
1 2 3 avatar: img: https://aa.com/bb.jpeg effect: false
页脚设置侧边栏的配置位于_config.butterfly.yml
的footer
字段,使用shields.io 生成的logo作为页脚上的标志,并关闭版权显示
1 2 3 4 5 6 7 footer : owner: enable: true since: 2021 custom_text: <p><a style="margin-inline:5px" target="_blank" href="https://hexo.io/" ><img no-lazy src="https://img.shields.io/badge/Frame-Hexo-blue?style=flat&logo=hexo" title="博客框架为 Hexo" alt="HEXO" ></a><a style="margin-inline:5px" target="_blank" href="https://butterfly.js.org/" ><img no-lazy src="https://img.shields.io/badge/Theme-Butterfly-6513df?style=flat&logo=bitdefender" title="主题采用 Butterfly" alt="Butterfly" ></a><a style="margin-inline:5px" target="_blank" href="https://www.jsdelivr.com/" ><img no-lazy src="https://img.shields.io/badge/CDN-jsDelivr-orange?style=flat&logo=jsDelivr" title="本站使用 Jsdelivr 为静态资源提供CDN加速" alt="Jsdelivr" ></a><a style="margin-inline:5px" target="_blank" href="https://github.com/" ><img no-lazy src="https://img.shields.io/badge/Source-Github-d021d6?style=flat&logo=GitHub" title="本站项目由 GitHub 托管" alt="GitHub" ></a><a style="margin-inline:5px" target="_blank" href="http://creativecommons.org/licenses/by-nc-sa/4.0/" ><img no-lazy src="https://img.shields.io/badge/Copyright-BY--NC--SA%204.0-d42328?style=flat&logo=Claris" alt="img" title="本站采用知识共享署名-非商业性使用-相同方式共享4.0国际许可协议进行许可" ></a></p> copyright: false # Copyright of theme and framework
注入js、css文件Butterfly主题支持将js脚本文件或者css样式文件注入到网页的header
或者footer
部分,配置位于_config.butterfly.yml
的inject
字段,样例如下
1 2 3 4 5 6 7 8 inject: head: - <link rel="stylesheet" href="/xxx.css"> - <link rel="stylesheet" href="/xxx.css"> bottom: - <script src="xxxx"></script> - <script src="xxxx"></script>
以下是本博客的一个实际注入
1 2 3 inject: head: - <link rel="stylesheet" href="/blog/css/footer.css" media="defer" onload="this.media='all'">
注意路径使用的是绝对路径,未测试相对路径是否可用
页脚透明在source/css
路径下新建footer.css
样式文件,内容如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #footer { background : rgba (255 ,255 ,255 ,.15 ); color : #000 ; border-top-right-radius : 20px ; border-top-left-radius : 20px ; backdrop-filter : saturate (100% ) blur (5px ) } #footer ::before { background : rgba (255 ,255 ,255 ,.15 ) } #footer #footer-wrap { color : var (--font-color) } #footer #footer-wrap a { color : var (--font-color) }
在主题配置文件中注入该样式文件
卡片、文章样式与黑暗模式配置文件中并未直接提供对黑暗模式样式的修改的,直接修改卡片、文章等的样式无法直接适配到黑暗模式。本人对css的知识比较薄弱,google并查看源码后找到了以下实现方式,依旧在css文件夹下新建一个样式文件(background.css
)并进行注入。实现方式就是设置元素的背景,使用rgba格式颜色最后一个参数是透明度,样式如下
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 :root { --light_bg_color : rgba (255 , 255 , 255 , 0.6 ); --dark_bg_color : rgba (18 , 18 , 18 , 0.8 ); --light_page_color : rgba (255 , 255 , 255 , 0.5 ); --dark_page_color : rgba (18 , 18 , 18 , 0.8 ); } [data-theme="dark" ] .post >.layout >#post ,#recent-posts >.recent-post-item ,.read-mode .layout >#post { background : var (--dark_bg_color); } [data-theme="dark" ] #aside-content .card-widget { background : var (--dark_bg_color); } [data-theme="light" ] #aside-content .card-widget { background : var (--light_bg_color); } [data-theme="light" ] #recent-posts >.recent-post-item ,.post >.layout >#post ,.read-mode .layout >#post { background : var (--light_bg_color); }
在调试时发现Hexo是通过改变data-theme
属性的值来切换黑暗模式的,并且类似[data-theme="light"]
的写法就可以在不同值时对应不同的样式。这里有个坑就是[data-theme="light"]
需要和css选择器写在同一行,否则会使得有的样式不生效。魔改过程中这个博客 给我了很大帮助,表示感谢
全局背景网页背景修改首先需要在主题配置文件中添加background: "#efefef"
,只有添加后渲染出来的网页才有#web_bg
这个元素,网页背景也是对这个元素样式进行修改。修改过程参考了这篇博客 很多,表示感谢~~。此部分样式内容放在background.css
内
1 2 3 4 #web_bg { background-color : #0093E9 ; background-image : linear-gradient (160deg , #0093E9 0% , #80D0C7 100% ); }
我选择蓝色渐变作为背景,这个网站 可以生成渐变背景的css样式代码,当然你也可以选择图片作为背景
algolia搜索配置实现站点搜索有两种形式,一个是local_search
一个是在线的搜索如algolia
。本站点使用algolia 提供的搜索。 algolia有免费套餐可以使用,额度是一个月10k请求,一般情况下也够了。注册过程就不细写了,可以参考其他大佬的教程,完成注册并创建一个index
后即可在API Keys
里得到三个key,分别是Application ID、Search-Only API Key以及Admin API Key。安装hexo的插件,这里推荐使用这个插件而不是hexo-algolia
插件
1 npm install hexo-algoliasearch
插件配置可以从github仓库 查找到,fields
部分配置可以在文档中查找。以下贴的配置需要放置于 _config.yml
文件内,起到插件配置的作用。其中的fields
部分是本博客实际使用的字段,不是很全但是基本涵盖了常用的查找范围
1 2 3 4 5 6 7 8 9 10 algolia: appId: "Z7A3XW4R2I" apiKey: "12db1ad54372045549ef465881c17e743" adminApiKey: "40321c7c207e7f73b63a19aa24c4761b" chunkSize: 5000 indexName: "blog" fields: - path - title - content:strip
插件配置完毕后还需要在Butterfly主题配置文件中使能搜索插件 ,否则博客页面上搜索按钮都不会出现,这点很重要!以下是_config.butterfly.yml
文件中的配置
1 2 3 4 algolia_search: enable: true hits: per_page: 6
当配置完毕后,生成站点后使用hexo algolia
即可生成索引。
图片的懒加载hexo已经有插件实现了图片的lazy load,所以仅需要简单的安装配置插件即可使用
1 npm install hexo-lazyload-image
该插件文档 见此
安装插件后需要在Hexo配置文件中添加如下字段
1 2 3 4 lazyload: enable: true onlypost: false loadingImg:
其中的loadingImg
是加载过程中的图,可自定义,默认图还是挺丑的
而对于某些你不想懒加载的图片,比如图标一类的,只需要在其元素属性上加入no-lazy
字段即可
jsDelivr加速(CDN)选择将文件放置在本人的GitHub仓库上,通过jsDelivr免费的CDN进行加速,使用该CDN加速GitHub内的文件无需注册,比较方便
1 https://cdn.jsdelivr.net/gh/<github name>/<repo name>/.../<file name>
只需要将上述路径替换成自己的仓库路径即可
gulp压缩对于生成的css、js、html、图片等文件,可以使用gulp自动化工具进行压缩以加快网站加载速度,本文参考Butterfly官方教程 ,安装gulp本体以及插件
1 2 npm install -g gulp-cli npm install --save-dev gulp-htmlclean gulp-html-minifier-terser gulp-clean-css gulp-terser gulp-uglify gulp-babel @babel/core @babel/preset-env
在网站根目录下创建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 const gulp = require ('gulp' )const cleanCSS = require ('gulp-clean-css' )const htmlmin = require ('gulp-html-minifier-terser' )const htmlclean = require ('gulp-htmlclean' )const imagemin = require ('gulp-imagemin' )const uglify = require ('gulp-uglify' )const babel = require ('gulp-babel' )gulp.task ('compress' , () => gulp.src (['./public/**/*.js' , '!./public/**/*.min.js' ]) .pipe (babel ({ presets : ['@babel/preset-env' ] })) .pipe (uglify ().on ('error' , function (e ) { console .log (e) })) .pipe (gulp.dest ('./public' )) ) gulp.task ('minify-css' , () => { return gulp.src ('./public/**/*.css' ) .pipe (cleanCSS ()) .pipe (gulp.dest ('./public' )) }) gulp.task ('minify-html' , () => { return gulp.src ('./public/**/*.html' ) .pipe (htmlclean ()) .pipe (htmlmin ({ removeComments : true , collapseWhitespace : true , collapseBooleanAttributes : true , removeEmptyAttributes : true , removeScriptTypeAttributes : true , removeStyleLinkTypeAttributes : true , minifyJS : true , minifyCSS : true , minifyURLs : true })) .pipe (gulp.dest ('./public' )) }) gulp.task ('default' , gulp.parallel ( 'compress' , 'minify-css' , 'minify-html'
我这里删除了最小化图片的部分,因为图片都使用了CDN加速
使用gulp
即可运行该task
github action生成与部署 部署于Github Pages因为不想在笔记本上生成网站再传输到自己的服务器或者GitHub上,所以使用GitHub Action进行网站的生成。首先你需要有个GitHub账号~~
新建一个仓库,分支Hexo上存储博客源文件,分支public用来存放生成的站点文件,同时直接开启GitHub Pages来部署博客。
上述过程中,安装的hexo-algoliasearch
和gulp-cli
插件需要本地安装,并且在package.json
中的scripts
下添加"algolia": "hexo algolia"
和"gulp": "gulp"
两项
1 2 3 4 5 6 7 8 "scripts" : { "build" : "hexo generate" , "clean" : "hexo clean" , "deploy" : "hexo deploy" , "server" : "hexo server" , "algolia" : "hexo algolia" , "gulp" : "gulp" }
如此添加后,就可以直接使用npm run algolia
和npm run gulp
来执行命令,避免包的全局安装,最大化利用缓存
GitHub Action参考Hexo官方的部署示例进行少部分修改
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 name: deploy_hexo on: push: branches: - hexo jobs: deploy_hexo: runs-on: ubuntu-latest env: ALGOLIA_APP_ID: ${{ secrets.ALGOLIA_APP_ID }} ALGOLIA_API_KEY: ${{ secrets.ALGOLIA_API_KEY }} ALGOLIA_ADMIN_API_KEY: ${{ secrets.ALGOLIA_ADMIN_API_KEY }} ALGOLIA_INDEX_NAME: ${{ secrets.ALGOLIA_INDEX_NAME }} steps: - uses: actions/checkout@v2 - name: Use Node.js 16 uses: actions/setup-node@v2 with: node-version: "16" - name: Cache NPM dependencies uses: actions/cache@v2 with: path: node_modules key: ${{ runner.OS }}-hexo-npm-cache restore-keys: | ${{ runner.OS }}-hexo-npm-cache - name: Install Dependencies run: npm install - name: Build run: npm run clean && npm run build && npm run algolia && npm run gulp - name: Deploy uses: peaceiris/actions-gh-pages@v3 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./public publish_branch: public user_name: 'github-actions[bot]' user_email: 'github-actions[bot]@clemon.noreply.github.com'
其中需要注意的是,由于启用GitHub Page后仓库不能是私有的,所以hexo-algoliasearch
所需要的三个key不适合直接放在配置文件中,而该插件支持从环境变量中直接获取key,所以将配置文件中的appId、apiKey、adminApiKey字段删除,在Action的配置中声明三个环境变量ALGOLIA_APP_ID
、ALGOLIA_API_KEY
、ALGOLIA_ADMIN_API_KEY
,本文将indexName也使用环境变量进行了注入。而这些key储存在仓库的secrets
里,没有公开访问权限。
私有部署本人强迫症并且考虑到Github服务器访问问题,所以选择私有部署并且设置Github仓库为私有
基于Caddy的WebHook插件铁头娃用新不用旧,直接上Caddy2,基本流程参考了这篇博客 ,使用的WebHook插件也是来自这位大佬,表示感谢🙏
贴一下我的博客部分Caddyfile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 your.domain.name { tls xxxxxx@gmail.com encode zstd gzip root blog file_server log { output file /caddy/logs/blog.log } route /webhook { webhook { repo https://github.com/gh_username/blog_repo.git path blog branch public secret xxxxxxx } } }
简单说明下:
root
和path
需要对应,这里使用相对路径Caddy会自动使用\var
作为根目录在Github仓库的Setting->Webhooks添加一个Webhook,URL就是https://your.domain.name/webhook
,Content type
选择application/json
,secret
自己设置一个并填到Caddyfile内的secret
位置,触发事件选择仅push就可以了 repo
需要带有.git后缀这里使用的Caddy需要编译带插件的,可以手动在官网下也可以自己编译,我贴一下我的Dockerfile
1 2 3 4 5 6 7 8 9 FROM caddy:builder-alpine AS builderRUN go env -w GO111MODULE=on && go env -w GOPROXY=https://goproxy.cn,direct \ && xcaddy build --with github.com/WingLim/caddy-webhook FROM caddy:alpineCOPY --from=builder /usr/bin/caddy /usr/bin/caddy
部署使用和docker-compose
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 version: '3' services: caddy: build: context: . dockerfile: Dockerfile.caddy restart: always networks: - proxy-bridge ports: - 80 :80 - 443 :443 - 6800 :6800 - 2015 :2015 volumes: - ./caddy/Caddyfile:/etc/caddy/Caddyfile - ./caddy/data:/data/caddy - ./log/caddy:/caddy/logs networks: proxy-bridge:
但是使用过程中发现存在问题,插件可以收到仓库更新的事件并去更新本地文件,但是会一直卡在updating。。。
基于rsync与CaddyCaddy的WebHook不好用也可以用其他同步方式不是嘛,rsync就是个不错的选择。简而言之就是Github Action生成好public的文件后,直接用rsync将文件部署到自己的目标服务器即可。 首先在目标服务器创建rsync的用户并设置密码,防止安全问题
1 2 sudo useradd -m rsync sudo passwd rsync
创建一对公钥、私钥
将公钥上传到目标服务器
1 ssh-copy-id -i ./id_rsa_rsync.pub rsync@domain.name
在目标服务器上创建文件夹作为目标部署文件夹
1 2 mkdir /var/rsyncsudo chmod -R rsync.rsync /var/rsync
将私钥保存到Github仓库的Secrets中,名字为HEXO_DEPLOY_KEY
,Github Action文件添加一个Step
1 2 3 4 5 6 7 8 9 - name: Deploy By Rsync uses: burnett01/rsync-deployments@5.1 with: switches: -avzr --delete path: public/ remote_path: /var/rsync/blog remote_host: domain.name remote_user: rsync remote_key: ${{ secrets.HEXO_DEPLOY_KEY }}
caddyfile只是很简单的启动一个fileserver,docker-compose里只是多只读挂载/var/rsync/blog
目录进去就好了
rsync用户不能禁止登陆,否则同步失败 采用这种方式,public分支可以删除 目标服务器建议禁止密码登陆 字体压缩参考了font-spider ,但是有很多问题,待解决后更新
访客统计截止这篇教程,Butterfly已经继承了不蒜子 的访问计数功能,默认开启无需配置。
评论系统Butterfly主题支持Disqus/Disqusjs/Livere/Gitalk/Valine/Waline/Utterances/Facebook Comments/Twikoo评论系统。
这里选用Valine ,这个不是类似GitHub issues的系统,并且LeanCloud在国内也有服务,所以访问速度什么的都还可以。
配置过程参考了这篇文章 ,在此表示感谢。
注册LeanCloudLeanCloud中国官网 去注册就可以了,需要使用支付宝进行实名认证。注册好了以后找到类似界面创建一个应用
应用选择开发版,虽然有限制但是一个小小的博客肯定是够了。创建好了就会跳转到如下界面,点击齿轮图标进入设置
然后需要绑定域名,这个域名需要是备案完成的域名,绑定过程会检查备案。海外版似乎不需要备案。
SSL就选择自动好了,省点事。这里的域名不是博客的域名!!看文档应该是调用LeanCloud Api时用的CNAME域名。这里不支持绑定裸域名,建议设置成类似blog-comment-api.domain.cn
的域名。然后需要去域名服务商的云解析添加一条CNAME记录,按着操作就好了,静待绑定完毕,其中部署证书可能需要较长时间。
绑定完毕之后不要删除或暂停这条CNAME记录,否则LeanCloud Api会无法调用(评论功能失效) 上面推荐的文章 里说这里的域名是博客域名,似乎是不对的。。。 好了之后就会有如下提示
然后在应用凭证里找到AppID
和AppKey
,后面配置要用
以后博客的评论信息会储存在LeanCloud数据库里
想要删除评论的话来这里就好了(控评doge)
配置由于Butterfly已经支持了,所以配置很简单,直接贴_config.butterfly.yml
相关部分。
开启评论系统
1 2 3 4 comments: use: - Valine
comments
字段可支持两个评论系统,但是没想到什么场景需要使用,所以这里就只写一个Valine
。
配置valine
1 2 3 4 5 6 7 8 9 10 11 12 13 14 valine: appId: <LeanCloud AppId> appKey: <LeanCLoud AppKey> pageSize: 10 avatar: wavatar lang: zh-CN placeholder: 你有什么想说呢~ guest_info: nick,mail requiredFields: mail recordIP: false serverURLs: https://blog-comment-api.domain.cn
valine
下的字段大多数都可以在valine配置项 里查到appId
和appKey
换成你自己的LeanCloud里的id和keyguest_info
就是评论者可填写的信息字段(可选nick/mail/link),对应requiredFields
就是评论者必须填写的字段serverURLs
在LeanCloud绑定的Api域名,valine访问LeanCloud Api需要使用想关闭某些文章的评论功能,在文章头部添加comments: false
就行了 字数统计安装插件
修改主题配置文件_config.butterfly.yml
1 2 3 4 5 wordcount: enable: true post_wordcount: true min2read: true total_wordcount: true