# fish-desktop react版本

![coverage](http://gitlab.ztesoft.com/fish-x/fish-desktop-x/badges/develop/coverage.svg?job=test&style=flat-square)
![Build Status](http://gitlab.ztesoft.com/fish-x/fish-desktop-x/badges/develop/build.svg?style=flat-square)

## 什么是FISH-X

FISH-X 是 FISH 下一代新版本。与阿里技术栈保持一致，在阿里开源项目（如桌面端Ant-design)上面继续开发，而不是从零开始做。

## FISH-X 平台完整蓝图

![](/public/architecture.png)

- Fish-Desktop-X，简称 FDX
- Fish-Mobile-X，简称 FMX
- Fish-Store-X，简称 FSX
- Fish-Topo-X，简称 FTX
- Fish-Koa-X，简称 FKX
- Fish-CLI-X，简称 FCX
- Fish-Unit-Test-X，简称 FUTX
- NGWEB-DSL-X，简称 NGX

其中，Fish-CLI-X 是底层工具；

Fish-Store-X 是一个全公司共享的前端模板 Store；

NGWEB-DSL-X 是自定义领域建模语言，我们自定义自己的标签规范和语言，然后通过 NGWEB-DSL-X 映射成运行时代码，从而摆脱前端技术不稳定给公司带来的技术风险，这个思路类似于微信小程序和钉钉小程序。



## FDX特点

- 整体上，FDX 与 FMX 相同的 React 技术栈，这样做的原因是最大程度降低业务组织的学习难度。
- 从阿里开源的组件库 AntD 上 fork 分支，而不是从零开始。这样做的目的是，降低对人力的需求。因为 UI 组件库的代码量非常庞大，FDX 做完之后预计会达到 10 万行 JS 代码的规模。目前我们的 FISH 版本已经超过 7 万行 JS，长期维护这样一个庞大的代码库需要消耗比较多的人力，这是很现实的成本。这里存在一个问题，阿里目前开源的 AntD 组件库是非常互联网化的风格，组件的外观很好看，但是每个组件的 feature 都相对比较简单，而软创目前的大部分业务项目还是后台管理类的项目，这些项目需要 UI 组件的特性非常复杂，我们需要投入比较多的人力来进行扩展和改造。
- 根据实际业务抽像出的标准组件接口。 组件接口作为媒介沟通页面跟具体组件实现。比如我们用到了某一个开源的 UI 组件，我们会根据实际业务抽象出一份标准接口，对开源组件进行二次封装之后再调用。这样即使后续需要更换其他组件，也不需要对页面进行改动。所有的 UI 组件，不论是我们自己造轮子写的，还是开源的，都是按照：1. 定义接口 -> 2. 进行封装 -> 3. 实现并上传 znpm 服务器 -> 4. 项目 depencency 中引用来自 znpm 的组件 IDL。 这样的流程来进行引用。
- 支持前端界面的微服务化，解决跨业务系统界面集成的难题。同时促进 UI/UX 规范化，方便跨业务系统集成

## 本地文档及示例查看
```
yarn install

npm run docz:dev
```

## 组件发布

- 修改组件代码
- 修改根目录下 package.json 文件中`version`中的版本号(***版本号要比之前的大***)
- 根目录先执行 npm run compile 再执行 npm run dist 最后 npm publish，要切换到npm官方源进行发包。

## 官网文档更新

请至CI/CD流程pipeline中手动运行prepare和doc



# 发包流程

简介：

## 版本级别说明：

1. 'major' : 表示主要版本的发布。当进行重大功能改动或不兼容的修改时，可以选择增加主要版本号。
2. 'premajor': 表示主要版本的预发布。在进行主要版本发布之前，可以选择进行预发布，以便在发布正式版本之前进行测试和准备。
3. 'minor': 表示次要版本的发布。当进行功能添加或兼容性改进时，可以选择增加次要版本号。
4. 'preminor': 表示次要版本的预发布。在进行次要版本发布之前，可以选择进行预发布，以便在发布正式版本之前进行测试和准备。
5. 'patch': 表示补丁版本的发布。当进行错误修复或较小的改进时，可以选择增加补丁版本号。
6. 'prepatch': 表示补丁版本的预发布。在进行补丁版本发布之前，可以选择进行预发布，以便在发布正式版本之前进行测试和准备。
7. 'prerelease': 表示预发布版本。当需要在正式版本发布之前进行更多的测试和准备时，可以选择发布预发布版本

## changeset 配置项说明：

* changelog: changelog 生成方式
* commit: 不要让 changeset 在 publish 的时候帮我们做 git add
* linked: 配置哪些包要共享版本
* access: 公私有安全设定，内网建议 restricted ，开源使用 public
* baseBranch: 项目主分支
* updateInternalDependencies: 确保某包依赖的包发生 upgrade，该包也要发生 version upgrade 的衡量单位（量级）
* ignore: 不需要变动 version 的包
* ___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH: 在每次 version 变动时一定无理由 patch 抬升依赖他的那些包的版本，防止陷入 major 优先的未更新问题

### 示例配置：

```
{
"$schema": "https://unpkg.com/@changesets/config@2.0.0/schema.json",
"changelog": "@changesets/cli/changelog",
"commit": false,
"linked": [],
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": [],
"___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH": {
    "onlyUpdatePeerDependentsWhenOutOfRange": true
  }
}
```


#### 特别说明：非常重要！！！

该发布流程以 tag 为 **锚点**，去捞取 **版本变更日志**，以及**总版本变更**，所以每次发版本之后一定要检查 tag 是否发布正常

### 正式版本发布模式：

1、**合并主分支**： 将基础分支合并进来

```bash
        git merge origin/v3.0
```


2、**生成变更集**： 执行 yarn changeset ：选择版本层级 + summary

```bash
        yarn changeset
```

3、**消费预变更集**： 执行 yarn version-package

```bash
        yarn version-package
```

4、**加载变更日志**： 执行 reloadlog  遍历每个包  将这段时间的commits 安装 文件夹去归类commits 信息 追加到 每个子包的changelog 上

```bash
        yarn changelog-gen
```

5、**发包**： 执行 yarn build + changeset publish (这一步可自行斟酌，发包时机不受限制，这里第五步只做建议)

```bash
        yarn build + changeset publish
```

6、**提交变更日志**： git add . + git commit -m 'xxxx' + git push

```bash
        git add . + git commit -m 'xxxx' + git push
```

7、**生成tag**:  git tag v1.0.0 -m '初始版本'  +  git push origin v1.0.0

```bash
        git tag v1.0.0 -m '初始版本'  +  git push origin v1.0.0
```

#### 版本发布详细流程：正式版本： 单包 + 多包 两轮发包流程

测试分支20597300（基于v5 分支） 当前版本（根目录版本）1.0.1

##### 步骤1：

1. 修改pkg1 中index.ts 内容
2. commit信息 ：#10597315 v1.0.1 : pkg1 修改；
3. push;

##### 步骤2：

1. 修改pkg2中 index.ts 内容
2. commit信息：#10597315 v1.0.1 : pkg2 修改；
3. push;

##### 步骤3：（开始发版本）：

在当前分支下 合并v5分支  ： git merge origin/v5;

执行 **yarn changeset** :

1. 选择要发布的包：这里选择pkg1 和 pkg2:

![image.png](images/readme/yarn_changeset.png)

1. 选择 patch 版本级别发布；

键入summary 内容： test  upgrade;
执行 yarn  version-packages:

自动会升级 pkg1 pkg2 的版本号 ，生成对应的CHANGELOG.md, 并且应为 pkg3 引用了pkg1 ,pkg3 也会跟着升级：

![image.png](images/readme/pkg3_upgrade.png)

1. 执行 **yarn  changelog-gen** :

1、检测根目录下package 版本是否和上一次tag 版本相同，如果版本相同则 patch 级别加1

2、拉取此刻距离上一次发tag的时间段内发生的 commits

3、解析每个commit 的文件夹 是否跟当前待发布的子包有交集，如果有交集则该子包的 CHANGELOG 将这次的commit 收集进去

##### 步骤4：

执行 **git add . && git commit -m '#10597315 v1.0.2 版本变更记录' && git push**

##### 步骤5：

执行 **git tag v1.0.2 -m 'v1.0.2'  +  git push origin v1.0.2**

此刻一个 发包流程**结束** （npm publish 可自行处理），接下来基于这个版本 继续第二次版本发布

##### 步骤6：

1. 修改pkg2 中index.ts 内容；
2. commit信息 ：#20597300 v1.0.2 : pkg2 修改；
3. push;

##### 步骤7：开始第二次发包流程，类似第一次发包流程 ，简化一下

**yarn  changeset**

**yarn  version-packages**

**yarn  reloadlog**

##### 步骤8：

执行 **git add . && git commit -m '#10597315 v1.0.3 版本变更记录' && git push**

##### 步骤9：

执行 **git tag v1.0.3 -m 'v1.0.3'  +  git push origin v1.0.3**

至此第二次发包流程**结束**

### pre 预发布模式：

### 常用 预发布类型：


| 名称  | 功能                                                                                     |
| ------- | ------------------------------------------------------------------------------------------ |
| alpha | 是内部测试版，一般不向外部发布，会有很多Bug，一般只有测试人员使用                        |
| beta  | 也是测试版，这个阶段的版本会一直加入新的功能。在Alpha版之后推出                          |
| rc    | Release　Candidate) 系统平台上就是发行候选版本。RC版不会再加入新的功能了，主要着重于除错 |

### 预发布流程：

**注意：changeset 有一个bug： 当你的工作空间中，某个子包中，package.json 缺失 version 字段时，预发布流程会报错。请保持每个子包都有符合规范的version**

#### 步骤1: 进入 pre 模式， 这是使用 tag = beta 模式：

**yarn changeset pre enter beta** : 该步骤会在 .chengeset 文件夹下生成预发布配置文件 pre.json：

![image.png](images/readme/pre_beta.png)


##### 步骤2：执行 yarn changeset:

###### 1. 选择 发布pkg3

###### 2. 变更级别 patch

###### 3. 这一步骤选择的 变更级别都会转成 预变更类型

##### 步骤3：执行 yarn version-packages

生成如下升级产物

![image.png](images/readme/yarn_changeset.png)


##### 步骤4：执行 yarn reloadlog

###### 收集 commits 信息

注：

* **在pre 模式下 根目录下的version 变更规则也会保持 pre 预发布策略 ，变更层级默认 **prerelease**：**![image.png](images/readme/pre_reloadlog.png)

* **与正常发布流程不同的是，预发布不会消费预变更集 ，会在发正式版本的时候同意消费；**

##### 后续步骤同 正常发布流程，这里不做赘述...

### 常见问题：

#### 一次发两个包，但是两个包的发布级别不一样怎么处理?

在执行 yarn changeset  产生变更集的 过程中  ，

##### 第一步选中所有要发包的版本：这里选择了 pk1  和 pk2:

![image.png](images/readme/fqs_diff_pkgs.png)


##### 第二步 按下回车键 选择发布级别 可以先选 pk1 为 major  级别：

![image.png](images/readme/fqs_diff_pkgs_step2.png)


##### 第三步按下回车键，将剩下的 pkg2 设置为 minor 级别：

![image.png](images/readme/fqs_diff_pkgs_step3.png)


之后就走正常的发包流程即可：执行 yarn version-packages;

##### 结果如下：

pkg1 走的 major 级别的改动 ：1.0.2 -> 2.0.0

![image.png](images/readme/fqs_diff_pkgs_res1.png)

pkg2走的 minor  级别的改动 ：3.0.0 -> 3.0.1

![image.png](images/readme/fqs_diff_pkgs_res2.png)


### 根目录下的版本号更新策略是什么？

###### * 正常发布模式下 根目录下的版本号在 reloadlog 环节中 默认 patch 级别 加 1 ， 1.0.1 -> 1.0.2

###### * pre发布模式下   根目录下的版本号 在预发布版本 默认 prerelease, 例如：1.0.1 -> 1.0.2-beta.0 、 1.0.2-beta.0 ->  1.0.2-beta.1

###### * 退出pre模式后   根目录下所有的子包都会由 pre 版本转为 正式版本  1.0.2-beta.1 ->  1.0.2


## commit 提交规范：
规范代码提交

代码提交规范对于团队或者公司来说是非常重要的，养成良好的代码提交规范可以方便回溯，有助于对本次提交进行review，如果单纯的只是要求团队成员遵循某些代码提交规范，是很难形成强制约束的，现在我们就尝试通过工具来约束代码提交规范。

#### 使用commitizen规范commit提交格式

`commitizen` 的作用主要是为了生成标准化的 `commit message`，符合 `Angular` 规范。

一个标准化的 `commit message` 应该包含三个部分：Header、Body 和 Footer，其中的 Header 是必须的，Body 和 Footer 可以选填。

```
<type>(<scope>): <subject>
// 空一行
<body>
// 空一行
<footer>
```

#### Header 部分由三个字段组成：type（必需）、scope（可选）、subject（必需）

###### Type （必须）`type` 必须是下面的其中之一：

* feat: 增加新功能
* fix: 修复 bug
* docs: 只改动了文档相关的内容
* style: 不影响代码含义的改动，例如去掉空格、改变缩进、增删分号
* refactor: 代码重构时使用，既不是新增功能也不是代码的bud修复
* perf: 提高性能的修改
* test: 添加或修改测试代码
* build: 构建工具或者外部依赖包的修改，比如更新依赖包的版本
* ci: 持续集成的配置文件或者脚本的修改
* chore: 杂项，其他不需要修改源代码或不需要修改测试代码的修改
* revert: 撤销某次提交

###### scope（可选）:

用于说明本次提交的影响范围。`scope` 依据项目而定，例如在业务项目中可以依据菜单或者功能模块划分，如果是组件库开发，则可以依据组件划分。

###### subject（必需）:

主题包含对更改的简洁描述：

注意三点：

1. 使用祈使语气，现在时，比如使用 "change" 而不是 "changed" 或者 ”changes“
2. 第一个字母不要大写
3. 末尾不要以.结尾

###### Body（可选）:

主要包含对主题的进一步描述，同样的，应该使用祈使语气，包含本次修改的动机并将其与之前的行为进行对比。

###### Footer（可选）:

包含此次提交有关重大更改的信息，引用此次提交关闭的issue地址，如果代码的提交是不兼容变更或关闭缺陷，则Footer必需，否则可以省略。

#### 直接上手：

上述步骤适用于第一次配置，这里我们已经配置好。这里提供两种方法去提交：

##### 方法一：使用 commitizen 模板工具，直接执行以下命令：

```javascript
yarn commit
```

只需要按照提示，根据模板一步一步执行下去，即可生成符合条件的commit 信息；

##### 方法二：直接使用常规提交：

点击提交按钮 或者 **git commit** 命令，**commitlint** 会自动检验 commit 信息的合法性，按照错误提示修改即可；以feat 为例：

```bash
  git commit -m 'feat: #xxxxxx（某个任务单）：完成xxxx 新功能 '
```

##### 如何配置：

##### `commitizen` 和 `cz-conventional-changelog`

如果需要在项目中使用 `commitizen` 生成符合 `AngularJS` 规范的提交说明，还需要安装 `cz-conventional-changelog` 适配器。

```
$ yarn install -wD commitizen cz-conventional-changelog

```

工程根目录下的 `package.json` 中增加一条脚本：

```
"scripts": {
  "commit": "cz"
}
```

接下来就可以使用 `$ yarn commit` 来代替 `$ git commit` 进行代码提交了，看到下面的效果就表示已经安装成功了。

![image.png](images/readme/yarn_commit.png)


##### commitlint && husky:

前面我们提到，通过 `commitizen` && `cz-conventional-changelog` 可以规范我们的 `commit message`，但是同时也存在一个问题，如果用户不通过 `yarn commit` 来提交代码，而是直接通过 `git commit` 命令来提交代码，就能绕开 `commit message` 检查，这是我们不希望看到的。

因此接下来我们使用 `commitlint` 结合 `husky` 来对我们的提交行为进行约束。在 `git commit` 提交之前使用 `git` 钩子来验证信息，阻止不符合规范的`commit` 提交。

安装 `commitlint` 和 `husky`：

```
yarn install -wD @commitlint/cli @commitlint/config-conventional husky
```

在工程根目录下增加 `commitlint.config.js` 配置文件，指定 `commitlint` 的校验配置文件：

```
module.exports = { extends: ['@commitlint/config-conventional'] };

```

husky 配置(husky的每个版本配置不一样，具体可以参考官方文档，当前的husky是v8.0.1)。

工程根目录下的 package.json 中增加一条 script:

```javascript
"scripts": {
  "postinstall": "husky install"
}
```

该脚本会在执行完 `$ yarn install` 之后自动执行，进行 husky 的初始化，执行完毕后就会在根目录下创建一个 `.husky` 目录。

执行如下命令新增一个husky的hook：

```javascript
$ npx husky add .husky/commit-msg 'npx --no-install commitlint --edit "$1"'

```

当我们通过 git commit 提交不符合规范的代码，就会出现如下报错，并且自动退出提交流程。

![image.png](images/readme/git_commit_error.png)
