赞
踩
使用 koa-generator
创建项目
# 安装
npm install -g koa-generator
# 创建项目
koa2 test-demo
# 安装依赖
cd test-demo
npm install
# 启动
npm run dev
访问 http://localhost:3000/
创建 .gitignore
忽略掉 node_modules
node_modules/
windows 系统 注意把 dev 路径的 斜杠(/)替换成 (\\)
使用 eslint
+ prettier
# 安装
npm install eslint eslint-config-airbnb-base eslint-plugin-import eslint-config-prettier eslint-plugin-prettier -D
创建 .eslintrc.js
module.exports = { env: { commonjs: true, es2020: true, node: true, jest: true, es6: true, }, extends: ['airbnb-base', 'plugin:prettier/recommended'], parserOptions: { ecmaVersion: 12, }, plugins: ['prettier'], rules: { 'no-unused-vars': 0, 'no-console': 'off', 'max-classes-per-file': 0, 'prettier/prettier': [ 'error', { singleQuote: true, semi: false, arrowParens: 'avoid' }, ], 'arrow-body-style': 'off', 'prefer-arrow-callback': 'off', }, }
创建 .eslintignore
node_modules/
在跟目录创建一个 src 文件夹,将 public,routes,view 放到 src 下
同时也将 app.js 放到 src 下,并且修改 bin/www 将 const app = require('../app')
改为 const app = require('../src/app')
在 package.json 创建脚本
"script": {
...,
"lint": "eslint \"src/**/*.{js,ts}\"",
"lint-fix": "eslint --fix \"src/**/*.{js,ts}\""
}
# lint 检查
npm run lint
# 安装
npm install --save-dev jest
在根目录创建 __test__
文件夹
在目录下创建 sum.test.js
function sum(a, b) {
return a + b
}
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3)
})
配置执行脚本,参数
"script": {
"test": "jest --runInBand --passWithNoTests --colors --forceExit",
}
# 执行
npm run test
这里使用 supertest
# 安装
npm install supertest --save-dev
# 安装 axios
npm install axios --save-dev
在 __test__
下创建 apis 文件夹
创建 _server.js
文件,使用 supertest mock 请求接口
const axios = require('axios') const supertest = require('supertest') let request const app = require('../../src/app') const isTestLocal = process.env.NODE_ENV === 'local' const isTestRemote = process.env.NODE_ENV === 'remote' if (isTestLocal) { // 通过 supertest 创建服务 const server = app.callback() request = supertest(server) } // 测试机 host const REMOTE_HOST = 'http://localhost:3000' /** * 发送请求 * @param {*} method * @param {*} url * @param {*} bodyOrParams * @param {*} headers */ async function ajax(method = 'get', url = '', bodyOrParams = {}, headers = {}) { // 如果有 token 可以在 headers 设置 let result // 本身测试,使用 supertest if (isTestLocal) { let res if (method === 'get') { res = await request[method](url).query(bodyOrParams).set(headers) } else { res = await request[method](url).send(bodyOrParams).set(headers) } result = res } // 远程测试机,使用 axios if (isTestRemote) { const remoteUrl = `${REMOTE_HOST}${url}` const conf = { method, url: remoteUrl, headers, } if (method === 'get') { conf.params = bodyOrParams } else { conf.body = bodyOrParams } const res = await axios(conf) result = res } // 返回结果 return result } module.exports = { async get(url, params, headers) { const res = await ajax('get', url, params, headers) return res }, async post(url, body, headers) { const res = await ajax('post', url, body, headers) return res }, async patch(url, body, headers) { const res = await ajax('patch', url, body, headers) return res }, async del(url, body, headers) { const res = await ajax('delete', url, body, headers) return res }, }
由于使用了环境变量 NODE_ENV
# 安装
npm install cross-env --save-dev
修改脚本
"script": {
"test:local": "cross-env NODE_ENV=local jest --runInBand --passWithNoTests --colors --forceExit",
"test:remote": "cross-env NODE_ENV=remote jest --runInBand --passWithNoTests --colors --forceExit"
}
创建测试文件 user-check.js
const { get } = require('./_server')
it('users/bar 测试', async () => {
const { text, status } = await get('/users/bar')
expect(status).toBe(200)
expect(text).toBe('this is a users/bar response')
})
在 apis 文件夹下创建 index.test.js
// 导入
require('./user-check')
# 执行
npm run test:local
使用 pre-commit
+ husky
+ lint-staged
# 安装
npm i pre-commit husky lint-staged --save-dev
# 初始化 husky
npm set-script prepare "husky install"
npm run prepare
在 package.json 中配置 lint-staged
{
"lint-staged": {
"*.js": [
"npm run lint",
"npm run test:local"
]
}
}
# 如果没有安装 npx 命令
npm install -g npx
# 添加 pre-commit 配置
npx husky add .husky/pre-commit 'npx lint-staged "$1"'
随便修改一个 src 下的 .js 文件,用于测试
# 执行
git add .
git commit -m "测试 commit 前的代码检查"
会根据 lint-staged 配置的,检查 git 缓存,匹配 *.js 文件,然后执行脚本检查代码
# 推送
git push
使用 @commitlint
# 安装
npm install -g @commitlint/cli @commitlint/config-conventional
配置 husky
npx husky add .husky/commit-msg "npx --no-install commitlint --edit $1"
在跟目录下添加 commitlint.config.js
文件
module.exports = { extends: ['@commitlint/config-conventional'] }
# 测试
git add .
git commit -m "commitlint 测试"
# No staged files match any configured task.
# ⧗ input: commitlint 测试
# ✖ subject may not be empty [subject-empty]
# ✖ type may not be empty [type-empty]
# ✖ found 2 problems, 0 warnings
# ⓘ Get help: https://github.com/conventional-changelog/commitlint/#what-is-commitlint
# 提交格式
git commit -m <type>[optional scope]: <description>
类型 | 描述 |
---|---|
build | 编译相关的修改,例如发布版本、对项目构建或者依赖的改动 |
chore | 其他修改, 比如改变构建流程、或者增加依赖库、工具等 |
ci | 持续集成 |
docs | 文档修改 |
feat | 新特性、新功能 |
fix | 修复 bug |
perf | 代码优化相关,比如提升性能、体验 |
refactor | 代码重构 |
revert | 回滚到上一个版本 |
style | 代码格式修改, 注意不是 css 修改 |
test | 测试相关,如测试用例修改 |
# 正确写法,注意分号后面的空格
git commit -m "feat: 增加 commitlint 功能"
commitlint - Lint commit messages
npx 使用教程 - 阮一峰的网络日志 (ruanyifeng.com)
使用 commitizen
# 全局安装
npm install -g commitizen
# 安装配置
commitizen init cz-conventional-changelog --save-dev --save-exact
# 测试
git add .
# 使用 git cz 进行提交,然后根据提示,输入内容,便可
git cz
# 推送
git push
使用 cz-customizable
自定义提示内容
# 安装
npm install cz-customizable --save-dev
// 在 package.json 将 cz-conventional-changelog 的配置
"config": {
"commitizen": {
"path": "./node_modules/cz-conventional-changelog"
}
}
// 更改为,不再使用 cz-conventional-changelog
"config": {
"commitizen": {
"path": "./node_modules/cz-customizable"
}
}
在根目录下创建 .cz-config.js
cz-customizable/cz-config-EXAMPLE.js at master · leoforfree/cz-customizable (github.com)
// 这里使用的是样例的配置,可根据需要自定义 module.exports = { types: [ { value: 'feat', name: 'feat: A new feature' }, { value: 'fix', name: 'fix: A bug fix' }, { value: 'docs', name: 'docs: Documentation only changes' }, { value: 'style', name: 'style: Changes that do not affect the meaning of the code\n (white-space, formatting, missing semi-colons, etc)', }, { value: 'refactor', name: 'refactor: A code change that neither fixes a bug nor adds a feature', }, { value: 'perf', name: 'perf: A code change that improves performance', }, { value: 'test', name: 'test: Adding missing tests' }, { value: 'chore', name: 'chore: Changes to the build process or auxiliary tools\n and libraries such as documentation generation', }, { value: 'revert', name: 'revert: Revert to a commit' }, { value: 'WIP', name: 'WIP: Work in progress' }, ], scopes: [{ name: 'accounts' }, { name: 'admin' }, { name: 'exampleScope' }, { name: 'changeMe' }], allowTicketNumber: false, isTicketNumberRequired: false, ticketNumberPrefix: 'TICKET-', ticketNumberRegExp: '\\d{1,5}', // it needs to match the value for field type. Eg.: 'fix' /* scopeOverrides: { fix: [ {name: 'merge'}, {name: 'style'}, {name: 'e2eTest'}, {name: 'unitTest'} ] }, */ // override the messages, defaults are as follows messages: { type: "Select the type of change that you're committing:", scope: '\nDenote the SCOPE of this change (optional):', // used if allowCustomScopes is true customScope: 'Denote the SCOPE of this change:', subject: 'Write a SHORT, IMPERATIVE tense description of the change:\n', body: 'Provide a LONGER description of the change (optional). Use "|" to break new line:\n', breaking: 'List any BREAKING CHANGES (optional):\n', footer: 'List any ISSUES CLOSED by this change (optional). E.g.: #31, #34:\n', confirmCommit: 'Are you sure you want to proceed with the commit above?', }, allowCustomScopes: true, allowBreakingChanges: ['feat', 'fix'], // skip any questions you want skipQuestions: ['body'], // limit subject length subjectLimit: 100, // breaklineChar: '|', // It is supported for fields body and footer. // footerPrefix : 'ISSUES CLOSED:' // askForBreakingChangeFirst : true, // default is false };
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。