以墨会友 · 以文载道

水墨博客搭建全记录

2026/6/6 · 编程

选型

想搭一个个人博客,要求两点:好看、能折腾。

看了一圈,Hugo 太模板化,Hexo 年代太久。Valaxy 是基于 Vue 3 + Vite 的静态博客框架,主题开发就是写 Vue 组件,对我这种前端出身的人没有学习成本。

在 npm 上翻主题的时候发现了 valaxy-theme-shuimo,水墨风格:宣纸纹理、印章、动态山水画生成。一眼就定了。

初始化

bash
mkdir blog && cd blog
pnpm init
pnpm add valaxy vite

Valaxy 要求主题名以 valaxy-theme- 开头,但水墨主题发布在 @jobinjia/valaxy-theme-shuimo。用 npm alias 解决:

json
{
  "dependencies": {
    "valaxy-theme-shuimo": "npm:@jobinjia/valaxy-theme-shuimo@^1.1.8"
  }
}

踩坑

坑一:Vite 版本不兼容

valaxy 0.28.x 的子依赖要求 vite 6-7,但 pnpm 默认拉了 vite 8,构建直接报错。在 pnpm-workspace.yaml 里强制锁定版本:

yaml
overrides:
  vite: "^6.4.3"

注意 pnpm 11.x 不读 package.jsonpnpm 字段,必须写在 pnpm-workspace.yaml 里。

坑二:suncalc 模块加载失败

水墨主题用 suncalc 计算日出日落来驱动天空效果。但 suncalc 是 CJS 模块,Vite 6 的依赖预构建处理后导出为空对象。启动时能看到:

[shuimo-theme] Failed to unwrap suncalc module; shape:

valaxy.config.ts 里加一行配置:

typescript
vite: {
  optimizeDeps: {
    include: ['suncalc'],
  },
}

修改后需要清缓存:

bash
rm -rf node_modules/.valaxy node_modules/.vite

坑三:Web Worker 构建报错

主题的山水画生成用了 Web Worker(useHeroSceneWorker.ts),Vite 6 默认的 worker format 是 iife,和 code-splitting 冲突,构建时报:

Invalid value "iife" for option "worker.format"

加一行配置:

typescript
vite: {
  worker: {
    format: 'es',
  },
}

坑四:mlly 解析警告

启动时会看到:

WARN Failed to resolve package valaxy-theme-shuimo/package.json
ENOTDIR: not a directory, open '...valaxy.DbAZGdnY.mjs/package.json'

这是 valaxy 0.28.x 的已知问题,mlly 库尝试把 .mjs 文件当目录读取。不影响运行,忽略即可。

坑五:pages 目录不存在

valaxy 启动时检查 pages/ 目录,不存在会直接退出。创建好目录结构:

pages/
├── posts/        # 博客文章
│   └── hello.md
└── about.md      # 关于页面

配置

valaxy.config.ts

关键配置:

  • decorations.seasonAware: false — 关闭四季飘散花卉,不喜欢花哨
  • decorations.heroLandscape: true — 保留首页山水画
  • stamp.author: '受命,于天,既寿,永昌' — 自定义印章文字

styles/index.css

水墨主题对比度偏低,自定义了一部分 CSS 变量提升文字可读性。

写文章脚本

为了方便,写了个 new.sh 脚本:

bash
./new.sh "文章标题"
./new.sh "文章标题" -t "标签1,标签2" -c "分类"

自动生成带 frontmatter 的 markdown 文件,默认标签和分类都是「随笔」,用 $EDITOR 打开直接写。

构建

bash
pnpm build

产物在 dist/ 目录,是 SPA 模式的静态站点。用 Nginx 托管,try_files 回退到 index.html 即可。

最终结构

blog/
├── valaxy.config.ts       # 主配置
├── site.config.ts         # 站点信息
├── package.json           # 依赖
├── pnpm-workspace.yaml    # pnpm overrides
├── new.sh                 # 新建文章脚本
├── pages/
│   ├── posts/             # 文章
│   └── about.md
├── styles/
│   └── index.css          # 自定义样式
└── dist/                  # 构建产物

花了多久

断断续续折腾了大概一个下午。大部分时间花在解决 vite 版本和模块兼容性问题上,真正的配置工作其实很少。

现在写文章的流程就是 ./new.sh "标题" → 写正文 → pnpm build → 丢到服务器。简单粗暴,我喜欢。