# IP 商品化小程序

**特性**

- 使用 `gulp` 构建（支持 `typescript` 和 `scss`）
- 使用 `typescript` 编译
- 使用 `eslint` + `stylelint` + `prettier` 格式代码规范
- 使用 `commitment` 约束提交规范
- 使用 `git hook` + `lint-staged` 提交时的校验检测
- 使用 `standard-version` 生成 `CHANGELOG` 和 版本管理
- 使用公司前端代码规范 `eslint-config-tencent`
- 使用小程序官方 `typings` 库

## 安装

```bash
#  1、安装依赖
npm install
# 2、全局安装依赖
npm install -g commitizen git-cz
# 3、启动代码
npm run dev
# 4、打开微信开发者工具，导入本项目根目录
```

**命令指南**

| 命令                  | 说明                           |
| --------------------- | ------------------------------ |
| npm run dev           | 开发环境                       |
| npm run build         | 编译打包                       |
| npm run test          | 单元测试                       |
| npm run lint          | 校验代码格式                   |
| npm run stylelint     | 校验样式格式并修复             |
| npm run release:patch | 主版本号，例：v0.0.1 -> v1.0.0 |
| npm run release:minor | 次版本号，例：v0.0.1 -> v0.1.0 |
| npm run release:major | 修订号，例：v0.0.1 -> v0.0.2   |

## 开发流程

**当前项目采用类 [gitflow](https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow) 的工作流程，各个分支的职责如下：**

- `master`：主干分支，保存最新已发布版本基线的分支
- `develop`：当次迭代功能提测分支，也是对开发的功能进行集成的分支
- `release`：负责版本发布的分支，当 `develop` 分支功能测试通过，基于 `develop` 分支检出一个当前发布版本的分支
- `feature/module`：特性开发分支，基于 `develop` 检出，可以根据特性来命名（推荐：采用小写 `kebab-case` 命名），尽量语义化，如 `feature/cart`、`feature/user-order`
- `hotfix/module`：对线上缺陷进行修改工作的分支，基于当前发布版本的 `release` 分支检出

![](https://films-10014007.cos.ap-shanghai.myqcloud.com/mp-ip-commercialize/gitflow.jpeg)

其中在特性分支进行开发，完成开发之后 MR 到 `develop` 分支，触发流水自动日常构建，检查代码安全扫描、代码质量红线，如代码质量红线不通过、则无法进行 `megre`

![](https://films-10014007.cos.ap-shanghai.myqcloud.com/mp-ip-commercialize/WX20210628-161139%402x.png)

## 提交规范

项目使用 `Husky` 挂载的 git 提交前置钩子进行代码检查以及提交信息规范检查。
提交规范基于`@commitlint/config-conventional`, 需要全局安装依赖`commitizen` `git-cz`插件

```bash
npm install -g commitizen git-cz

git add .
git cz # 必须使用`git cz`约束提交规范
```

**常用的 type 类别**

- feat：新功能
- fix：bug 修复
- docs：文档更新
- style：代码的格式，标点符号的更新
- refactor：代码重构
- perf：性能优化
- test：测试更新
- build：构建系统或者包依赖更新
- ci：CI 配置，脚本文件等更新

**提交示例**

```bash
➜ mp-ip-commercialize git:(master) ✗ git add .
➜ mp-ip-commercialize git:(master) ✗ git cz
? Select the type of change that you're committing: ✏️  docs:       Documentation only changes
? Write a short, imperative mood description of the change:
  [-------------------------------------------------------------] 55 chars left
   docs: 新增文档
? Provide a longer description of the change:

? List any breaking changes
  BREAKING CHANGE:
? Issues this commit closes, e.g #123:

> mp-ip-commercialize@3.0.0 lint-staged
> lint-staged -c ./.husky/.lintstagedrc.js

✔ Preparing...
✔ Running tasks...
✔ Applying modifications...
✔ Cleaning up...
[master 0b59ddb] docs: ✏️ 新增文档
 4 files changed, 8573 insertions(+), 8674 deletions(-)
 rewrite README.md (100%)
 create mode 100644 project.config.json
 rewrite yarn.lock (90%)
```

## 组件规范

[详见](./src/components/README.md)

## 命名规范

[详见](./命名规范.md)

## 图标使用

目前使用 [`mini-program-iconfont-cli`](https://github.com/iconfont-cli/mini-program-iconfont-cli) 工具把 `iconfont` 图标批量转换成多个平台小程序的组件。不依赖字体，支持多色彩。

**使用流程**

第一步，在蓝湖导出并下载`svg`格式图标

第二步，然后在[阿里 iconfont](https://www.iconfont.cn/manage/index?spm=a313x.7781069.1998910419.13&manage_type=myprojects&projectId=2632983)上传图标, 如该项目图标库的权限，找组内成员添加

第三步，添加完图标之后，然后点击`Symbol`方式生成链接

![](https://films-10014007.cos.ap-shanghai.myqcloud.com/mp-ip-commercialize/WX20210628-155520%402x.png)

第四步，更新项目根目录中`iconfont.json`的 `symbol_url` 地址

```json
{
  "symbol_url": "//at.alicdn.com/t/font_2632983_lhrvk42ew29.js", // 图标新增或更改、都需要更新symbol_url地址
  "save_dir": "./src/components/iconfont",
  "use_rpx": true,
  "trim_icon_prefix": "icon",
  "default_icon_size": 32
}
```

第五步，生成小程序 `iconfont` 组件

```bash
npm run iconfont  # or npx iconfont-wechat
```

```
├── iconfont
│   ├── iconfont.js
│   ├── iconfont.json
│   ├── iconfont.wxml
│   └── iconfont.wxss
```

**使用**
在 `wxml` 中使用图标

```html
// 原色彩
<iconfont name="wechat" />

// 单色：红色
<iconfont name="wechat" color="red" />

// 多色：红色+橘色
<iconfont name="wechat" color="{{['red', 'orange']}}" size="300" />

// 不同格式的颜色写法
<iconfont name="wechat" color="{{['#333', 'rgb(50, 124, 39)']}}" />

// 与文字对齐
<view style="display: flex; alignItems: center;">
  <text>Hello</text>
  <iconfont name="wechat" />
</view>
```

## 扩展包说明

| 名称        | 文档地址                                 | 说明                                                     |
| ----------- | ---------------------------------------- | -------------------------------------------------------- |
| dayjs       | https://github.com/iamkun/dayjs          | `Day.js` 是一个轻量的处理时间和日期的 `JavaScript` 库    |
| mitt        | https://github.com/developit/mitt        | 事件订阅监听 - `EventEmitter`                            |
| aegis       | http://aegis.oa.com                      | `Aegis` 一站式前端监控解决方案                           |
| @vant/weapp | https://vant-contrib.gitee.io/vant-weapp | `Vant Weapp` 轻量、可靠的小程序 UI 组件库                |
| flyio       | https://github.com/wendux/fly            | 基于 `Promise`、支持请求转发的微信小程序版 `http` 请求库 |

### 版本管理

`standard-version` 是一款遵循语义化版本[semver](https://semver.org/)和 [commit message](https://www.conventionalcommits.org/en/v1.0.0/) 标准规范 的版本和 changlog 自动化工具

**主版本号.次版本号.修订号，版本号递增规则如下：**

- 主版本号(`major`)：向后不兼容的更改，增加主版本，理解为新的版本迭代
- 次版本号(`minor`)：向下兼容的功能性新增， 理解为 `Feature` 版本
- 修订号(`patch`)：向下兼容的问题修正， 理解为 `Bug fix` 版本。

```bash
npm run release:major # 例: v0.0.1 -> v1.0.0
npm run release:minor # 例: v0.0.1 -> v0.1.0
npm run release:patch # 例: v0.0.1 -> v0.0.2
```

**tag 变更规则**
建议 tag 格式为：`v${major.minor.patch}`，如 `v1.0.0`
当要发布的内容为 `bug-fix` 时，应迭代 `patch` 版本号，如这里为 `v1.0.1`
当要发布的内容为 `feature` 时，应迭代 `minor` 版本号，如这里为 `v1.1.0`
当要发布的内容为破坏性改动/重构级改动，应迭代 `major` 版本号，如这里为 `v2.0.0`

## 环境变量

**模式**

默认情况下,项目有了两个模式：

- `development` 模式用于 `cross-env NODE_ENV=development gulp dev`
- `production` 模式用于 `cross-env NODE_ENV=production gulp build`

你可以通过传递 cross-env 插件设置参数为命令行覆写默认的模式。例如，如果你想要在构建命令中使用测试环境变量：

```
cross-env NODE_ENV=test
```

你可以在你的项目根目录中放置下列文件来指定环境变量：

```
.env.[mode]         # 只在指定的模式中被载入
.env.development    # 只在开发模式中被载入
.env.production     # 只在生产模式中被载入
```

一个环境文件只包含环境变量的“键=值”对：

```
MP_APP_NOT_SECRET_CODE=some_value
```

请注意，除了 `NODE_ENV` 变量，其他变量命名规则必须以 `MP_APP` 开头

**示例：Development 模式**
假设我们有一个应用包含以下 `.env.development` 文件：

```
NODE_ENV='development'
MP_APP_TITLE='My App'
```

大致用法请参考 [Vue CLI 模式和环境变量](https://cli.vuejs.org/zh/guide/mode-and-env.html#%E6%A8%A1%E5%BC%8F)

## 项目结构

```
├── README.md           //说明文档
├── dist                //编译之后的项目文件（带 sorcemap，支持生产环境告警定位）
├── gulpfile.js
├── package.json        //项目配置
├── src                 //开发目录
│   ├── app.json        //小程序起始文件
│   ├── app.ts
│   ├── app.wxss
│   ├── assets          //资源文件
│   ├── components      //组件
│   ├── pages           //小程序相关页面
│   ├── sitemap.json
│   └── utils           //工具
├── tsconfig.json       //typescirpt配置
```

注意：`package.json`中的`dependencies`字段，依赖的包会被自动打包到`dist`里。

## Q&A

1. 解决 node 与 miniprogram-api-typings 类型冲突 （console、module、exports）
   issues：https://github.com/wechat-miniprogram/api-typings/issues/66

2. typescript 设了 parserOptions.project, 容易导致 tsconfig 没有指定的文件无法被 eslint 检查
   issues：https://git.woa.com/standards/javascript/issues/157
   解决：https://iwiki.woa.com/pages/viewpage.action?pageId=194047628

3. 关于组件`(components)`和模板`(templates)`的选择，总结以下：

- 当遇到业务模块比较独立，需要进行拆分解耦的情况，推荐使用组件写法，🌰 例子：商品列表页、地址模块、商品规格选项模块
- 当遇到页面中 UI 结存在有相同的，此时推荐使用模板写法进行复用（例外：如果遇到单页面结构比较大、比较复杂，也可以适当使用模块写法，进行分离）
- 组件`(components)` 更多关注是功能层面，独立性，而模板`(templates)`更多关注是 UI 层复用。最后模板`(templates)`可以在组件中也可以在页面中使用，看自己开发的场景
