跳到主要内容

关于

年纪大了,看的多了,见的杂了,记忆力也没有年轻的时候那么好了。但是总有些瞬间,有些知识是我们不愿所遗忘的,是值得被回忆想起来的,是能够为我们所用的。 当然咯,有很多方式可以记录。日常生活动态用微信朋友圈记录,工作技能用CSDN等网站记录。但是出于一种怀旧典藏的心理,总觉得数据存在别人那里让我觉得不放心,让我觉得无法掌控,让我觉得不能依自己所想来组织自己的表达。所以觉得还是自己用本地文件记录更好,那么如何让内容展示出去呢,也能够方便自己随时随地查看,毕竟随时随地打开笔记本翻阅查看也不太显示,所以最终决定自己搭建一个博客网站咯,作为一个技术开发从业者,这也是我一直所期望的。

使用Obsidian记录

最开始一直是使用Typora作为编辑器的,后来Typora发布正式版开始收费之后,我也选择成为了正版用户,毫无疑问我认为Typora在单文档编辑方面是其他app无法匹及的。 后来偶然接触到了Obsidian,它提倡的数据本地持有,文档仓库概念,All in One等一些思想与我不谋而合,再花了一两天的时间试用之后,我决定换用Obsidian作为以后的编辑工具了。

安装 File Hider 插件用于隐藏工作区目录,例如 node_modules。 安装 Codeblock Customizer 用于显示代码块行号。

使用Docusaurus作为前端

Typesense作为搜索引擎

在使用上 Algolia DocSearch 是使用体验最好的,也是 Docusaurus 官方支持的,但是奈何其不开源且收费。被我折腾过一次后,第二次就怎么也使用不了了。

Typesense 作为 Algolia 的开源平替版,和 Docusaurus 集成度也还行。但是目前发现它对中文分词好像不太友好。

mkdir $(pwd)/typesense-data
docker run -d --restart unless-stopped --name typesense -p 8108:8108 -v$(pwd)/typesense-data:/data typesense/typesense:26.0 --data-dir /data --api-key="amass_toolset" --enable-cors

安装 DocSearch Scraper

编写配置文件 typesense.json

{
"index_name": "amass_blog",
"start_urls": [
"https://amass.fun/"
],
"sitemap_urls": [
"https://amass.fun/sitemap.xml"
],
"sitemap_alternate_links": true,
"stop_urls": [],
"selectors": {
"lvl0": {
"selector": "(//ul[contains(@class,'menu__list')]//a[contains(@class, 'menu__link menu__link--sublist menu__link--active')]/text() | //nav[contains(@class, 'navbar')]//a[contains(@class, 'navbar__link--active')]/text())[last()]",
"type": "xpath",
"global": true,
"default_value": "Documentation"
},
"lvl1": "header h1",
"lvl2": "article h2",
"lvl3": "article h3",
"lvl4": "article h4",
"lvl5": "article h5, article td:first-child",
"lvl6": "article h6",
"text": "article p, article li, article td:last-child"
},
"strip_chars": " .,;:#",
"custom_settings": {
"separatorsToIndex": "_",
"attributesForFaceting": [
"language",
"version",
"type",
"docusaurus_tag"
],
"attributesToRetrieve": [
"hierarchy",
"content",
"anchor",
"url",
"url_without_anchor",
"type"
]
},
"conversation_id": [
"833762294"
],
"nb_hits": 46250
}

创建 .env 文件

TYPESENSE_API_KEY=amass_toolset
TYPESENSE_HOST=amass.fun
TYPESENSE_PORT=8108
TYPESENSE_PROTOCOL=http

运行scraper

docker run -it --rm --env-file=$(pwd)/typesense-data/.env -e "CONFIG=$(cat $(pwd)/typesense-data/typesense.json | jq -r tostring)" typesense/docsearch-scraper:0.9.1

自定义导航栏

Docusaurus在移动端的响应式布局,不太符合我的要求:

npm run swizzle @docusaurus/theme-classic Navbar/Content -- --eject
import React from 'react';
// ...
import DefaultNavbarItem from '@theme/NavbarItem/DefaultNavbarItem';
import UserLogin from '@site/src/components/UserLogin.jsx';

export default function NavbarContent() {
return (
<NavbarContentLayout
// ...
right={
// ...
<DefaultNavbarItem className={styles.mustDisplay} label="留言板" to="/MessageBoard" />
<UserLogin />
}
/>
);
}
.mustDisplay {
display: inline-block !important;

}

.searchBar {
position: static !important;
}

自定义 NotFound 页面

Docusaurus 自带的404页面,我们可以自定义,让其更生动:

npm run swizzle @docusaurus/theme-classic NotFound -- --eject	
npm run swizzle @docusaurus/theme-classic MDXComponents -- --eject # 这里我们自定义TaskList

另外,在使用Nginx时,如果遇到错误,也可以指向到这里:

error_page 500 502 503 504 /404.html;
location = /404.html {
root amass_blog;
}

支持Mermaid

npm install @docusaurus/theme-mermaid

Twikoo评论系统

工作微信机器人作为评论即时通知。

Swizzling Docusaurus 内部组件

安装twikoo包,然后定制DocItem/LayoutBlogPostPage添加评论组件。

npm install twikoo
npm run swizzle @docusaurus/theme-classic DocItem/Layout -- --eject
npm run swizzle @docusaurus/theme-classic BlogPostPage -- --eject

然后添加如下代码:

import CommentItem from '../../../components/CommentItem';
// ...
function BlogPostPageContent({sidebar, children}) {
// ...
const {
// ...
comments = true,
} = frontMatter;
return (
<BlogLayout>
<!--省略实现-->
{comments && (<CommentItem />)}
</BlogLayout>
);
}

CodeBlock支持c++标识

Docusaurus高亮C++代码,只能使用cpp才能识别。但是之前一直都是使用typora作为编辑器,习惯输入c++。这时需要定制一下CodeBlock/Content这个组件:

npm run swizzle @docusaurus/theme-classic CodeBlock/Content -- --eject

然后在src/theme/CodeBlock/Content/String.js修改如下两行:

let language = normalizeLanguage(
languageProp ?? parseLanguage(blockClassName) ?? defaultLanguage,
);
if (language === "c++") language = "cpp";

适配React Material主题

npm run swizzle @docusaurus/theme-classic ColorModeToggle -- --wrap
import React, { useEffect } from "react";
import ColorModeToggle from "@theme-original/ColorModeToggle";
import { useColorScheme } from "@mui/material/styles";

export default function ColorModeToggleWrapper(props) {
// MUI color mode setting
const { setMode } = useColorScheme();

// "value" holds the color theme. Either "light" or "dark"
const { value } = props;

// change mode based on "value" prop
// "dark" or "light" are also used for MUI
useEffect(() => {
setMode(value);
}, [value]);

return (
<>
<ColorModeToggle {...props} />
</>
);
}

创建MUI主题配置src/components/MuiTheme.js文件:

import { experimental_extendTheme as extendTheme } from "@mui/material/styles";

const muiTheme = extendTheme({
colorSchemes: {
light: {
palette: {
primary: {
main: "#205d3b",
},
background: {
paper: "#2e8555",
},
},
},
dark: {
palette: {
primary: {
main: "#29d5b0",
},
background: {
paper: "#25c2a0",
},
},
},
},
});

export default muiTheme;

新建src/theme/Root.jsx文件:

import React from 'react';
import store from '../business/store';
import { Provider } from 'react-redux'
import { CacheProvider } from '@emotion/react';
import { Experimental_CssVarsProvider as CssVarsProvider } from '@mui/material/styles';
import createEmotionCache from '../business/createEmotionCache';
import theme from "@site/src/components/MuiTheme.js";

const cache = createEmotionCache();

export default function Root({ children }) {
return <CacheProvider value={cache}>
<CssVarsProvider theme={theme}>
<Provider store={store}>
{children}
</Provider>
</CssVarsProvider>
</CacheProvider>
}

杂想

早在2021年06月的时候,想法就萌生了。最开始想用React自己实现一个博客前端应用。先后也边学边用React、React Material、React Markdown实现了一个简陋的应用。大致逻辑就是前端向服务器请求Markdown原始文档,然后依赖React Markdown在前端进行markdown解析渲染及呈现。前后大概花了一个星期左右吧,马马虎虎能看,后面就没再管了,尽管我知道问题很多。特别是兼容这一块,不同的浏览器,不同的终端设备,不同的显示器分辨率以及缩放率,让我这个半吊子叫苦不迭,果然每一件事情较真起来没有一个是容易的。后来入职了一家公司,记得是在当时作自我介绍时,我有写过我有个人网站(啊哈哈,技术菜鸟的虚荣心)。后面HR访问了一下,然后在一边吐槽着这网站居然也能用?(小小的自尊心受到万点暴击)。

再到后来,大约是2022年05月份的时候,终于有时间继续折腾这个网站了。那个时候我把原因归结于我对React等前端知识不足,不是专业的以至于网站不好用,兼容性不好,加载慢,被吐槽(心理过不起的坎......>..<)。经过网上的一番搜索,我最终又敲定了一版方案。改用C++ Web Toolkit实现网站,说干就干,结果就是一个月后不得不决定直接终止放弃。虽然说用C++来写网页,似乎看起来帮我规避了对前端不熟的短板,但是却把我带进了更深的坑。我花了一定的时间去翻看它的文档,学习示例。其实他的思路很有意思,整个框架像极了Qt,无非是在界面绘制的时候,一个是将内容写入到Windows窗口,而一个是生成即时html文档提供给browser端。那么意味着我不止得熟悉Wt得原理,更需要熟悉html这一层的知识,因为其生成的html更为原始,如果要查细节原因的话,那简直是个无底洞。

最终我又把目光朝向了Qt WebAssembly,这个是基本可以说完全屏蔽了html、css等实现细节,而且我对Qt也比较熟悉。不过在后面熟悉示例的过程中便很快发现了其中几个问题,一个是其打包出来的应用文件非常大,MB级别的。这对于移动端以及我的简陋服务器带宽来说都是不能忍受的。另一个是其大致实现思路是使用了html的canvas元素,然后在其上面绘制UI元素,确实是屏蔽了html、css细节,但是与之带来了N多缺点,一个是做不了延迟加载,必须得所有资源一次性加载完成才能显示,另一个是其不是基于DOM结构,所以对于网页的各种优化都没有,例如无障碍浏览模式以及搜索引擎的SEO等等。

最终我意识到凭借我目前的技术能力以及有限的时间,是无法去从零实现一个自己想要的网页应用的。唯一可行的就是拿来主义,直接用别人弄好的框架。最开始选用的是Material for MkDocs,这个框架最开是使用的还行,界面也受益于Material风格让人感觉比较舒心。可能有不足的就是其采用的Python-Markdown解析库对Markdown格式要求极为严格,在静态构建html文档的时候发现其很多与我之前使用Typora编辑的格式所不兼容。当然与我自己去实现,还是选择了接受妥协。一段时间后,有了想增加博客的想法,及不仅把自己的笔记放上去,也能展示某年某月自己的感想及所见所闻。但是奈何Material for MkDocs这个功能需要成为赞助者才能使用,而这个赞助费对我来说比较高昂,so只能选择放弃。

在2023年春节的时候,闲暇之余我偶发发现了Facebook的Docusaurus框架,顿时让我心中暗呼终于找到了心中所属。它刚好提供了笔记和博客的功能,而且可定制性比较强,虽然要求使用者具备一定的开发能力,不过正好之前的一顿折腾让我稍微了解了一点React的使用。退一步来说,及时开箱式的使用,我也觉得已经达到我目前的要求拉。 至此,前端展示的寻觅之路就到这里啦。再折腾下去,就会犯下为折腾工具为耗费心力却不重视内容的旁路错误了。嗯,可能已经有些过了吧,现在回想起来,一开始就应该用现成的。

使用Git存储笔记

使用Git存储笔记不算一个好办法,但也不算太差。一个是笔记修改后可以通过提交记录查看修改变更内容,另一个是我们可以配和CI实现笔记自动化部署至网站。 大致来说就是我们增删改笔记之后,将其变动推送至Git远程仓库(这里我使用的是Gitee),Git会经由Hook机制通知CI服务器(这里我使用的是Drone CI),通过CI进行自动化部署。

服务器部署

这是个人网站,当然其内容应该也无法吸引浏览者为其捐款,所以开销一贯主张能省则省,能用最低配就用最低配。

端口分配

端口号组件作用
3389RDP用于映射PVE虚拟机Windows11的RDP服务,方便远程操作
3390RDP用于映射公司办公机 Windows11的RDP服务,比向日葵好使
3391RDP老家Windows 11的RDP服务
7000FRPSfrps转发监听端口
8080OpenResty8080便于记忆当域名未备案通过时,临时使用访问网站
8081HttpServer自己编写的C++服务器程序,用于处理自定义功能
8082twikoo用于网站评论功能
8083Gitea用于提供git代码托管服务
8084frp_http_proxyfrps通过此端口接受http请求
8085frp_board用于FRP看板
8086wiznote用于私人笔记
8087speed_test用于测试服务器延时的小工具
8088PVE用于 FRP 转发 PVE 数据
8108Typesense搜索引擎

域名解析

域名解析更改解析IP地址。

另外可以在 FreeSSL上申请免费的SSL证书,阿里云提供的免费证书数量越来越少了,目前可以免费申请20个SSL证书,每个有效期三个月。算起来可以支撑一年5个域名证书。

域名作用
amass.fun根域名
unraid.amass.fun访问NAS
gitea.amass.funGitea
office.amass.funCollabora文件预览编辑

OpenRestry

apt-get -y install --no-install-recommends wget gnupg ca-certificates
wget -O - https://openresty.org/package/pubkey.gpg | gpg --dearmor -o /usr/share/keyrings/openresty.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/openresty.gpg] http://openresty.org/package/ubuntu $(lsb_release -sc) main" | tee /etc/apt/sources.list.d/openresty.list > /dev/null
apt-get update
apt-get -y install openresty
opm get bungle/lua-resty-session

Docker

# Add Docker's official GPG key:
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
chmod a+r /etc/apt/keyrings/docker.gpg

# Add the repository to Apt sources:
echo "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
apt-get update
apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
docker run hello-world # 测试

为知笔记

为知笔记提供了免费使用Docker进行私有部署的服务。在用户主目录建立一个wizdata的文件夹。为知笔记服务端会把所有的数据保存在这个目录里面,注意定时备份该目录。

mkdir ~/wizdata
docker run --name wiz --restart=always -it -d -v ${PWD}/wizdata:/wiz/storage -v /etc/localtime:/etc/localtime -p 8086:80 -p 9269:9269/udp wiznote/wizserver

Twikoo

Twikoo是一个简洁、安全、免费的网站评论系统。

mkdir ~/HttpServer/twikoo_data
docker run --name twikoo --restart=always -e TWIKOO_THROTTLE=1000 -p 8082:8080 -v ${PWD}/twikoo_data:/app/data -d imaegoo/twikoo

librespeed

docker run -d --name=librespeed -e PASSWORD=88888888 -p 8087:80 -v ${PWD}/librespeed:/config --restart unless-stopped lscr.io/linuxserver/librespeed:latest

Frp

前后端部署

将Docusaurus构建生成的前端文件上传到~/HttpServer/amass_blog

构建HttpServer应用,将其上传至~/HttpServer下,并为其配置好运行环境。

HttpServer下的conflua目录上传至~/HttpServer下,conf/nginx.conf有对上述服务的反向代理配置。

建站记录

2024/03/04

在折腾完 NAS 之后,其有着丰富的存储容量和计算性能。所以合计着等雨云的一年服务器到期之后,依旧使用阿里云 87.12¥/年的服务区,然后复杂的应用部署在 NAS 上,再购买 frp 服务进行内网穿透。

2023/11/05

在使用Gitea搭建自己的Git服务器后,深感1Mbps的带宽实在太拉跨了,于是在一番寻找之后找到了一个叫雨云的云服务商家,初步体验套餐如下:

  • CPU:4核
  • 内存:4GB
  • 硬盘:30GB
  • 带宽:10Mbps上传,30Mbps下载
  • 按年付费:624¥/年。

2023/01/02

自己使用React开发Web成本太高,而且最终缺陷也很多。现在已经切换使用mkdocs。

2022/11/21

使用Drone CI自动更新上传笔记。

2021/06/24

实现了服务器接入了自己创建的微信公众号,但是现在个人账号不开放推送消息的功能,只有最简单的回复功能,后续可以自定义公众号菜单,然后做成指令发送给服务器进行响应然后返回相应消息。

2021/06/12

云服务器就在阿里云上购买的最便宜的配置,按年付费:87.12¥/年。

  • CPU:1核
  • 内存:2GB
  • 硬盘:40GB
  • 带宽:1Mbps

域名也选了比较便宜的.fun域名,按年付费:52¥/年。