> For the complete documentation index, see [llms.txt](https://benjaken.gitbook.io/personal-space/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://benjaken.gitbook.io/personal-space/master.md).

# 关于近期小程序代码优化的总结

最近我开发小程序也有三四个月，针对开发过程中遇到的错误调试、代码优化或项目自动化构建进行总结。

### 代码检查

在梳理代码逻辑时发现很多代码不规范的地方，包括简单的js问题以及代码格式化的问题，造成了代码可读性下降，所以项目优化的第一步就是对代码风格做统一化处理。主要用到`eslint`和`prettier`。

#### 关于rpx

`rpx`是小程序官方提供的一种像素单位，可按照屏幕宽度进行自适应，小程序开发过程中建议使用rpx。但对于一些第三方框架，如`vant`，用的是`px`。所以需将对应的`px`换算为`rpx`（按照`750px`的设计稿是`1px:2rpx`）

![](/files/-MLqiNY98IlDWb1g2fMk)

因为用到[miniprogram-ci](https://developers.weixin.qq.com/miniprogram/dev/devtools/ci.html)作为构建工具（下文有提及），所以在自动化构建的过程中需要对`vant`组件库进行转换，转换具体是依赖`gulp`、`gulp-postcss`、`postcss-pxtransform` 对项目中的`px`进行转换。在gulpfile.js中增加以下代码：

```
function formatCSS(cb) {
  const processors = [
    pxtorem({
      platform: 'weapp',
      designWidth: 750
    })
  ]
  gulp
    .src(['./miniprogram_npm/**/*.wxss'])
    .pipe(postcss(processors))
    .pipe(gulp.dest('./miniprogram_npm'))
  gulp
    .src(['./pages/**/*.wxss'])
    .pipe(postcss(processors))
    .pipe(gulp.dest('./pages'))
  gulp
    .src(['./pages/**/*.less'])
    .pipe(postcss(processors))
    .pipe(gulp.dest('./pages'))
  cb()
}
```

注意这里的pxtorem配置有误，因而需要单独引用一份出来修改`deviceRatio`

```
const deviceRatio = {
  640: 2.34,
  750: 2,
  828: 1.81
}
```

#### 如何在提交前触发格式检查

为避免开发时，开发人员的风格各自不同，不符合代码规范，因而需要对代码格式进行eslint检查并自动格式化，这里主要用到`husky、lint-staged、eslint以及prettier`插件

1. 在package.json中增加配置

```
{
  "scripts": {
    "precommit": "lint-staged"
  },
  "lint-staged": {
    "pages/**/*.{js,wxs}": [
      "eslint --fix --ext .js",
      "prettier ./ --write",
      "git add"
    ]
  },
  "devDependencies": {
    "eslint": "^5.0.0",
    "eslint-config-ali": "^2.0.1",
    "eslint-plugin-import": "^2.6.0",
    "eslint-plugin-react": "^7.1.0",
    "husky": "^0.14.2",
    "babel-eslint": "^8.1.1",
    "lint-staged": "^4.0.0",
    "prettier":"^1.16.4",
    "eslint-plugin-prettier":"^3.0.1",
    "eslint-config-prettier":"^4.0.0"
  },
}

```

2\. 在`.eslintrc.js`增加eslint扫描配置

```
module.exports = {
  "extends": ["eslint-config-ali","prettier", "plugin:prettier/recommended"],
  "parser": "babel-eslint",
  "rules": {
    "prettier/prettier": "error",
    "strict": "off",
    "no-console": "off",
    "import/no-dynamic-require": "off",
    "global-require": "off",
    "require-yield": "off",
    "eqeqeq": "off",
    "new-cap": "off",
    "no-nested-ternary": "off",
    "array-callback-return": "off"
  },
  "plugins": ["prettier"],
  "globals": {
    "React": "readable",
    "wx": true,
    "App": true,
    "Page": true,
    "Component": true,
    "getApp": true,
    "toast": true
  }
};
```

3\. 增加`.prettierrc.js`文件，用于在扫描通过后格式化代码

```
module.exports = {
  printWidth: 100,
  semi: false,
  singleQuote: true,
  trailingComma: 'none',
  bracketSpacing: true,
  jsxBracketSameLine: false,
  arrowParens: 'avoid',
  requirePragma: false,
  proseWrap: 'preserve'
};
```

这里如果要忽略掉某一目录，可增加`.prettierignore`文件

```
.vscode
node_modules
miniprogram_npm
helper
pages/api/sdk/wxsdk3.2.0.js
pages/utils/
typings/
```

这样在commit的时候就会自动触发`lint-staged`，如果代码不合规范就会不让提交

![](/files/-MLvFi_TWDPABZCgaDce)

### 自动化构建

之前构建都是在微信开发工具中手动发布，每次都需要手动输入版本号，很不方便，因而需要。而小程序正好提供[miniprogram-ci](https://developers.weixin.qq.com/miniprogram/dev/devtools/ci.html)作为官方的构建工具，我们可使用该工具提供的命令行模式，具体如下：

1. 在package.json中加上

```
 "devDependencies": {
    "miniprogram-ci": "^1.0.79",
    "dayjs": "^1.8.36",
    "execa": "^4.0.3"
 }
```

2\. 因为用到vant组件库，所以需要自动化构建npm

```
async function buildNPM(cb) {
  await ci.packNpm(project, {
    reporter: infos => {
      console.log(infos)
    }
  })
  cb()
}
```

3\. 在CI.js中增加以下代码，用于自动化构建并上传

```
async function uploadCI(cb) {
  await ci.upload({
    project,
    version: getVersion(),
    desc: getGitCommit(),
    setting: {
      es6: true,
      es7: true,
      minify: true
    },
    onProgressUpdate: console.log
  })
  cb()
}
```

4\. 在微信后台生成一个代码上传密钥，重命名为private.key，保存到根目录下

![](/files/-MLqg3o7XyVzPpCFJJ4R)

5\. 在Jenkins中配置自动化构建项目，Jenkins搭建教程很多，这里不再阐述。在这过程中会先构建npm，然后执行rpx转换，最后构建程序并上传，构建脚本如下：

```
node -v
rm -rf node_modules
npm i
npm i gulp -g
gulp default --branch $giteeSourceBranch
```

6\. 等待构建完成后就会自动上传到小程序那边

![](/files/-MLqhWKA9T4hVqWQsqIR)

PS：详细的构建脚本如下（gulpfile.js）:

```
const ci = require('miniprogram-ci')
const dayjs = require('dayjs')
const execa = require('execa')
const gulp = require('gulp')
const postcss = require('gulp-postcss')
const pxtorem = require('./helper/pxtransform')

const app = require('./package.json')
const config = require('./project.config.json')

const project = new ci.Project({
  appid: config.appid, // 小程序的appId
  type: 'miniProgram',
  projectPath: './', // 打包路径
  privateKeyPath: './private.key', // 密钥位置
  ignores: ['node_modules/**/*', 'CI.js', 'private.key'] // 打包时忽略的文件
})

function getVersion() {
  const branch = process.argv[2]
  const date = dayjs().format('YYYYMMDD')
  return `${app.version}.${date}.${branch == 'master' ? 'release' : 'beta'}`
}

function getGitCommit() {
  const commit = execa.commandSync('git log -1')
  return `【${process.argv[2]}】${commit.stdout}`
}

async function buildNPM(cb) {
  await ci.packNpm(project, {
    reporter: infos => {
      console.log(infos)
    }
  })
  cb()
}

function formatCSS(cb) {
  const processors = [
    pxtorem({
      platform: 'weapp',
      designWidth: 750
    })
  ]
  gulp
    .src(['./miniprogram_npm/**/*.wxss'])
    .pipe(postcss(processors))
    .pipe(gulp.dest('./miniprogram_npm'))
  gulp
    .src(['./pages/**/*.wxss'])
    .pipe(postcss(processors))
    .pipe(gulp.dest('./pages'))
  gulp
    .src(['./pages/**/*.less'])
    .pipe(postcss(processors))
    .pipe(gulp.dest('./pages'))
  cb()
}

async function uploadCI(cb) {
  await ci.upload({
    project,
    version: getVersion(),
    desc: getGitCommit(),
    setting: {
      es6: true,
      es7: true,
      minify: true
    },
    onProgressUpdate: console.log
  })
  cb()
}

exports.default = gulp.series(buildNPM, formatCSS, uploadCI)

```

### 真机远程调试

小程序不像webview一样可以通过chrome或safari远程调试，因而需要通过抓包去捕捉真机中的请求错误，一般抓包工具都可以，以下用[charles](https://www.charlesproxy.com/)举例：

1. 安装charles，配置代理：

![](/files/-MLqnw2rt80zS58bU5LX)

2\. 保证手机和pc在同一网络下，在无线局域网-配置代理中输入pc端的无线地址、charles端口

![](/files/-MLqoZQ1sLMdMMsfWN0X)

3\. 这样charles中就会显示对应的请求

![](/files/-MLqolro2bH8rzgz0y6Z)

4\. 对于SSL请求，是看不到内容的，所以需要安装代理证书。

![](/files/-MLqpTMYWMHYtm0Gwsum)

![](/files/-MLqpMboP1XqFNqfHNBJ)

在手机端打开 [chls.pro/ssl](http://chls.pro/ssl) 下载安装证书

![](/files/-MLqpfKuxpGCO4sEUrrS)

需要在 设置→通用→关于本机→证书信任设置里面启用完全信任Charles证书，打开信任按钮

![](/files/-MLqqm3bRE-3deoWL-VM)

在charles中打开Proxy -> SSL Proxying Settings，勾选Enable SSL Proxying并配置域名

![](/files/-MLqqLzyoo5q8t7vk-M5)

### 错误搜集

小程序自身就有一个错误搜集的机制，当线上版本或测试版本出错时，就会传到后台。但这种错误一是对于接口调用的错误没有搜集，二是错误发生时没有提醒。因而需要接入一个第三方的错误监控系统。

![微信的错误搜集页面](/files/-MLq6WQJVbGkVNmUeVeT)

接入其实也很简单，[sentry](https://sentry.io/) 是一个开源的实时错误监控的项目，它支持很多端的配置，包括 web 前端、服务器端、移动端及其游戏端。支持各种语言，例如 python、oc、java、node、javascript 等。对于主流框架vue、angular、react等也支持。安装方式参照docker安装方式即可，网上的[教程](https://blog.csdn.net/kwame211/article/details/104642014)很多，这里就不再阐述。

这里主要说下怎么接入到小程序中，其实已经有有赞开发的插件 [raven-weapp](https://github.com/youzan/raven-weapp)

#### **引入文件**

由于目前小程序不支持从node\_modules中引入文件，因此以npm方式安装的话只能手动将raven-weapp/dist目录下需要的文件拷贝到其他文件中，在app.js中引入，例如：

```
var Raven = require('./utils/raven-weapp/build/raven')
```

#### **初始化Raven**

在sentry中创建一个项目，选择JavaScript类型，创建完会生成对应的服务器链接（<http://36887e0d8a0b48ea9ae3738204a358ef@sentry.nerochen.wang:9000/4>），在app.js中onLaunch时初始化Raven，

```
		Raven.config('http://36887e0d8a0b48ea9ae3738204a358ef@sentry.nerochen.wang:9000/4', {
			release: '1.2.0', // 版本号
			environment: 'production', //指定某个环境下才会上报
			allowDuplicates: true, // 允许相同错误重复上报
			sampleRate: 0.5 // 采样率
		}).install()
```

这样当前端报错时就会上传对应的错误

#### 接口调用的错误

Raven也支持自定义上传错误信息，我们可以在封装request的时候，将接口调用错误信息用Raven上传

```
Raven.captureMessage(url:${url}\nresult:${JSON.stringify(error)}, { level: 'error' });
```

![错误截图](/files/-MLqBZ023Ll1x_kAMcnl)

#### 关于错误通知

除了sentry自带的邮件通知（[配置](https://juejin.im/post/6844904051700842510)），我们使用企业微信的也可以通过配置webhook，触发企业微信机器人通知到我们（<https://dinglingdingling.com/>），具体步骤如下：

1. 在企业微信建一个用于通知的群，然后管理员身份配置群机器人

![](/files/-MLqRU81Pb33BMePG4y8)

2\. 在上述网站中配置一个转发

![](/files/-MLqS-OdgR35fn6KPrRD)

3\. 在sentry中增加webhook插件

![](/files/-MLqSPNSNUWlLPxdNfzu)

4\. 配置dinglingdingling生成的链接

![](/files/-MLqXcHqUcvMnrw-C-nW)

5\. 点击test触发通知

![](/files/-MLqXT2HB3sNtW5K2W1Z)

以上接入同样可以应用在项目构建完成、错误的提醒，定时构建的通知等。
