nextjs-particlex-themeBuild high performance blog!Use particlex to build your amazing blog!

自动化构建

参考:Github Pages 部署

手动构建

本项目实际上就是一个普通的 Next.js 项目,通过在环境变量中指向博客的目录,在构建时进行读取,最后借助于 SSG 模式生成博客的静态文件。

创建配置文件

Note

此步骤可选,不提供也可以,但是可能会有部分功能上的影响。

本博客框架最大的特点就是无侵入,你只需要拉取代码后,安装依赖并配置好相关环境变量后就可直接打包,但仍然需要你创建一个配置文件。

在你的博客根目录创建一个 _config.yaml,然后提供下面的配置:

title: 博客标题 subtitle: 子标题 description: 描述
yaml

配置环境变量

从 Hexo 迁移

如果你打算从 Hexo 博客迁移,只需要提供一个环境变量即可无侵入迁移。

  • 如果你是 Linux 系统,你也可以通过 export 关键字来临时暴露这个环境变量:

    export BLOG_PATH=/path/to/your/hexo
    shell
  • 如果你是 windows,可以在本项目的根目录中创建一个 .env.local 文件:

    # .env.local BLOG_PATH=/path/to/your/hexo
    env

从其它任意 Markdown 博客迁移

支持从任意 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_DIRECTORYsource

在 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.yaml
text

其中 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 build
shell

运行完成后,会在 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. &lt;hello&gt; # 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

如果需要配置 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 数据。

DataSourceConfig

Source Code

名称类型描述
titlestring博客名称
subtitlestring | null子标题
descriptionstring | null描述
authorstring作者名称
homePagestring | null作者首页链接
theme_configThemeConfig | null主题配置
metadataMap<string, string>null

ThemeConfig

名称类型描述
indexPageSizenumber | null首页分页大小,默认为5
backgroundstring[] | null首页背景图片,每次访问会随机展示
avatarstring | null头像链接
faviconstring | null外部图标链接。不填默认使用根目录下的 favicon.ico

Envrionment

详见: environment.d.ts

默认值:.env

Metadata

名称类型描述
titlestring | null文章标题,不写时使用 Untitled
datestring | null文件创建时间,使用 yyyy/MM/dd hh:mm:ss 的格式,例如: 2024/10/24 11:14:33
categoriesstringstring[] | null
tagsstringstring[] | null
seoSEO | nullSEO 优化

SEO

SEO 优化

名称类型描述
titlestring | null网页标题
descriptionstring | null网页描述,推荐长度至少为 25
keywordsstring[] | null网页关键词

使用 Actions 部署

在项目根目录创建 .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
2024/07/31

Markdown是一种轻量级的「标记语言」。

1 Markdown语法教程

1.1 标题

不同数量的#可以完成不同的标题.。

1.2 字体

粗体、斜体、粗体和斜体,删除线,需要在文字前后加不同的标记符号。如下:

这个是粗体

这个是斜体

这个是粗体加斜体

~~这里是删除线~~

注:如果想给字体换颜色、字体或者居中显示,需要使用内嵌HTML来实现。

1.3 无序列表

无序列表的使用,在符号-后加空格使用。如下:

  • 无序列表 1
  • 无序列表 2
  • 无序列表 3

如果要控制列表的层级,则需要在符号-前使用空格。如下:

  • 无序列表 1
  • 无序列表 2
    • 无序列表 2.1
    • 无序列表 2.2

1.4 有序列表

有序列表的使用,在数字及符号.后加空格后输入内容,如下:

  1. 有序列表 1
  2. 有序列表 2
  3. 有序列表 3

1.5 引用

引用的格式是在符号>后面书写文字。如下:

读一本好书,就是在和高尚的人谈话。 ——歌德

雇用制度对工人不利,但工人根本无力摆脱这个制度。 ——阮一峰

1.6 链接

particlex

1.7 图片

favicon.ico

1.8 分割线

可以在一行中用三个以上的减号来建立一个分隔线,同时需要在分隔线的上面空一行。如下:


1.9 表格

可以使用冒号来定义表格的对齐方式,如下:

| 姓名 | 年龄 | 工作 | | :--------- | :--: | -----------: | | 小可爱 | 18 | 吃可爱多 | | 小小勇敢 | 20 | 爬棵勇敢树 | | 小小小机智 | 22 | 看一本机智书 |

1.10 代码块

如果在一个行内需要引用代码,只要用反引号引起来就好,如下:

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

2 其他语法

2.1 HTML

支持原生 HTML 语法,请写内联样式,如下:

<span style="display: block; text-align: center; color: orangered">橙色居中</span>
md

效果(橙色居中):

橙色居中

2.2 Mdx

Caution

在 mdx 中必须使用 React 语法,例如 class 需要写成 className, style需要提供一个对象而不是直接的字符串。

由于使用 SSR 渲染,所以无法绑定事件

支持 mdx + tailwindcss.

基础使用

<dib className="text-orange-500 text-right">hello</dib>
html

效果(橙色居右):

hello
图表

由于 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

效果:

Initread configinit internal servicesDiagram requesteddiagram registered ?get implementationprint error renderer type Generate svgDraw canvasCustom renderer outputdata available?read datagenerate diagramsinit themesyesnosvgcanvascustom可用noActivity Example

2.3 Github 警告

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 123
text
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.

BLOG_PATH

类型: string

说明: 博客的路径,必须提供,虽然可以使用相对路径,但还是强烈建议使用绝对路径

NEXT_PUBLIC_CND_PUBLIC_PATH_BASE_URL

类型: string | undefined

默认值: 无默认值

说明: CDN 路径前缀,不要以 / 结尾,否则路径拼接会出问题。

因为环境变量是 next.js 处理的,所以没有很好的办法来对 / 结尾的 URL 进行替换...

YAML_INDENT_SPACE_COUNT

类型: number | undefined

默认值: 2

说明: 处理 文章元数据中 yaml 配置的 TAB 缩进,这里会将 TAB 替换为相应数量的空格,以便于继续 YAML 解析。

虽然提供了这个配置,但还是不要用 TAB 键来敲 YAML 的缩进!!!除非你是在专门的 IDE 中,例如 JetBrains 系列的 IDE 会在编辑 YAML 时自动将 TAB 转为 空格。 但是在 VSCode 中,这个转换是不存在的,因为你是在 md 文件中编辑的 yaml,所以需要格外注意,同理其它编辑器也需要一并注意。

NEXT_PUBLIC_COMMENT_SCRIPT_INJECT

类型: string | undefined

默认值: 无默认值

说明: 为第三方评论组件注入脚本。

详见 配置评论组件

NEXT_PUBLIC_COMMENT_CONTAINER_IDENTIFIER

类型: string | undefined

默认值: 无默认值

说明: 为第三方评论组件设置组件容器。

详见 配置评论组件

BLOG_HOME_POST_DIRECTORY

类型: string

默认值: source/_posts

说明: 首页文章的存放目录,相对于 BLOG_PATH 的路径。详见 [从任意 Markdown 博客迁移](/quick-start#从任意 Markdown 博客迁移)。

BLOG_RESOURCE_DIRECTORY

类型: string

默认值: source/images

说明: 资源文件的存放目录,相对于 BLOG_PATH 的路径。详见 [从任意 Markdown 博客迁移](/quick-start#从任意 Markdown 博客迁移)。

BLOG_POST_DIRECTORY

类型: string

默认值: source

说明: 所有博客文件的存放路径,相对于 BLOG_PATH 的路径。详见 [从任意 Markdown 博客迁移](/quick-start#从任意 Markdown 博客迁移)。

文章元数据

Metadata

在文章 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

title

类型string | undefined

文章标题,虽然可以为空,但是强烈推荐提供

示例:

title: Java Hello World
yaml

date

类型string | undefined

文章创建时间,任意可以被 js 使用 new Date(<date>) 解析的字符串,例如:2023-09-04 16:16:53,可以为空。

示例:

date: 2023-09-04 16:16:53
yaml

tags

类型: 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

categories

类型: 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

类型SEO | undefined

详细类型定义

seo: title: <string | undefined> keywords: <string[] | undefined> description: string
yaml

示例:

seo: title: Java Hello World | Xxx's Blog keywords: - java - 'hello world' description: '使用 Java 编写 Hello World 代码。'
yaml