chore: clean up and migrate temp docs to proper locations
- Remove outdated temporary documentation files - Migrate relevant content to appropriate locations in docs structure - Update gitea actions deployment guide with proper images and content
This commit is contained in:
@@ -1,206 +0,0 @@
|
|||||||
# Markdown博客文章迁移指南
|
|
||||||
|
|
||||||
本文档规定了将Markdown文档迁移到`zhaoguiyang.site`博客系统的标准流程和必要步骤。所有迁移工作必须严格按照本指南执行。
|
|
||||||
|
|
||||||
## 1. 博客文章结构
|
|
||||||
|
|
||||||
在`zhaoguiyang.site`项目中,博客文章按照语言分别存储在以下目录:
|
|
||||||
|
|
||||||
- 英文文章:`/src/pages/blog/posts/`
|
|
||||||
- 中文文章:`/src/pages/zh/blog/posts/`
|
|
||||||
|
|
||||||
## 2. 文件命名规范
|
|
||||||
|
|
||||||
为了保持一致性和良好的URL结构,请遵循以下命名规范:
|
|
||||||
|
|
||||||
- 使用小写字母
|
|
||||||
- 单词之间使用连字符(`-`)分隔
|
|
||||||
- 文件名应简洁地反映文章内容
|
|
||||||
- 使用`.md`扩展名
|
|
||||||
|
|
||||||
示例:`react-performance-optimization.md`
|
|
||||||
|
|
||||||
## 3. 前置元数据(Frontmatter)要求
|
|
||||||
|
|
||||||
每篇博客文章必须在文件顶部包含YAML格式的前置元数据,用三个连字符(`---`)包围。
|
|
||||||
|
|
||||||
### 必需属性
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
---
|
|
||||||
title: "文章标题" # 文章标题(必需)
|
|
||||||
description: "文章描述" # 文章简短描述或摘要(必需)
|
|
||||||
date: "2023-06-15" # 发布日期,格式:YYYY-MM-DD(必需)
|
|
||||||
image: "图片URL" # 文章封面图片URL(必需)
|
|
||||||
tags: ["标签1", "标签2"] # 文章标签(必需)
|
|
||||||
tagId: ["tag1", "tag2"] # 标签唯一标识符(必需)
|
|
||||||
category: "文章分类" # 文章分类(必需)
|
|
||||||
categoryId: "category-id" # 分类唯一标识符(必需)
|
|
||||||
readTime: "5 min read" # 阅读时间(必需)
|
|
||||||
---
|
|
||||||
```
|
|
||||||
|
|
||||||
### 前置元数据示例
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
---
|
|
||||||
title: "React性能优化最佳实践"
|
|
||||||
description: "本文探讨了提升React应用性能的多种策略和技术,包括组件优化、状态管理和渲染优化。"
|
|
||||||
date: "2023-06-15"
|
|
||||||
image: "https://example.com/images/react-performance.jpg"
|
|
||||||
tags: ["React", "性能优化", "前端开发"]
|
|
||||||
tagId: ["react", "performance", "frontend"]
|
|
||||||
category: "前端开发"
|
|
||||||
categoryId: "frontend"
|
|
||||||
readTime: "5 min read"
|
|
||||||
---
|
|
||||||
```
|
|
||||||
|
|
||||||
### 属性说明
|
|
||||||
|
|
||||||
| 属性 | 类型 | 描述 | 是否必需 |
|
|
||||||
|------|------|------|----------|
|
|
||||||
| `title` | 字符串 | 文章标题 | 是 |
|
|
||||||
| `description` | 字符串 | 文章描述/摘要 | 是 |
|
|
||||||
| `date` | 字符串 | 发布日期(YYYY-MM-DD格式) | 是 |
|
|
||||||
| `image` | 字符串 | 文章封面图片URL | 是 |
|
|
||||||
| `tags` | 字符串数组 | 文章标签 | 是 |
|
|
||||||
| `tagId` | 字符串数组 | 标签唯一标识符(用于多语言环境) | 是 |
|
|
||||||
| `category` | 字符串 | 文章分类 | 是 |
|
|
||||||
| `categoryId` | 字符串 | 分类唯一标识符(用于多语言环境) | 是 |
|
|
||||||
| `readTime` | 字符串 | 阅读时间(如"5 min read") | 是 |
|
|
||||||
|
|
||||||
## 4. 迁移步骤
|
|
||||||
|
|
||||||
### 4.1 准备Markdown文件
|
|
||||||
|
|
||||||
1. 检查并确认Markdown文件的格式和内容符合项目规范
|
|
||||||
2. 文件必须使用UTF-8编码
|
|
||||||
3. 必须移除所有不兼容的HTML标签和特殊格式
|
|
||||||
|
|
||||||
### 4.2 添加前置元数据
|
|
||||||
|
|
||||||
1. 在文件顶部添加前置元数据区域(用`---`包围)
|
|
||||||
2. 填写所有必需属性(`title`、`description`、`date`、`image`、`tags`、`tagId`、`category`、`categoryId`、`readTime`)
|
|
||||||
3. 确保所有属性都按照规定格式填写完整
|
|
||||||
|
|
||||||
### 4.3 图片处理
|
|
||||||
|
|
||||||
文章中的图片必须按照以下两种方式之一进行处理:
|
|
||||||
|
|
||||||
#### 方式一:使用外部图片链接
|
|
||||||
|
|
||||||
必须在Markdown中使用完整的URL:
|
|
||||||
|
|
||||||
```markdown
|
|
||||||

|
|
||||||
```
|
|
||||||
|
|
||||||
#### 方式二:使用本地图片
|
|
||||||
|
|
||||||
1. 必须将图片文件放在`public/images/blog/`目录下
|
|
||||||
2. 必须在Markdown中使用以下格式引用图片:
|
|
||||||
|
|
||||||
```markdown
|
|
||||||

|
|
||||||
```
|
|
||||||
|
|
||||||
### 4.4 放置文件
|
|
||||||
|
|
||||||
必须根据文章语言,将处理好的Markdown文件放在指定目录:
|
|
||||||
|
|
||||||
- 英文文章:必须放在`/src/pages/blog/posts/your-article-name.md`
|
|
||||||
- 中文文章:必须放在`/src/pages/zh/blog/posts/your-article-name.md`
|
|
||||||
|
|
||||||
### 4.5 验证
|
|
||||||
|
|
||||||
1. 必须通过以下命令启动开发服务器:`pnpm run dev`
|
|
||||||
2. 必须访问博客页面,确认文章显示正常
|
|
||||||
3. 必须检查文章内容、元数据、图片和格式是否完全符合规范
|
|
||||||
|
|
||||||
## 5. Markdown语法支持
|
|
||||||
|
|
||||||
本博客系统仅支持以下Markdown语法:
|
|
||||||
|
|
||||||
### 5.1 基本语法
|
|
||||||
|
|
||||||
- 标题:必须使用`#`、`##`、`###`等标记,一级标题`#`仅用于文章标题
|
|
||||||
- 强调:必须使用`*斜体*`表示斜体,`**粗体**`表示粗体
|
|
||||||
- 列表:必须使用`-`或`1.`分别表示无序和有序列表
|
|
||||||
- 链接:必须使用`[链接文本](URL)`格式
|
|
||||||
- 图片:必须使用``格式
|
|
||||||
- 引用:必须使用`>`标记
|
|
||||||
- 代码:行内代码必须使用单反引号`` ` ``包围,代码块必须使用三反引号包围
|
|
||||||
|
|
||||||
### 5.2 代码块
|
|
||||||
|
|
||||||
必须使用三个反引号(```)包围代码,并明确指定语言以启用语法高亮:
|
|
||||||
|
|
||||||
````markdown
|
|
||||||
```javascript
|
|
||||||
function greeting() {
|
|
||||||
console.log("Hello, world!");
|
|
||||||
}
|
|
||||||
```
|
|
||||||
````
|
|
||||||
|
|
||||||
### 5.3 表格
|
|
||||||
|
|
||||||
表格必须使用以下格式:
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
| 列1 | 列2 | 列3 |
|
|
||||||
|-----|-----|-----|
|
|
||||||
| 内容1 | 内容2 | 内容3 |
|
|
||||||
| 内容4 | 内容5 | 内容6 |
|
|
||||||
```
|
|
||||||
|
|
||||||
## 6. 多语言内容管理
|
|
||||||
|
|
||||||
本项目必须同时提供英文和中文两个版本的文章,遵循以下规则:
|
|
||||||
|
|
||||||
1. 创建两个版本的Markdown文件(内容对应但语言不同)
|
|
||||||
2. 两个文件必须使用完全相同的`tagId`和`categoryId`值
|
|
||||||
3. 两个文件必须使用相同的文件名,但放置在不同的语言目录中
|
|
||||||
4. 英文版文章必须放在`/src/pages/blog/posts/`目录
|
|
||||||
5. 中文版文章必须放在`/src/pages/zh/blog/posts/`目录
|
|
||||||
|
|
||||||
文章对应示例:
|
|
||||||
|
|
||||||
- 英文版:`/src/pages/blog/posts/react-performance-tips.md`
|
|
||||||
- 中文版:`/src/pages/zh/blog/posts/react-performance-tips.md`
|
|
||||||
|
|
||||||
两个版本的文章必须保持同步更新,确保内容的一致性。
|
|
||||||
|
|
||||||
### 6.1 文档翻译规则
|
|
||||||
|
|
||||||
处理文档翻译时必须遵循以下规则:
|
|
||||||
|
|
||||||
1. 如果只有中文版文档,必须将其翻译为专业的英文版
|
|
||||||
2. 如果只有英文版文档,必须将其翻译为专业的中文版
|
|
||||||
3. 如果同时存在中英文两个版本,无需翻译,直接将文件放置到对应的语言目录中
|
|
||||||
4. 对于必需的前置元数据属性:
|
|
||||||
- 如果原始Markdown文件中已存在该属性,必须直接使用原有内容
|
|
||||||
- 如果原始Markdown文件中缺少某些必需属性,必须根据文档内容自动生成合适的属性值
|
|
||||||
- 生成的属性必须与文章内容高度相关,不得使用通用或无关的内容
|
|
||||||
|
|
||||||
## 7. 注意事项
|
|
||||||
|
|
||||||
- **图片大小**:必须优化所有图片大小,图片文件大小不得超过500KB
|
|
||||||
- **内容格式**:必须使用正确的标题层级(从h2开始)和段落分隔
|
|
||||||
- **代码示例**:所有代码示例必须使用正确的语法高亮标记
|
|
||||||
- **内部链接**:必须使用相对路径链接到网站内的其他页面
|
|
||||||
- **外部链接**:必须对所有外部链接使用完整URL,并添加`target="_blank"`属性
|
|
||||||
|
|
||||||
## 8. 故障排除
|
|
||||||
|
|
||||||
迁移过程中出现问题时,必须按以下顺序检查:
|
|
||||||
|
|
||||||
1. 前置元数据格式必须完全符合YAML语法规范
|
|
||||||
2. 文件编码必须为UTF-8,不允许使用其他编码
|
|
||||||
3. 文件路径和名称必须完全符合命名规范
|
|
||||||
4. Markdown语法必须正确无误
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
本指南是将Markdown文档迁移到`zhaoguiyang.site`博客系统的标准流程。所有迁移工作必须严格遵循本文档的规定执行。如有任何问题,请联系项目维护者。
|
|
||||||
@@ -10,9 +10,10 @@ category: "DevOps"
|
|||||||
categoryId: "devops"
|
categoryId: "devops"
|
||||||
readTime: "10 min read"
|
readTime: "10 min read"
|
||||||
---
|
---
|
||||||
|
|
||||||
本文以部署一个前端项目为示例,将手把手教你如何利用Gitea actions创建项目部署的自动化流程,对于不想使用Jenkins的小伙伴来说,Gitea actions是一个不错的`CI/CD`解决方案。
|
本文以部署一个前端项目为示例,将手把手教你如何利用Gitea actions创建项目部署的自动化流程,对于不想使用Jenkins的小伙伴来说,Gitea actions是一个不错的`CI/CD`解决方案。
|
||||||
|
|
||||||
|
<!-- truncate -->
|
||||||
|
|
||||||
## 前言
|
## 前言
|
||||||
在我们开发完一个项目后,需要将项目部署到服务器上,以便于用户可以访问。但是,每次部署都需要手动操作,这会浪费我们的时间和精力。因此,我们可以利用Gitea actions创建一个自动化流程,以便于我们快速部署项目。
|
在我们开发完一个项目后,需要将项目部署到服务器上,以便于用户可以访问。但是,每次部署都需要手动操作,这会浪费我们的时间和精力。因此,我们可以利用Gitea actions创建一个自动化流程,以便于我们快速部署项目。
|
||||||
|
|
||||||
@@ -87,7 +88,7 @@ services:
|
|||||||
### 配置说明
|
### 配置说明
|
||||||
|
|
||||||
**GITEA_RUNNER_REGISTRATION_TOKEN** 此参数为注册令牌,需要从你的gitea中进行获取,一共有三个级别,我这里直接选用组织级别的,在组织设置页中进行获取,如下图所示:
|
**GITEA_RUNNER_REGISTRATION_TOKEN** 此参数为注册令牌,需要从你的gitea中进行获取,一共有三个级别,我这里直接选用组织级别的,在组织设置页中进行获取,如下图所示:
|
||||||

|

|
||||||
|
|
||||||
其他的实例配置页面及说明请参考官方文档,有详细的说明
|
其他的实例配置页面及说明请参考官方文档,有详细的说明
|
||||||
|
|
||||||
@@ -99,6 +100,254 @@ services:
|
|||||||
|
|
||||||
成功后,可查看容器的运行以及日志,日志中会显示注册成功的信息,如下图所示:
|
成功后,可查看容器的运行以及日志,日志中会显示注册成功的信息,如下图所示:
|
||||||
|
|
||||||

|

|
||||||
|

|
||||||
|
|
||||||
|
然后我们回到你获取runner令牌的页面,进行刷新就能看到你的runner了,如下图所示:
|
||||||
|

|
||||||
|
图中的名称是根据你注册配置时的名称
|
||||||
|
|
||||||
|
> 至此,我们的runner部署就算完成了,接下来可以去在项目中使用了。
|
||||||
|
|
||||||
|
## 使用actions
|
||||||
|
|
||||||
|
gitea actions的使用方式与github actions类似,如果你不熟悉这类配置,可以先去了解下**github actions**,
|
||||||
|
作者将使用一个`vitepress`项目作为示例
|
||||||
|
|
||||||
|
### 创建配置文件
|
||||||
|
1. 在项目根目录下创建`.gitea/workflows`目录
|
||||||
|
2. 在其目录中创建`deploy.yaml`配置文件
|
||||||
|
3. 我们先写个测试配置,用于测试环境变量,如下所示:
|
||||||
|
```yaml
|
||||||
|
name: Deploy Test
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Print Environment Variables
|
||||||
|
run: env
|
||||||
|
|
||||||
|
- name: Print Current Directory
|
||||||
|
run: pwd
|
||||||
|
|
||||||
|
- name: List Files in Working Directory
|
||||||
|
run: ls -la
|
||||||
|
```
|
||||||
|
然后提交代码到仓库,我们应该就可以在仓库的actions中看到执行任务了,如下图所示:
|
||||||
|

|
||||||
|
|
||||||
|
> **ps:如果你没有看到actions执行,甚至没看到actions这个选项,可能需要你在仓库、组织或管理页面中开启actions选项**
|
||||||
|
### 配置打包
|
||||||
|
我们修改`deploy.yaml`配置文件,添加打包步骤, 我这里使用的是pnpm,请根据自己的实际情况调整一些配置,这里不过多展开
|
||||||
|
|
||||||
|
````yaml
|
||||||
|
name: Deploy docs for project
|
||||||
|
run-name: ${{ gitea.actor }} is building out Gitea Actions 🚀
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
node-version: [18.x]
|
||||||
|
steps:
|
||||||
|
# TODO 临时解决 https://github.com/go-gitea/gitea/issues/32481, 等待gitea发布1.23.0进行修复
|
||||||
|
- name: Install git
|
||||||
|
run: |
|
||||||
|
if ! command -v git &> /dev/null; then
|
||||||
|
apt-get update && apt-get install -y git
|
||||||
|
else
|
||||||
|
echo "git is already installed"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Checkout repository code
|
||||||
|
uses: https://gitea.com/actions/checkout@v4
|
||||||
|
with:
|
||||||
|
ref: 'main'
|
||||||
|
|
||||||
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: ${{ matrix.node-version }}
|
||||||
|
|
||||||
|
# Skip pnpm cache to reduce overhead
|
||||||
|
- name: Install pnpm
|
||||||
|
run: |
|
||||||
|
if ! command -v pnpm &> /dev/null; then
|
||||||
|
npm install -g pnpm@9
|
||||||
|
else
|
||||||
|
echo "pnpm is already installed"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Check Node.js and pnpm versions
|
||||||
|
run: |
|
||||||
|
echo "pnpm version ===>" && pnpm -v
|
||||||
|
echo "node version ===>" && node -v
|
||||||
|
|
||||||
|
# Simplify node_modules handling without caching
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
if [ ! -d "node_modules" ] || [ "$(find package.json -newer node_modules)" ]; then
|
||||||
|
echo "Dependencies are outdated or missing, installing..."
|
||||||
|
pnpm install
|
||||||
|
else
|
||||||
|
echo "Dependencies are up-to-date, skipping installation."
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Build docs
|
||||||
|
run: pnpm run docs:build
|
||||||
|
````
|
||||||
|
|
||||||
|
> **特意说明:安装git是为了修复目前gitea actions中无法通过`actions/checkout`检出代码的问题,此问题预计会在`v1.23.0`中修复,目前我们只能这样处理, 但据作者的观察发现好像与使用的镜像版本也有关系,如果是`ubuntu-latest`好像就不用安装,请以实际情况为准**
|
||||||
|
|
||||||
|
如果一切顺利,那么你应该可以看到工作流中完成了打包任务,如图所示
|
||||||
|

|
||||||
|
|
||||||
|
### 部署项目
|
||||||
|
|
||||||
|
部署代码的原理,实际上是通过`ssh`的方式连接到目标服务器并执行部署脚本,因此我们需要先配置好SSH,然后使用`actions` [easingthemes/ssh-deploy](https://github.com/easingthemes/ssh-deploy) 连接到目标服务器并推送代码即可
|
||||||
|
|
||||||
|
#### 配置SSH
|
||||||
|
这一步骤实际上是为服务器配置一个用户并支持`SSH`登录,也就是免密登录,因此我们在**目标服务器**依次使用以下命令,作者使用的`Debian 12`,请根据实际情况调整命令!
|
||||||
|
|
||||||
|
##### 创建用户(建议创建一个操作部署目录的用户,不要使用root用户!!!)
|
||||||
|
```bash
|
||||||
|
sudo adduser deployuser # 请根据自己实际情况修改用户名
|
||||||
|
```
|
||||||
|
创建成功后,可以查看是否存在`/home/deployuser`目录,不存在则可能需要手动创建
|
||||||
|
|
||||||
|
##### 创建密钥对
|
||||||
|
我们需要先将用户切换到`deployuser`用户下,然后执行以下命令
|
||||||
|
```bash
|
||||||
|
# 1. 创建公私钥
|
||||||
|
ssh-keygen -t rsa -b 4096 -C ""
|
||||||
|
# 将公钥内容添加到 authorized_keys 文件
|
||||||
|
echo ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
|
||||||
|
# 设置正确的权限
|
||||||
|
chmod 600 ~/.ssh/authorized_keys
|
||||||
|
chmod 700 ~/.ssh
|
||||||
|
```
|
||||||
|
##### 赋予特定目录的读写权限(可跳过)
|
||||||
|
这里需要`root`权限的用户操作
|
||||||
|
```bash
|
||||||
|
# 1. 创建目录
|
||||||
|
mkdir -p /var/www/html/project
|
||||||
|
# 2. 修改目录权限
|
||||||
|
sudo chown deployuser:deployuser /var/www/project
|
||||||
|
sudo chmod 700 /var/www/project
|
||||||
|
```
|
||||||
|
由于作者这里使用了`1panel`进行管理网站所以目录就是自动生成的目录,与此有所出入,但流程步骤一致,请根据自己实际情况修改
|
||||||
|
|
||||||
|
#### 在gitea中配置密钥信息
|
||||||
|
|
||||||
|
1. 在你的gitea的个人、组织或管理的actions页面中,点击`密钥`,将我们刚刚在服务器中生成的私钥复制到`密钥`中,然后点击`添加密钥`即可
|
||||||
|
2. 因为后续我们需要用到服务器IP、用户名,这里也建议配置到密钥或变量中,方便后续使用。
|
||||||
|
|
||||||
|
作者这里,将私钥、服务器IP、用户名配置到了密钥中,如图所示
|
||||||
|

|
||||||
|
|
||||||
|
到这里我们就完成了部署项目所需要的配置了,接下来我们就可以开始部署流程了。
|
||||||
|
|
||||||
|
> ps:由于`easingthemes/ssh-deploy`需要使用`rsync`执行脚本命令,所以在镜像容器中或者目标服务器都需要依赖此工具,如果不存在,就需要提前安装好,特别是**目标服务器**, 一般需要用root用户或者有安装权限的用户操作
|
||||||
|
|
||||||
|
### 项目部署
|
||||||
|
|
||||||
|
我们在`deploy.yml`中,添加以下代码,注意格式!!!
|
||||||
|
|
||||||
|
````yaml
|
||||||
|
- name: ssh deploy
|
||||||
|
uses: easingthemes/ssh-deploy@v5.1.0
|
||||||
|
with:
|
||||||
|
SSH_PRIVATE_KEY: ${{ secrets.SH_SSH_PRIVATE_KEY }}
|
||||||
|
REMOTE_HOST: ${{ secrets.SH_REMOTE_HOST }}
|
||||||
|
REMOTE_USER: ${{ secrets.SH_REMOTE_USER }}
|
||||||
|
SOURCE: "/.vitepress/dist/"
|
||||||
|
TARGET: "/1Panel/1panel/apps/openresty/openresty/www/sites/demo.zhaoguiyang.cn/index/dist" # 请根据实际情况修改为你的部署目录
|
||||||
|
EXCLUDE: "/node_modules/"
|
||||||
|
````
|
||||||
|
如果一切顺利的话,你就会看到actions执行成功,并且在你的部署目录下,有一个dist目录存在了,如下图所示:
|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
接下来,你就只需要使用`nginx`之类的工具指向此目录,就可以访问了。
|
||||||
|
|
||||||
|
> ps: 如果你在上面这个步骤出现了错误,请仔细查看错误日志,根据作者的经验来说,大概率是出现在ssh密钥和权限处理的这两个问题上,如果你使用的不是`ubuntu-latest`,那你可能还需根据报错信息,安装一些必须的工具,如:`git`、`rsync`等
|
||||||
|
|
||||||
|
|
||||||
|
### 完整配置
|
||||||
|
|
||||||
|
````yaml
|
||||||
|
name: Deploy docs for project
|
||||||
|
run-name: ${{ gitea.actor }} is building out Gitea Actions 🚀
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
node-version: [18.x]
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository code
|
||||||
|
uses: https://gitea.com/actions/checkout@v4
|
||||||
|
with:
|
||||||
|
ref: 'main'
|
||||||
|
|
||||||
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: ${{ matrix.node-version }}
|
||||||
|
|
||||||
|
# Skip pnpm cache to reduce overhead
|
||||||
|
- name: Install pnpm
|
||||||
|
run: |
|
||||||
|
if ! command -v pnpm &> /dev/null; then
|
||||||
|
npm install -g pnpm@9
|
||||||
|
else
|
||||||
|
echo "pnpm is already installed"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Check Node.js and pnpm versions
|
||||||
|
run: |
|
||||||
|
echo "pnpm version ===>" && pnpm -v
|
||||||
|
echo "node version ===>" && node -v
|
||||||
|
|
||||||
|
# Simplify node_modules handling without caching
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
if [ ! -d "node_modules" ] || [ "$(find package.json -newer node_modules)" ]; then
|
||||||
|
echo "Dependencies are outdated or missing, installing..."
|
||||||
|
pnpm install
|
||||||
|
else
|
||||||
|
echo "Dependencies are up-to-date, skipping installation."
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Build docs
|
||||||
|
run: pnpm run docs:build
|
||||||
|
|
||||||
|
- name: ssh deploy
|
||||||
|
uses: easingthemes/ssh-deploy@v5.1.0
|
||||||
|
with:
|
||||||
|
SSH_PRIVATE_KEY: ${{ secrets.SH_SSH_PRIVATE_KEY }}
|
||||||
|
REMOTE_HOST: ${{ secrets.SH_REMOTE_HOST }}
|
||||||
|
REMOTE_USER: ${{ secrets.SH_REMOTE_USER }}
|
||||||
|
SOURCE: "/.vitepress/dist/"
|
||||||
|
TARGET: "/1Panel/1panel/apps/openresty/openresty/www/sites/demo.zhaoguiyang.cn/index/dist" # 请根据实际情况修改为你的部署目录
|
||||||
|
EXCLUDE: "/node_modules/"
|
||||||
|
|
||||||
|
````
|
||||||
|
|
||||||
然后我们回到你获取runner令牌的页面,进行刷新就能看到你的runner了。
|
|
||||||
@@ -1,350 +0,0 @@
|
|||||||
---
|
|
||||||
authors: [joyZhao]
|
|
||||||
title: 利用Gitea actions创建项目部署的自动化流程
|
|
||||||
tags: [gitea, actions, CI/CD, 自动化部署]
|
|
||||||
---
|
|
||||||
|
|
||||||
本文以部署一个前端项目为示例,将手把手教你如何利用Gitea actions创建项目部署的自动化流程,对于不想使用Jenkins的小伙伴来说,Gitea actions是一个不错的`CI/CD`解决方案。
|
|
||||||
|
|
||||||
<!-- truncate -->
|
|
||||||
|
|
||||||
## 前言
|
|
||||||
在我们开发完一个项目后,需要将项目部署到服务器上,以便于用户可以访问。但是,每次部署都需要手动操作,这会浪费我们的时间和精力。因此,我们可以利用Gitea actions创建一个自动化流程,以便于我们快速部署项目。
|
|
||||||
|
|
||||||
## 什么是Gitea actions
|
|
||||||
Gitea actions是Gitea的一个功能,它允许我们创建自动化流程,以便于我们快速部署项目。Gitea actions可以执行各种任务,例如构建、测试、部署等。Gitea actions可以使用各种编程语言和工具,例如Python、Java、Docker等。并且Gitea actions在配置上尽量与GitHub actions的配置兼容,因此,如果你已经熟悉了GitHub actions,那么你也可以轻松地使用Gitea actions。
|
|
||||||
详见官方文档:[Gitea actions](https://docs.gitea.com/zh-cn/usage/actions/overview)
|
|
||||||
|
|
||||||
## 准备工作
|
|
||||||
在我们开始创建此流程前,首先你需要准备以下资料:
|
|
||||||
1. 一台服务器,最好拥有root权限(会安装一些工具)
|
|
||||||
2. 一个已部署的Gitea仓库,版本至少需要>=`v1.19`,官方强烈建议使用`v1.20`或更高版本
|
|
||||||
3. docker环境(非必须, 用在部署runner的主机上)
|
|
||||||
|
|
||||||
> ps: 作者这里服务器准备的是:一台打包服务器 + 一台部署(目标)服务器, 你可以只用一台服务器,但注意环境的隔离
|
|
||||||
|
|
||||||
请在进行后续步骤前,确保已完成所有的准备工作,具体的安装配置,请参考官方文档,这里我不会再赘述。[安装](https://docs.gitea.com/zh-cn/category/installation)
|
|
||||||
|
|
||||||
如果你使用**1panel面板**,可直接在应用商店中一键完成安装,作者就就是使用此方式。
|
|
||||||
|
|
||||||
>注意:在版本 < `v1.21.0`之前的版本,需要在配置文件中,开启`actions`功能,具体请参考官方文档[配置](https://docs.gitea.com/zh-cn/usage/actions/quickstart),之后的版本则是默认开启。
|
|
||||||
|
|
||||||
本教程使用的Gitea版本为`v1.22.6` !
|
|
||||||
|
|
||||||
|
|
||||||
## 配置Runner
|
|
||||||
在Gitea actions中,运行Job,都是通过Runner来执行的,因此,我们需要先配置Runner,以便于我们后续的部署流程。有两种安装方式,可直接安装到主机上,也可以通过docker容器中,这里作者将通过docker安装,为避免过多的资源消耗,可以将其安装到一个单独的主机中(ps:对于国内用户,可以选择一台香港服务器,这样运行job的速度会更快😄), 作者选择的主机就是一台香港的VPS
|
|
||||||
|
|
||||||
### 下载act_Runner
|
|
||||||
|
|
||||||
首先我们需要下载此工具,用来注册或者生成配置[下载地址](https://gitea.com/gitea/act_runner/releases),请在此页面中选择与你的系统对应的版本进行下载,下载完成后,上传到服务器中,这里我是上传到了服务器中的`/gitea_runner2`目录下。也可以使用`curl`等工具直接下载, 可直接使用以下命令,但注意名称和下载地址,我的系统是`Debain12 x86_64`,因此下载的是`act_runner-0.2.11-linux-amd64`。
|
|
||||||
|
|
||||||
```bash
|
|
||||||
curl -o act_runner2 https://gitea.com/gitea/act_runner/releases/download/v0.2.11/act_runner-0.2.11-linux-amd64
|
|
||||||
```
|
|
||||||
完成后,设置下执行权限
|
|
||||||
```bash
|
|
||||||
chmod +x act_runner2 # 注意文件名,请根据实际情况修改
|
|
||||||
|
|
||||||
./act_runner --version # 看到版本信息就代表成功了
|
|
||||||
```
|
|
||||||
### 生成配置
|
|
||||||
```
|
|
||||||
./act_runner2 generate-config > config.yaml
|
|
||||||
```
|
|
||||||
一般情况下默认的配置就够了,如果你有其他的需求请自行修改`config.yaml`。
|
|
||||||
|
|
||||||
**由于作者选用docker安装的方式,所以如果你选用直接在主机安装的方式,可以跳过后续的安装步骤,参考官方文档进行安装[直接安装](https://docs.gitea.com/zh-cn/usage/actions/quickstart)**
|
|
||||||
|
|
||||||
### 注册runner
|
|
||||||
|
|
||||||
这里我选择通过`docker-compose.yml`配置的方式进行注册
|
|
||||||
|
|
||||||
**注意: 将配置中的参数结合你自己的情况修改,以下配置仅供参考!!!**
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
version: "3.8"
|
|
||||||
services:
|
|
||||||
runner:
|
|
||||||
image: gitea/act_runner:latest
|
|
||||||
environment:
|
|
||||||
CONFIG_FILE: /config.yaml
|
|
||||||
GITEA_INSTANCE_URL: "<your_gitea.com>"
|
|
||||||
GITEA_RUNNER_REGISTRATION_TOKEN: "<your_registration_token_here>"
|
|
||||||
GITEA_RUNNER_NAME: "act_vps_runner2"
|
|
||||||
GITEA_RUNNER_LABELS: "act_vps_runner2"
|
|
||||||
volumes:
|
|
||||||
- /gitea_runner2/config.yaml:/config.yaml
|
|
||||||
- /gitea_runner2/runner_data/data:/data
|
|
||||||
- /gitea_runner2/runner_data/cache:/root/.cache
|
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
|
||||||
```
|
|
||||||
### 配置说明
|
|
||||||
|
|
||||||
**GITEA_RUNNER_REGISTRATION_TOKEN** 此参数为注册令牌,需要从你的gitea中进行获取,一共有三个级别,我这里直接选用组织级别的,在组织设置页中进行获取,如下图所示:
|
|
||||||

|
|
||||||
|
|
||||||
其他的实例配置页面及说明请参考官方文档,有详细的说明
|
|
||||||
|
|
||||||
**如果您无法看到设置页面,请确保您具有正确的权限并且已启用 Actions, 检查Gitea版本 !!!**
|
|
||||||
|
|
||||||
### 运行并生成runner
|
|
||||||
|
|
||||||
由于作者使用1panel面板,因此直接在容器选项中编排即可,如果你没有使用此类的可视化工具,就需要手动执行``docker-compose up -d``
|
|
||||||
|
|
||||||
成功后,可查看容器的运行以及日志,日志中会显示注册成功的信息,如下图所示:
|
|
||||||
|
|
||||||

|
|
||||||

|
|
||||||
|
|
||||||
然后我们回到你获取runner令牌的页面,进行刷新就能看到你的runner了,如下图所示:
|
|
||||||

|
|
||||||
图中的名称是根据你注册配置时的名称
|
|
||||||
|
|
||||||
> 至此,我们的runner部署就算完成了,接下来可以去在项目中使用了。
|
|
||||||
|
|
||||||
## 使用actions
|
|
||||||
|
|
||||||
gitea actions的使用方式与github actions类似,如果你不熟悉这类配置,可以先去了解下**github actions**,
|
|
||||||
作者将使用一个`vitepress`项目作为示例
|
|
||||||
|
|
||||||
### 创建配置文件
|
|
||||||
1. 在项目根目录下创建`.gitea/workflows`目录
|
|
||||||
2. 在其目录中创建`deploy.yaml`配置文件
|
|
||||||
3. 我们先写个测试配置,用于测试环境变量,如下所示:
|
|
||||||
```yaml
|
|
||||||
name: Deploy Test
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
deploy:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Print Environment Variables
|
|
||||||
run: env
|
|
||||||
|
|
||||||
- name: Print Current Directory
|
|
||||||
run: pwd
|
|
||||||
|
|
||||||
- name: List Files in Working Directory
|
|
||||||
run: ls -la
|
|
||||||
```
|
|
||||||
然后提交代码到仓库,我们应该就可以在仓库的actions中看到执行任务了,如下图所示:
|
|
||||||

|
|
||||||
|
|
||||||
> **ps:如果你没有看到actions执行,甚至没看到actions这个选项,可能需要你在仓库、组织或管理页面中开启actions选项**
|
|
||||||
### 配置打包
|
|
||||||
我们修改`deploy.yaml`配置文件,添加打包步骤, 我这里使用的是pnpm,请根据自己的实际情况调整一些配置,这里不过多展开
|
|
||||||
|
|
||||||
````yaml
|
|
||||||
name: Deploy docs for project
|
|
||||||
run-name: ${{ gitea.actor }} is building out Gitea Actions 🚀
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
jobs:
|
|
||||||
deploy:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
node-version: [18.x]
|
|
||||||
steps:
|
|
||||||
# TODO 临时解决 https://github.com/go-gitea/gitea/issues/32481, 等待gitea发布1.23.0进行修复
|
|
||||||
- name: Install git
|
|
||||||
run: |
|
|
||||||
if ! command -v git &> /dev/null; then
|
|
||||||
apt-get update && apt-get install -y git
|
|
||||||
else
|
|
||||||
echo "git is already installed"
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Checkout repository code
|
|
||||||
uses: https://gitea.com/actions/checkout@v4
|
|
||||||
with:
|
|
||||||
ref: 'main'
|
|
||||||
|
|
||||||
- name: Use Node.js ${{ matrix.node-version }}
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: ${{ matrix.node-version }}
|
|
||||||
|
|
||||||
# Skip pnpm cache to reduce overhead
|
|
||||||
- name: Install pnpm
|
|
||||||
run: |
|
|
||||||
if ! command -v pnpm &> /dev/null; then
|
|
||||||
npm install -g pnpm@9
|
|
||||||
else
|
|
||||||
echo "pnpm is already installed"
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Check Node.js and pnpm versions
|
|
||||||
run: |
|
|
||||||
echo "pnpm version ===>" && pnpm -v
|
|
||||||
echo "node version ===>" && node -v
|
|
||||||
|
|
||||||
# Simplify node_modules handling without caching
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
if [ ! -d "node_modules" ] || [ "$(find package.json -newer node_modules)" ]; then
|
|
||||||
echo "Dependencies are outdated or missing, installing..."
|
|
||||||
pnpm install
|
|
||||||
else
|
|
||||||
echo "Dependencies are up-to-date, skipping installation."
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Build docs
|
|
||||||
run: pnpm run docs:build
|
|
||||||
````
|
|
||||||
|
|
||||||
> **特意说明:安装git是为了修复目前gitea actions中无法通过`actions/checkout`检出代码的问题,此问题预计会在`v1.23.0`中修复,目前我们只能这样处理, 但据作者的观察发现好像与使用的镜像版本也有关系,如果是`ubuntu-latest`好像就不用安装,请以实际情况为准**
|
|
||||||
|
|
||||||
如果一切顺利,那么你应该可以看到工作流中完成了打包任务,如图所示
|
|
||||||

|
|
||||||
|
|
||||||
### 部署项目
|
|
||||||
|
|
||||||
部署代码的原理,实际上是通过`ssh`的方式连接到目标服务器并执行部署脚本,因此我们需要先配置好SSH,然后使用`actions` [easingthemes/ssh-deploy](https://github.com/easingthemes/ssh-deploy) 连接到目标服务器并推送代码即可
|
|
||||||
|
|
||||||
#### 配置SSH
|
|
||||||
这一步骤实际上是为服务器配置一个用户并支持`SSH`登录,也就是免密登录,因此我们在**目标服务器**依次使用以下命令,作者使用的`Debian 12`,请根据实际情况调整命令!
|
|
||||||
|
|
||||||
##### 创建用户(建议创建一个操作部署目录的用户,不要使用root用户!!!)
|
|
||||||
```bash
|
|
||||||
sudo adduser deployuser # 请根据自己实际情况修改用户名
|
|
||||||
```
|
|
||||||
创建成功后,可以查看是否存在`/home/deployuser`目录,不存在则可能需要手动创建
|
|
||||||
|
|
||||||
##### 创建密钥对
|
|
||||||
我们需要先将用户切换到`deployuser`用户下,然后执行以下命令
|
|
||||||
```bash
|
|
||||||
# 1. 创建公私钥
|
|
||||||
ssh-keygen -t rsa -b 4096 -C ""
|
|
||||||
# 将公钥内容添加到 authorized_keys 文件
|
|
||||||
echo ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
|
|
||||||
# 设置正确的权限
|
|
||||||
chmod 600 ~/.ssh/authorized_keys
|
|
||||||
chmod 700 ~/.ssh
|
|
||||||
```
|
|
||||||
##### 赋予特定目录的读写权限(可跳过)
|
|
||||||
这里需要`root`权限的用户操作
|
|
||||||
```bash
|
|
||||||
# 1. 创建目录
|
|
||||||
mkdir -p /var/www/html/project
|
|
||||||
# 2. 修改目录权限
|
|
||||||
sudo chown deployuser:deployuser /var/www/project
|
|
||||||
sudo chmod 700 /var/www/project
|
|
||||||
```
|
|
||||||
由于作者这里使用了`1panel`进行管理网站所以目录就是自动生成的目录,与此有所出入,但流程步骤一致,请根据自己实际情况修改
|
|
||||||
|
|
||||||
#### 在gitea中配置密钥信息
|
|
||||||
|
|
||||||
1. 在你的gitea的个人、组织或管理的actions页面中,点击`密钥`,将我们刚刚在服务器中生成的私钥复制到`密钥`中,然后点击`添加密钥`即可
|
|
||||||
2. 因为后续我们需要用到服务器IP、用户名,这里也建议配置到密钥或变量中,方便后续使用。
|
|
||||||
|
|
||||||
作者这里,将私钥、服务器IP、用户名配置到了密钥中,如图所示
|
|
||||||

|
|
||||||
|
|
||||||
到这里我们就完成了部署项目所需要的配置了,接下来我们就可以开始部署流程了。
|
|
||||||
|
|
||||||
> ps:由于`easingthemes/ssh-deploy`需要使用`rsync`执行脚本命令,所以在镜像容器中或者目标服务器都需要依赖此工具,如果不存在,就需要提前安装好,特别是**目标服务器**, 一般需要用root用户或者有安装权限的用户操作
|
|
||||||
|
|
||||||
### 项目部署
|
|
||||||
|
|
||||||
我们在`deploy.yml`中,添加以下代码,注意格式!!!
|
|
||||||
|
|
||||||
````yaml
|
|
||||||
- name: ssh deploy
|
|
||||||
uses: easingthemes/ssh-deploy@v5.1.0
|
|
||||||
with:
|
|
||||||
SSH_PRIVATE_KEY: ${{ secrets.SH_SSH_PRIVATE_KEY }}
|
|
||||||
REMOTE_HOST: ${{ secrets.SH_REMOTE_HOST }}
|
|
||||||
REMOTE_USER: ${{ secrets.SH_REMOTE_USER }}
|
|
||||||
SOURCE: "/.vitepress/dist/"
|
|
||||||
TARGET: "/1Panel/1panel/apps/openresty/openresty/www/sites/demo.zhaoguiyang.cn/index/dist" # 请根据实际情况修改为你的部署目录
|
|
||||||
EXCLUDE: "/node_modules/"
|
|
||||||
````
|
|
||||||
如果一切顺利的话,你就会看到actions执行成功,并且在你的部署目录下,有一个dist目录存在了,如下图所示:
|
|
||||||

|
|
||||||

|
|
||||||
|
|
||||||
接下来,你就只需要使用`nginx`之类的工具指向此目录,就可以访问了。
|
|
||||||
|
|
||||||
> ps: 如果你在上面这个步骤出现了错误,请仔细查看错误日志,根据作者的经验来说,大概率是出现在ssh密钥和权限处理的这两个问题上,如果你使用的不是`ubuntu-latest`,那你可能还需根据报错信息,安装一些必须的工具,如:`git`、`rsync`等
|
|
||||||
|
|
||||||
|
|
||||||
### 完整配置
|
|
||||||
|
|
||||||
````yaml
|
|
||||||
name: Deploy docs for project
|
|
||||||
run-name: ${{ gitea.actor }} is building out Gitea Actions 🚀
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
jobs:
|
|
||||||
deploy:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
node-version: [18.x]
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository code
|
|
||||||
uses: https://gitea.com/actions/checkout@v4
|
|
||||||
with:
|
|
||||||
ref: 'main'
|
|
||||||
|
|
||||||
- name: Use Node.js ${{ matrix.node-version }}
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: ${{ matrix.node-version }}
|
|
||||||
|
|
||||||
# Skip pnpm cache to reduce overhead
|
|
||||||
- name: Install pnpm
|
|
||||||
run: |
|
|
||||||
if ! command -v pnpm &> /dev/null; then
|
|
||||||
npm install -g pnpm@9
|
|
||||||
else
|
|
||||||
echo "pnpm is already installed"
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Check Node.js and pnpm versions
|
|
||||||
run: |
|
|
||||||
echo "pnpm version ===>" && pnpm -v
|
|
||||||
echo "node version ===>" && node -v
|
|
||||||
|
|
||||||
# Simplify node_modules handling without caching
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
if [ ! -d "node_modules" ] || [ "$(find package.json -newer node_modules)" ]; then
|
|
||||||
echo "Dependencies are outdated or missing, installing..."
|
|
||||||
pnpm install
|
|
||||||
else
|
|
||||||
echo "Dependencies are up-to-date, skipping installation."
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Build docs
|
|
||||||
run: pnpm run docs:build
|
|
||||||
|
|
||||||
- name: ssh deploy
|
|
||||||
uses: easingthemes/ssh-deploy@v5.1.0
|
|
||||||
with:
|
|
||||||
SSH_PRIVATE_KEY: ${{ secrets.SH_SSH_PRIVATE_KEY }}
|
|
||||||
REMOTE_HOST: ${{ secrets.SH_REMOTE_HOST }}
|
|
||||||
REMOTE_USER: ${{ secrets.SH_REMOTE_USER }}
|
|
||||||
SOURCE: "/.vitepress/dist/"
|
|
||||||
TARGET: "/1Panel/1panel/apps/openresty/openresty/www/sites/demo.zhaoguiyang.cn/index/dist" # 请根据实际情况修改为你的部署目录
|
|
||||||
EXCLUDE: "/node_modules/"
|
|
||||||
|
|
||||||
````
|
|
||||||
|
|
||||||
|
|
||||||
到这里,本文就结束了,如有错误,请多多谅解,希望给有需要的小伙伴带来一些思路和帮助
|
|
||||||
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
---
|
|
||||||
authors: [joyZhao]
|
|
||||||
title: Docusaurus v3中使用Tailwind Css的样式
|
|
||||||
tags: [docusaurus, tailwindcss]
|
|
||||||
---
|
|
||||||
|
|
||||||
今天来分享一下如何在Docusaurus v3中使用Tailwind Css的样式。
|
|
||||||
<!-- truncate -->
|
|
||||||
|
|
||||||
## 安装相关依赖
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm install tailwindcss
|
|
||||||
```
|
|
||||||
## 配置tailwind.config.js
|
|
||||||
|
|
||||||
```js
|
|
||||||
/** @type {import('tailwindcss').Config} */
|
|
||||||
module.exports = {
|
|
||||||
content: [
|
|
||||||
"./src/**/*.{js,jsx,ts,tsx,md,mdx}",
|
|
||||||
"./docs/**/*.{md,mdx}",
|
|
||||||
],
|
|
||||||
theme: {
|
|
||||||
screens: {
|
|
||||||
xs: '480px',
|
|
||||||
sm: '576px',
|
|
||||||
md: '768px',
|
|
||||||
lg: '998px',
|
|
||||||
xl: '1200px',
|
|
||||||
'2xl': '1400px',
|
|
||||||
},
|
|
||||||
extend: {
|
|
||||||
fontFamily: {
|
|
||||||
sans: 'var(--ifm-font-family-base)',
|
|
||||||
firacode: 'var(--font-family-firacode)',
|
|
||||||
kaiti: 'var(--font-family-kaiti)',
|
|
||||||
},
|
|
||||||
colors: {
|
|
||||||
'font-color': 'var(--ifm-font-color-base)',
|
|
||||||
'link-color': 'var(--ifm-link-color)',
|
|
||||||
'link-hover-color': 'var(--ifm-link-hover-color)',
|
|
||||||
primary: 'var(--ifm-color-primary)',
|
|
||||||
'primary-light': 'var(--ifm-color-primary-light)',
|
|
||||||
'primary-lighter': 'var(--ifm-color-primary-lighter)',
|
|
||||||
'primary-lightest': 'var(--ifm-color-primary-lightest)',
|
|
||||||
'primary-dark': 'var(--ifm-color-primary-dark)',
|
|
||||||
'primary-darker': 'var(--ifm-color-primary-darker)',
|
|
||||||
'primary-darkest': 'var(--ifm-color-primary-darkest)',
|
|
||||||
},
|
|
||||||
boxShadow: {
|
|
||||||
nysm: '0 0 2px 0 rgb(0 0 0 / 0.05)',
|
|
||||||
ny: '0 0 3px 0 rgb(0 0 0 / 0.1), 0 0 2px - 1px rgb(0 0 0 / 0.1)',
|
|
||||||
nymd: '0 0 6px -1px rgb(0 0 0 / 0.1), 0 0 4px -2px rgb(0 0 0 / 0.1)',
|
|
||||||
nylg: '0 0 15px -3px rgb(0 0 0 / 0.1), 0 0 6px -4px rgb(0 0 0 / 0.1)',
|
|
||||||
spread: '0 5px 40px rgb(0 0 0 / 0.1)',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
plugins: [],
|
|
||||||
darkMode: ["class", '[data-theme="dark"]'],
|
|
||||||
corePlugins: {
|
|
||||||
preflight: false,
|
|
||||||
},
|
|
||||||
blocklist: ["container"],
|
|
||||||
}
|
|
||||||
```
|
|
||||||
## 创建tailwind.css
|
|
||||||
|
|
||||||
在`src/css`目录下创建`tailwind.css`文件,并写入以下内容:
|
|
||||||
|
|
||||||
```css
|
|
||||||
@tailwind base;
|
|
||||||
@tailwind components;
|
|
||||||
@tailwind utilities;
|
|
||||||
```
|
|
||||||
**注意:创建完成后是需要在custom.css中导入tailwind.css的,否则tailwind样式不会生效**
|
|
||||||
|
|
||||||
## 创建postcss.config.js
|
|
||||||
|
|
||||||
在项目根目录下创建`postcss.config.js`文件,并写入以下内容:
|
|
||||||
|
|
||||||
```js
|
|
||||||
module.exports = {
|
|
||||||
plugins: {
|
|
||||||
tailwindcss: {},
|
|
||||||
autoprefixer: {},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
@@ -1,132 +0,0 @@
|
|||||||
---
|
|
||||||
id: git-commit-rules
|
|
||||||
title: Git提交规范
|
|
||||||
author: Joy Zhao
|
|
||||||
sidebar_position: 2
|
|
||||||
---
|
|
||||||
|
|
||||||
## commit message ( 三部分组成 )
|
|
||||||
|
|
||||||
### Header( 必需)
|
|
||||||
|
|
||||||
包括三个字段:
|
|
||||||
|
|
||||||
`type`(必需)
|
|
||||||
|
|
||||||
`scope`(可选)
|
|
||||||
|
|
||||||
`subject`(必需)
|
|
||||||
|
|
||||||
### **(1) type**
|
|
||||||
|
|
||||||
用于说明 commit 的类别,只允许使用下面7个标识:
|
|
||||||
|
|
||||||
- feat:新功能(feature)
|
|
||||||
- fix:修补bug
|
|
||||||
- docs:文档(documentation)
|
|
||||||
- style: 格式(不影响代码运行的变动)
|
|
||||||
- refactor:重构(即不是新增功能,也不是修改bug的代码变动)
|
|
||||||
- test:增加测试
|
|
||||||
- chore:构建过程或辅助工具的变动
|
|
||||||
|
|
||||||
### (2)scope
|
|
||||||
|
|
||||||
`scope`用于说明 commit 影响的范围,比如数据层、控制层、视图层等等,视项目不同而不同。
|
|
||||||
|
|
||||||
### (3)subject
|
|
||||||
|
|
||||||
`subject`是 commit 目的的简短描述,不超过50个字符。
|
|
||||||
|
|
||||||
- 以动词开头,使用第一人称现在时,比如`change`,而不是`changed`或`changes`
|
|
||||||
- 第一个字母小写
|
|
||||||
- 结尾不加句号(.`)`
|
|
||||||
|
|
||||||
### Body
|
|
||||||
|
|
||||||
Body 部分是对本次 commit 的详细描述,可以分成多行
|
|
||||||
|
|
||||||
例子:
|
|
||||||
|
|
||||||
````Plain
|
|
||||||
|
|
||||||
Further paragraphs come after blank lines.
|
|
||||||
|
|
||||||
- Bullet points are okay, too
|
|
||||||
- Use a hanging indent ```
|
|
||||||
|
|
||||||
**注意点:**
|
|
||||||
|
|
||||||
1. 使用第一人称现在时,比如使用change而不是changed或changes。
|
|
||||||
2. 应该说明代码变动的动机,以及与以前行为的对比。
|
|
||||||
|
|
||||||
### Footer
|
|
||||||
|
|
||||||
### Footer 部分只用于两种情况:
|
|
||||||
|
|
||||||
**(1)不兼容变动**
|
|
||||||
|
|
||||||
如果当前代码与上一个版本不兼容,则 Footer 部分以`BREAKING CHANGE`开头,后面是对变动的描述、以及变动理由和迁移方法。
|
|
||||||
|
|
||||||
```jsx
|
|
||||||
Plain Text BREAKING CHANGE: isolate scope bindings definition has changed.
|
|
||||||
To migrate the code follow the example below:
|
|
||||||
|
|
||||||
Before:
|
|
||||||
|
|
||||||
scope: {
|
|
||||||
myAttr: 'attribute',
|
|
||||||
}
|
|
||||||
|
|
||||||
After:
|
|
||||||
|
|
||||||
scope: {
|
|
||||||
myAttr: '@',
|
|
||||||
}
|
|
||||||
|
|
||||||
The removed `inject` wasn't generaly useful for directives so there should be no code using it.
|
|
||||||
````
|
|
||||||
|
|
||||||
**(2)关闭 Issue**
|
|
||||||
|
|
||||||
如果当前 commit 针对某个issue,那么可以在 Footer 部分关闭这个 issue 。
|
|
||||||
|
|
||||||
```jsx
|
|
||||||
Plain Text Closes #234
|
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
Closes #123, #245, #992
|
|
||||||
```
|
|
||||||
|
|
||||||
### Revert ( 特殊情况 )
|
|
||||||
|
|
||||||
如果当前 commit 用于撤销以前的 commit,则必须以`revert:`开头,后面跟着被撤销 Commit 的 Header
|
|
||||||
|
|
||||||
```Plain
|
|
||||||
|
|
||||||
This reverts commit 667ecc1654a317a13331b17617d973392f415f02. ```
|
|
||||||
|
|
||||||
Body部分的格式是固定的,必须写成`This reverts commit <hash>.`,其中的`hash`是被撤销 commit 的 SHA 标识符。
|
|
||||||
|
|
||||||
如果当前 commit 与被撤销的 commit,在同一个发布(release)里面,那么它们都不会出现在 Change log 里面。如果两者在不同的发布,那么当前 commit,会出现在 Change log 的`Reverts`小标题下面
|
|
||||||
|
|
||||||
## 生成 Change log ( 三部分 )
|
|
||||||
|
|
||||||
需要所有 Commit 都符合 Angular 格式,Change log 就可以用脚本自动生成
|
|
||||||
|
|
||||||
- New features
|
|
||||||
- Bug fixes
|
|
||||||
- Breaking changes
|
|
||||||
|
|
||||||
每个部分都会罗列相关的 commit ,并且有指向这些 commit 的链接。当然,生成的文档允许手动修改,所以发布前,你还可以添加其他内容。
|
|
||||||
|
|
||||||
[conventional-changelog](<https://github.com/ajoslin/conventional-changelog>) 就是生成 Change log 的工具,运行下面的命令即可
|
|
||||||
|
|
||||||
## Commitizen
|
|
||||||
|
|
||||||
[Commitizen](<https://github.com/commitizen/cz-cli>)是一个撰写合格 Commit message 的工具
|
|
||||||
|
|
||||||
## validate-commit-msg
|
|
||||||
|
|
||||||
[validate-commit-msg](<https://github.com/kentcdodds/validate-commit-msg>) 用于检查 Node 项目的 Commit message 是否符合格式
|
|
||||||
```
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
---
|
|
||||||
id: map-traversal-traps
|
|
||||||
title: Map遍历数字的陷阱
|
|
||||||
sidebar_label: map遍历数字的陷阱
|
|
||||||
description: Map遍历数字的陷阱,['1','2','3'].map(parseInt)的返回值是什么?
|
|
||||||
---
|
|
||||||
|
|
||||||
# ['1','2','3'].map(parseInt)的返回值
|
|
||||||
|
|
||||||
> **先说结果:其运行的结果是: [1, NAN, NAN]**
|
|
||||||
|
|
||||||
## map方法
|
|
||||||
|
|
||||||
`map()`方法会创建一个新数组,其结果是该数组中的每个元素都调用一个提供的回调函数的返回值
|
|
||||||
|
|
||||||
```JavaScript
|
|
||||||
let arr = [ 1, 2, 3 ];
|
|
||||||
|
|
||||||
arr.map ( ( item, index, arr ) => item ) // 1, 2, 3 [ 1, 2, 3 ]
|
|
||||||
```
|
|
||||||
|
|
||||||
该函数接收三个参数:当前项, 下标索引, 操作的数组
|
|
||||||
|
|
||||||
## parsetInt方法
|
|
||||||
|
|
||||||
`parseInt()` 是用来解析字符串,使字符串成为指定基数的整数,parseInt的基本语法:
|
|
||||||
|
|
||||||
`parseInt(string, radix)`
|
|
||||||
|
|
||||||
**接收两个参数,第一个表示被处理的值(字符串),第二个表示为解析时的基数。radix是一个介于2-36之间的整数,返回解析后的整数值。 如果被解析参数的第一个字符无法被转化成数值类型,则返回 NaN**
|
|
||||||
|
|
||||||
```JavaScript
|
|
||||||
praseInt('111') // 111
|
|
||||||
|
|
||||||
parseInt('111', 0) // 111
|
|
||||||
|
|
||||||
// radix为0时,且string参数不以"0x"和"0"开头时,按照10为基数处理
|
|
||||||
|
|
||||||
parseInt('111', 1) // NaN 【2 <= radix <= 36】
|
|
||||||
|
|
||||||
parseInt('111', 2) // 7
|
|
||||||
```
|
|
||||||
|
|
||||||
## 结论
|
|
||||||
|
|
||||||
当运行 `[1, 2, 3].map(parseInt)` 上时实际上运行的是:
|
|
||||||
|
|
||||||
```JavaScript
|
|
||||||
['1', '2', '3'],map( parseInt('1', 0)); // radix为0时,使用默认的10进制。
|
|
||||||
|
|
||||||
['1', '2', '3'],map( parseInt('2', 0)); // radix值在2-36,无法解析,返回NaN
|
|
||||||
|
|
||||||
['1', '2', '3'],map( parseInt('3', 0)); // 基数为2,2进制数表示的数中,最大值小于3,无法解析,返回NaN
|
|
||||||
|
|
||||||
map函数返回的是一个数组,所以最后结果为[1, NaN, NaN]
|
|
||||||
```
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
---
|
|
||||||
id: browser-run-principle
|
|
||||||
title: 浏览器的运行原理
|
|
||||||
author: Joy Zhao
|
|
||||||
sidebar_position: 1
|
|
||||||
---
|
|
||||||
|
|
||||||
## 渲染流程
|
|
||||||
html → 字符串 → 渲染 → 像素点
|
|
||||||
|
|
||||||
## 一、浏览器是如何渲染页面的?
|
|
||||||
当浏览器的网络线程收到HTML文档后,会产生一个渲染任务,并将其传递给渲染主线程的消息队列。
|
|
||||||
|
|
||||||
在事件循环机制的作用下,渲染主线程取出消息队列中的渲染任务,开启渲染流程。
|
|
||||||
|
|
||||||
整个渲染流程分为多个阶段,分别是:HTML解析、样式计算 布局、分层、绘制、分快、光栅化、每个阶段都有明确的输入输出,上一个阶段的输出会成为下一个阶段的输入。
|
|
||||||
|
|
||||||
这样,整个渲染流程就形成了一套组织严密的生产流水线。
|
|
||||||
|
|
||||||
### 第一步:解析HTML
|
|
||||||
解析过程中遇到CSS解析CSS,遇到JS执行JS。为了提高解析效率,浏览器在开始解析前,会启动一个预解析的线程,率先下载HTML中的外部CSS文件和外部的JS文件。
|
|
||||||
|
|
||||||
如果主线程解析到link位置,此外部的CSS的文件还没有下载解析好,主线程不会等待,继续解析后续的HTML,这是因为下载和解析CSS的工作是在预解析线程中进行的。这就是CSS不会阻塞HTML解析的根本原因。
|
|
||||||
|
|
||||||
如果主线程解析到script位置,会停止解析HTML,转而等待JS文件下载好,并将全局代码解析执行完成后,才继续解析HTML。这是因为JS代码的执行过程可能会修改当前的DOM树,所以DOM树的生成必须暂停。这就是JS会阻塞HTML解析的根本原因。
|
|
||||||
|
|
||||||
在第一步完成后,会得到DOM树和CSSOM树,浏览器的默认样式、内部样式、外部样式、行内样式均会包含在CSSOM树中。
|
|
||||||
|
|
||||||
### 第二步:样式计算
|
|
||||||
主线程遍历得到的DOM树,依次为树中的每个节点计算出它最终的样式,称之为Computed Style。
|
|
||||||
|
|
||||||
在这一过程中,很多预设值会变成绝对值,比如red会变成rgb(255,0,0); 相对单位会变成绝对单位,比如em会变成px
|
|
||||||
|
|
||||||
这一步完成后,会得到一颗带有样式的DOM树。
|
|
||||||
|
|
||||||
### 第三步:布局
|
|
||||||
布局阶段会依次遍历DOM树的每一节点,计算每个节点的几何信息。例如节点的宽高、相对包含块的位置。
|
|
||||||
|
|
||||||
大部分时候,DOM树和布局树并非一一对应。
|
|
||||||
|
|
||||||
比如 display:noned的节点没有几何信息,因此不会生成到布局树;又比如使用了伪元素选择器,虽然DOM树中不存在这些伪元素节点,但它们拥有几何信息,所以会生成到布局树中。还有匿名行盒、匿名块盒等等都会导致DOM树和布局树无法一一对应。
|
|
||||||
|
|
||||||
### 第四步:分层
|
|
||||||
主线程会使用一套复杂的策略对整个布局树中进行分层。
|
|
||||||
|
|
||||||
分层的好处在于,将某一层改变后,仅会对该层进行后续处理,从而提升效率。
|
|
||||||
|
|
||||||
滚动条、堆叠上下文、transform、opcity 等样式都会或多或少的影响分层结果,也可以通过will-change属性更大层度的影响分层结果。
|
|
||||||
|
|
||||||
### 第五步:绘制
|
|
||||||
主线程会为每个层单独产生绘制指令集,用于描述这一层的内容该如何画出来。
|
|
||||||
|
|
||||||
完成绘制后,主线程将每个图层的绘制信息提交给合成线程,剩余工作将由合成线程完成。
|
|
||||||
|
|
||||||
合成线程首先对每个图层进行分块,将其划为更多的区域。
|
|
||||||
|
|
||||||
它会从线程池中拿取多个线程来完成分块工作。
|
|
||||||
|
|
||||||
### 第六步:光栅化
|
|
||||||
合成线程会将块信息交给GPU进程,以极高的速度完成光栅化。
|
|
||||||
|
|
||||||
GPU进程会开启多个线程来完成光栅化,并且优化处理靠近视口区域的块。
|
|
||||||
|
|
||||||
光栅化的结果,就是一块一块的位图
|
|
||||||
|
|
||||||
### 第七步:画
|
|
||||||
合成线程拿到每个层、每个块的位图后,生成一个个【指引(quad)】信息。
|
|
||||||
|
|
||||||
指引会标识出每个位图应该画到屏幕的哪个位置,以及考虑到旋转、缩放等变形。
|
|
||||||
|
|
||||||
变形发生在合成线程,与渲染主线程无关,这就是transform效率高的本质原因。
|
|
||||||
|
|
||||||
合成线程会把quad提交给GPU进程,由GPU进程产生系统调用,提交给GPU硬件,完成最终的屏幕成像。
|
|
||||||
|
|
||||||
|
|
||||||
## 什么是reflow(回流)?
|
|
||||||
reflow的本质就是重新计算layout树。
|
|
||||||
|
|
||||||
当进行了会影响布局树的操作后,需要重新计算布局树,会引发layout
|
|
||||||
|
|
||||||
为了避免连续的多次操作导致布局树反复计算,浏览器会合并这些操作,当js代码全部完成后再进行统一计算。所以,改动属性造成的reflow是异步完成的。
|
|
||||||
|
|
||||||
也同样如此,当js获取布局属性时,就可能造成无法获取到最新的布局信息。
|
|
||||||
|
|
||||||
浏览器在反复权衡下,最终决定获取属性立即reflow
|
|
||||||
|
|
||||||
## 什么是repaint(重绘)?
|
|
||||||
repaint的本质是重新根据分层信息计算了绘制指令。
|
|
||||||
|
|
||||||
当改动了可见样式后,就需要重新计算,会引发repaint。
|
|
||||||
|
|
||||||
由于元素的布局信息也属于可见样式,所以reflow一定会引起repaint
|
|
||||||
|
|
||||||
## 为什么transform的效率高?
|
|
||||||
因为transform没有样式、布局、分层、光栅化的步骤,直接进入了合成线程进行绘制。所以它的效率比直接改动样式或几何属性效率高。
|
|
||||||
Reference in New Issue
Block a user