参考:Github Pages 部署。
本项目实际上就是一个普通的 Next.js 项目,通过在环境变量中指向博客的目录,在构建时进行读取,最后借助于 SSG 模式生成博客的静态文件。
Note 此步骤可选,不提供也可以,但是可能会有部分功能上的影响。
本博客框架最大的特点就是无侵入,你只需要拉取代码后,安装依赖并配置好相关环境变量后就可直接打包,但仍然需要你创建一个配置文件。
在你的博客根目录创建一个 _config.yaml
,然后提供下面的配置:
title: 博客标题
subtitle: 子标题
description: 描述
yaml
如果你打算从 Hexo 博客迁移,只需要提供一个环境变量即可无侵入迁移。
如果你是 Linux 系统,你也可以通过 export
关键字来临时暴露这个环境变量:
export BLOG_PATH=/path/to/your/hexoshell
如果你是 windows,可以在本项目的根目录中创建一个 .env.local
文件:
# .env.local BLOG_PATH=/path/to/your/hexoenv
支持从任意 Markdown 类型的博客迁移,只要你的博客文件是由 Markdown 文件编写的,就可以进行迁移。
迁移时,除了基础的 BLOG_PATH
需要提供外(详见上面的 从 Hexo 迁移),还需要额外提供下面三个环境变量:
BLOG_HOME_POST_DIRECTORY
: 首页文章文件夹,这些文件将会在首页和归档中展示。BLOG_RESOURCE_DIRECTORY
: 资源文件夹,访问前缀固定为 images
。BLOG_POST_DIRECTORY
:存放所有页面的文件夹,将会为这些页面构建 web 静态页面。BLOG_HOME_POST_DIRECTORY
可以是 BLOG_POST_DIRECTORY
的子目录,但是反过来不行!除此之外,这两个目录也可以单独分开指定。
以 hexo 博客为例,上面三个参数应该分别配置为:
BLOG_HOME_POST_DIRECTORY
: source/_posts
BLOG_RESOURCE_DIRECTORY
: source/images
BLOG_POST_DIRECTORY
:source
在 hexo 中,source
目录中存放了所有的 Markdown 文档,source/_post
存放了首页文章的 Markdown 文档。
再例如,以下面的博客目录结构为例:
blog-root ├── ROOT │ ├── java_guide.md │ └── javascript_guide.md ├── javascript │ └── javascript_advance.md ├── img │ └── coffee.png ├── hello_world.md ├── java_advance.md └── _config.yamltext
其中 ROOT 目录中的 md 文件为 首页文章
,其它文件均为普通的 文章
(嵌套页面)。
相应的配置为:
BLOG_HOME_POST_DIRECTORY
: ROOT
BLOG_RESOURCE_DIRECTORY
: img
BLOG_POST_DIRECTORY
:./
BLOG_PATH
: /xxx/xxx/blog-root
注意 BLOG_POST_DIRECTORY
不能为空字符串。
Important 提示:这里的静态资源目录虽然为
img
,但实际访问前缀会被替换为images
,例如这里的img/coffee.png
,访问路径为images/coffee.png
. 这是 next.js 的限制,目前没有很优雅的方法解决。
在完成上面的配置后,直接运行下面的命令就可以开始构建了:
npm run install npm run buildshell
运行完成后,会在 out
目录生成所有的静态文件。
元数据类似于 Hexo 中的机制,需要你在 Markdown 文件的顶部提供文章相关的配置,例如:
---
title: async/await 异步编程
date: 2024-07-01 22:56:28
categories:
- Rust
tags: Rust
seo:
title: async/await 异步编程 | Rust
description: 使用 async/await 进行异步编程。
keywords:
- rust
- async
- await
---
# title
# sub-title
xxxx
md
详见 文章元数据
应该优先考虑以 v<version>-stabled
分支作为基础来对博客进行构建,例如 v1-stabled
,我们会持续对这个分支进行稳固更新。
这样你就可以不用考虑频繁的小版本的更新是否需要应用到自己的博客上,你只需要关注当有新的大版本发布时是否需要更新就可以了。
强烈建议使用 CDN 保存你的图片,而不是直接和博客静态文件一起分发。
由于 next.js 限制 (其实有解,但是不太优雅),所有的图片必须放到 images
目录中,可以手动配置,但是访问的路径前缀将始终为 images
。
例如在 hexo 中,图片必须全部放到 source/images
中,放在其它任何地方的图片都会被忽略。
所有的图片都使用了原生懒加载 loading="_lazy"
。
对于网站图标 favicon.ico
可以直接放在根目录中。
例如在 hexo 中需要放在 source/favicon.ico
中。
当你需要使用 >
和 <
时,请万分小心,如果这两个符号没有被 `、```、或转移符号包括或修饰的话,在构建时将会报错:
<hello> # illegal, will cause build failed.
<hello> # ok
\<hello\> # ok
`<hello>` # ok
``` # ok
<hello>
```
markdown
配置评论组件需要设置两个环境变量:
NEXT_PUBLIC_COMMENT_SCRIPT_INJECT
NEXT_PUBLIC_COMMENT_CONTAINER_IDENTIFIER
下面以 giscus 为例进行演示。
进入 giscus 配置网站:https://giscus.app/zh-CN 。按照要求配置完成后获取到一段 script 脚本:
<script src="https://giscus.app/client.js"
data-repo="nextjs-particlex-theme/nextjs-particlex-theme.github.io"
data-repo-id="R_kgDOMcWxsw"
data-category="Announcements"
data-category-id="DIC_kwDOMcWxs84Chidp"
data-mapping="pathname"
data-strict="0"
data-reactions-enabled="1"
data-emit-metadata="0"
data-input-position="top"
data-theme="preferred_color_scheme"
data-lang="zh-CN"
data-loading="lazy"
crossorigin="anonymous"
async>
html
同时 giscus
要求网页中必须要拥有一个类名为 giscus
元素来作为评论组件的容器,所以最终的环境变量的值为:
NEXT_PUBLIC_COMMENT_SCRIPT_INJECT
: <上面那串脚本>
NEXT_PUBLIC_COMMENT_CONTAINER_IDENTIFIER
: .giscus
以 Github Pages 为例,在构建阶段,配置文件就要这么写:
- name: Build
env:
NEXT_PUBLIC_COMMENT_SCRIPT_INJECT: |
<script src="https://giscus.app/client.js"
data-repo="nextjs-particlex-theme/nextjs-particlex-theme.github.io"
data-repo-id="R_kgDOMcWxsw"
data-category="Announcements"
data-category-id="DIC_kwDOMcWxs84Chidp"
data-mapping="pathname"
data-strict="0"
data-reactions-enabled="1"
data-emit-metadata="0"
data-input-position="top"
data-theme="preferred_color_scheme"
data-lang="zh-CN"
data-loading="lazy"
crossorigin="anonymous"
async>
</script>
NEXT_PUBLIC_COMMENT_CONTAINER_IDENTIFIER: '.giscus'
yaml
如果需要配置 CDN,你需要缓存项目中 public 目录中所有内容到你的 CDN 中,并最终在构建阶段提供环境变量。例如在 Github Actions中:
- name: Build run: 'snip...' env: NEXT_PUBLIC_CND_PUBLIC_PATH_BASE_URL: 'https://your.cdn/prefix'plaintext
Tip public 目录在一个 stable 分支中不会发生变动,当你使用新的分支时建议参考迁移指南来判断是否需要更新你的 CDN 数据。
名称 | 类型 | 描述 |
---|---|---|
title | string | 博客名称 |
subtitle | string | null | 子标题 |
description | string | null | 描述 |
author | string | 作者名称 |
homePage | string | null | 作者首页链接 |
theme_config | ThemeConfig | null | 主题配置 |
metadata | Map<string, string> | null |
名称 | 类型 | 描述 |
---|---|---|
indexPageSize | number | null | 首页分页大小,默认为5 |
background | string[] | null | 首页背景图片,每次访问会随机展示 |
avatar | string | null | 头像链接 |
favicon | string | null | 外部图标链接。不填默认使用根目录下的 favicon.ico |
详见: environment.d.ts
默认值:.env
名称 | 类型 | 描述 |
---|---|---|
title | string | null | 文章标题,不写时使用 Untitled |
date | string | null | 文件创建时间,使用 yyyy/MM/dd hh:mm:ss 的格式,例如: 2024/10/24 11:14:33 |
categories | string | string[] | null |
tags | string | string[] | null |
seo | SEO | null | SEO 优化 |
SEO 优化
名称 | 类型 | 描述 |
---|---|---|
title | string | null | 网页标题 |
description | string | null | 网页描述,推荐长度至少为 25 |
keywords | string[] | null | 网页关键词 |
在项目根目录创建 .github/workflows/pages.yaml
,添加如下内容:
name: Pages
on:
push:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout Main Repository
uses: actions/checkout@v4
with:
repository: IceOfSummer/nextjs-particlex-theme
# 这里可以选一个 tag 或者 分支
ref: master
path: nextjs-particlex-theme
- name: Cache Next.js
uses: actions/cache@v4
with:
path: nextjs-particlex-theme/.next/cache
key: nextjs-cache
- name: Use Node.js 20
uses: actions/setup-node@v4
with:
node-version: "20"
cache: 'npm'
cache-dependency-path: nextjs-particlex-theme/package-lock.json
- name: Checkout Datasource Repository
uses: actions/checkout@v4
with:
path: datasource
- name: Install Dependencies
run: 'cd nextjs-particlex-theme && npm install'
- name: Build
run: 'export BLOG_PATH=${GITHUB_WORKSPACE}/datasource && cd nextjs-particlex-theme && npm run build'
- name: Upload GitHub Pages artifact
uses: actions/upload-pages-artifact@v3
with:
path: 'nextjs-particlex-theme/out'
deploy:
needs: build
permissions:
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
yaml
如果需要提供环境变量,直接在 Build
步骤提供就行。例如禁用构建时的缓存:
- name: Build
env:
DATASOURCE_CACHE_ENABLE: false
run: 'export BLOG_PATH=${GITHUB_WORKSPACE}/datasource && cd nextjs-particlex-theme && npm run build'
yaml
Markdown是一种轻量级的「标记语言」。
不同数量的#
可以完成不同的标题.。
粗体、斜体、粗体和斜体,删除线,需要在文字前后加不同的标记符号。如下:
这个是粗体
这个是斜体
这个是粗体加斜体
~~这里是删除线~~
注:如果想给字体换颜色、字体或者居中显示,需要使用内嵌HTML来实现。
无序列表的使用,在符号-
后加空格使用。如下:
如果要控制列表的层级,则需要在符号-
前使用空格。如下:
有序列表的使用,在数字及符号.
后加空格后输入内容,如下:
引用的格式是在符号>
后面书写文字。如下:
读一本好书,就是在和高尚的人谈话。 ——歌德
雇用制度对工人不利,但工人根本无力摆脱这个制度。 ——阮一峰
可以在一行中用三个以上的减号来建立一个分隔线,同时需要在分隔线的上面空一行。如下:
可以使用冒号来定义表格的对齐方式,如下:
| 姓名 | 年龄 | 工作 | | :--------- | :--: | -----------: | | 小可爱 | 18 | 吃可爱多 | | 小小勇敢 | 20 | 爬棵勇敢树 | | 小小小机智 | 22 | 看一本机智书 |
如果在一个行内需要引用代码,只要用反引号引起来就好,如下:
Use the printf()
function.
在需要高亮的代码块的前一行及后一行使用三个反引号,同时第一行反引号后面表示代码块所使用的语言,如下:
// FileName: HelloWorld.java
public class HelloWorld {
// Java 入口程序,程序从此入口
public static void main(String[] args) {
System.out.println("Hello,World!"); // 向控制台打印一条语句
}
}
java
<hello>
<world></world>
</hello>
xml
支持原生 HTML 语法,请写内联样式,如下:
<span style="display: block; text-align: center; color: orangered">橙色居中</span>md
效果(橙色居中):
Caution 在 mdx 中必须使用 React 语法,例如
class
需要写成className
,style
需要提供一个对象而不是直接的字符串。由于使用 SSR 渲染,所以无法绑定事件。
支持 mdx + tailwindcss.
<dib className="text-orange-500 text-right">hello</dib>
html
效果(橙色居右):
由于 mermaid 不支持 SSR,所以使用了支持 SSR 的 Pintor 来绘制流程图。
<PintoraDiagram code={`
activityDiagram
title: Activity Example
start
partition Init {
:read config;
:init internal services;
note left: init themes
}
:Diagram requested;
if (diagram registered ?) then
:get implementation;
else (no)
:print error;
endif
switch ( renderer type )
case ( svg )
:Generate svg;
case ( canvas )
:Draw canvas;
case ( custom )
:Custom renderer output;
endswitch
while (data available?) is (可用)
:read data;
:generate diagrams;
endwhile (no)
end
`}/>
html
效果:
Note Note 123
Tip TIP 123
Important IMPORTANT 123
Warning WARNING 123
Caution CAUTION 123
> [!NOTE] > Note 123 > [!TIP] > TIP 123 > [!IMPORTANT] > IMPORTANT 123 > [!WARNING] > WARNING 123 > [!CAUTION] > CAUTION 123text
Note 说明: 类型中有
undefined
表示你可以不提供该参数。
由于做这个项目的目的是弃用 hexo,所以可以无缝从 hexo 切换过来。
在你的博客根目录中创建 _config.yaml
.
可用配置: DataSourceConfig。
样例:
# 博客标题
title: <string>
# 子标题
subtitle: <string | undefined>
# 描述
description: <string | undefined>
# homePage
authorHome: <string | undefined>
theme_config: <undefined | ThemeConfig>
# 首页背景图片,配置多个每次都会随机展示
background: <string[] | undefined>
# 首页显示的文章数量,默认为 5
indexPageSize: <number | undeinfed>
# 头像
avatar: <string | undefined>
yaml
一切以该文件注释为准:environment.d.ts.
类型: string
说明: 博客的路径,必须提供,虽然可以使用相对路径,但还是强烈建议使用绝对路径!
类型: string
| undefined
默认值: 无默认值
说明: CDN 路径前缀,不要以 /
结尾,否则路径拼接会出问题。
因为环境变量是 next.js 处理的,所以没有很好的办法来对
/
结尾的 URL 进行替换...
类型: number
| undefined
默认值: 2
说明: 处理 文章元数据中 yaml 配置的 TAB 缩进,这里会将 TAB 替换为相应数量的空格,以便于继续 YAML 解析。
虽然提供了这个配置,但还是不要用 TAB 键来敲 YAML 的缩进!!!除非你是在专门的 IDE 中,例如 JetBrains 系列的 IDE 会在编辑 YAML 时自动将 TAB 转为 空格。 但是在 VSCode 中,这个转换是不存在的,因为你是在 md 文件中编辑的 yaml,所以需要格外注意,同理其它编辑器也需要一并注意。
类型: string
| undefined
默认值: 无默认值
说明: 为第三方评论组件注入脚本。
详见 配置评论组件
类型: string
| undefined
默认值: 无默认值
说明: 为第三方评论组件设置组件容器。
详见 配置评论组件
类型: string
默认值: source/_posts
说明: 首页文章的存放目录,相对于 BLOG_PATH 的路径。详见 [从任意 Markdown 博客迁移](/quick-start#从任意 Markdown 博客迁移)。
类型: string
默认值: source/images
说明: 资源文件的存放目录,相对于 BLOG_PATH 的路径。详见 [从任意 Markdown 博客迁移](/quick-start#从任意 Markdown 博客迁移)。
类型: string
默认值: source
说明: 所有博客文件的存放路径,相对于 BLOG_PATH 的路径。详见 [从任意 Markdown 博客迁移](/quick-start#从任意 Markdown 博客迁移)。
在文章 markdown 顶部使用如下格式以提供元数据:
--- <yaml content here> ---text
在 ---
之间的内容,就是 yaml 格式的元数据,与 hexo 兼容。
Overview:
title: async/await 异步编程
date: 2024-07-01 22:56:28
categories:
- Rust
tags: Rust
seo:
title: async/await 异步编程 | Rust
description: 使用 async/await 进行异步编程。
keywords:
- rust
- async
- await
yaml
类型:string
| undefined
文章标题,虽然可以为空,但是强烈推荐提供。
示例:
title: Java Hello World
yaml
类型:string
| undefined
文章创建时间,任意可以被 js 使用 new Date(<date>)
解析的字符串,例如:2023-09-04 16:16:53
,可以为空。
示例:
date: 2023-09-04 16:16:53
yaml
类型: string[]
| string
| DeprecatedTags
|undefined
详细类型定义:
tags: <string | string[] | undefined>
---
# 为了兼容 particlex 主题提供的,不推荐使用,实际实现会忽略 `path` 的值
tags:
data:
- { name: <string>, path: <string> }
yaml
示例:
tags: java
---
tags:
- java
- spring
---
tags:
data:
- { name: 'java', path: '/java/' }
yaml
类型: string[]
| string
| DeprecatedCategories
| undefined
详细类型定义:
categories: <string | string[] | undefined>
---
# 为了兼容 particlex 主题提供的,不推荐使用,实际实现会忽略 `path` 的值
categories:
data:
- { name: <string>, path: <string> }
yaml
示例:
categories: java
---
categories:
- java
- spring
---
categories:
data:
- { name: 'java', path: '/java/' }
yaml
类型:SEO | undefined
详细类型定义:
seo:
title: <string | undefined>
keywords: <string[] | undefined>
description: string
yaml
title
: html 网页标题,而非文章的标题,如果不指定,则会使用 <文章标题> | <博客title>
。
参考资料:影响标题链接的最佳实践。
keywords
: 关键字,如果不提供,默认使用 tags
内容(如果有)。
参考资料: 关键词堆砌; Google 不会将关键字元标记用于网页排名。
description
: 网页描述。
参考资料:使用高质量的描述。
示例:
seo:
title: Java Hello World | Xxx's Blog
keywords:
- java
- 'hello world'
description: '使用 Java 编写 Hello World 代码。'
yaml