{"id":14989353,"url":"https://github.com/yi-ge/koa2-api-scaffold","last_synced_at":"2025-04-04T12:09:21.772Z","repository":{"id":43673265,"uuid":"79574311","full_name":"yi-ge/Koa2-API-Scaffold","owner":"yi-ge","description":"一个基于Koa2的轻量级RESTful API Server脚手架。","archived":false,"fork":false,"pushed_at":"2020-04-10T09:47:56.000Z","size":573,"stargazers_count":764,"open_issues_count":0,"forks_count":146,"subscribers_count":17,"default_branch":"master","last_synced_at":"2025-04-04T12:09:16.362Z","etag":null,"topics":["api","express","koa","koa2","node","nodejs","rest-api","restful","restful-api"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"wtfpl","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yi-ge.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-01-20T16:10:07.000Z","updated_at":"2025-02-28T08:30:58.000Z","dependencies_parsed_at":"2022-09-20T13:15:27.891Z","dependency_job_id":null,"html_url":"https://github.com/yi-ge/Koa2-API-Scaffold","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yi-ge%2FKoa2-API-Scaffold","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yi-ge%2FKoa2-API-Scaffold/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yi-ge%2FKoa2-API-Scaffold/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yi-ge%2FKoa2-API-Scaffold/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yi-ge","download_url":"https://codeload.github.com/yi-ge/Koa2-API-Scaffold/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247174454,"owners_count":20896078,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","express","koa","koa2","node","nodejs","rest-api","restful","restful-api"],"created_at":"2024-09-24T14:18:11.323Z","updated_at":"2025-04-04T12:09:21.744Z","avatar_url":"https://github.com/yi-ge.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Koa2 RESTful API 服务器脚手架\n\n这是一个基于 Koa2 的轻量级 RESTful API Server 脚手架，支持 ES6。\n\n**注意：** 因升级 Koa 版本至 2.3.0+，为配合相应的依赖项，故需要 Node.js 版本大于等于 v8.0.0（建议 v11.13.0），NPM 大于等于 v5.0.0。建议使用 yarn 代替 npm。\n\n约定使用 JSON 格式传输数据，POST、PUT、DELET 方法支持的 Content-Type 为`application/x-www-form-urlencoded、multipart/form-data、application/json`可配置支持跨域。非上传文件推荐 application/x-www-form-urlencoded。通常情况下返回 application/json 格式的 JSON 数据。\n\n可选用 redis 等非关系型数据库。考虑 RESTful API Server 的实际开发需要，这里通过 sequelize.js 作为 PostgreSQL, MySQL, MariaDB, SQLite, MSSQL 关系型数据库的 ORM，如无需关系型 ORM，`npm remove sequelize -S`，然后删除`src/lib/sequelize.js`文件。\n\n此脚手架只安装了一些和 Koa2 不冲突的搭建 RESTful API Server 的必要插件，附带每一个插件的说明。采用 ESlint 进行语法检查。\n\n因此脚手架主要提供 RESTful API，故暂时不考虑前端静态资源处理，只提供静态资源访问的基本方法便于访问用户上传到服务器的图片等资源。基本目录结构与 vue-cli 保持一致，可配合 React、AngularJS、Vue.js 等前端框架使用。在 Cordova/PhoneGap、Electron 中使用时需要开启跨域功能。\n\n**免责声明：** 此脚手架仅为方便开发提供基础环境，任何人或组织均可随意克隆使用，使用引入的框架需遵循原作者规定的相关协议（部分框架列表及来源地址在下方）。项目维护者均不对采用此脚手架产生的任何后果负责。\n\n**基于 Vue 2，Webpack 4，Koa 2 的 SSR 脚手架：**[https://github.com/yi-ge/Vue-SSR-Koa2-Scaffold](https://github.com/yi-ge/Vue-SSR-Koa2-Scaffold)。\n\n## 开发使用说明\n\n```bash\ngit clone https://github.com/yi-ge/koa2-API-scaffold.git\n\ncd mv koa2-API-scaffold\nnpm install\nnpm run dev # 可执行npm start跳过ESlint检查。\n```\n\n访问： http://127.0.0.1:3000/\n\n## 调试说明\n\n```bash\nnpm run dev --debug\n\nOr\n\nnpm start --debug\n```\n\n支持 Node.js 原生调试功能：https://nodejs.org/api/debugger.html\n\n## 开发环境部署\n\n生成 node 直接可以执行的代码到 dist 目录：\n\n```bash\nnpm run build\n```\n\n```bash\nnpm run production # 生产模式运行\n\n# Or\n\nnode dist/app.js\n```\n\n### PM2 部署说明\n\n提供了 PM2 部署 RESTful API Server 的示例配置，位于“pm2.js”文件中。\n\n```bash\npm2 start pm2.js\n```\n\nPM2 配合 Docker 部署说明： http://pm2.keymetrics.io/docs/usage/docker-pm2-nodejs/\n\n### Docker 部署说明\n\n```bash\ndocker pull node\ndocker run -itd --name RESTfulAPI -v `pwd`:/usr/src/app -w /usr/src/app node node ./dist/app.js\n```\n\n通过'docker ps'查看是否运行成功及运行状态\n\n### Linux/Mac 直接后台运行生产环境代码\n\n有时候为了简单，我们也这样做：\n\n```bash\nnohup node ./dist/app.js \u003e logs/out.log \u0026\n```\n\n查看运行状态（如果有'node app.js'出现则说明正在后台运行）：\n\n```bash\nps aux|grep app.js\n```\n\n查看运行日志\n\n```bash\ncat logs/out.log\n```\n\n监控运行状态\n\n```bash\ntail -f logs/out.log\n```\n\n### 配合 Vue-cli 部署说明\n\nVue-cli（Vue2）运行'npm run build'后会在'dist'目录中生成所有静态资源文件。推荐使用 Nginx 处理静态资源以达最佳利用效果，然后通过上述任意一种方法部署 RESTful API 服务器。前后端是完全分离的，请注意 Koa2 RESTful API Server 项目中 config/main.json 里面的跨域配置。\n\n推荐的 Nginx 配置文件：\n\n```text\nserver\n    {\n        listen 80;\n        listen [::]:80;\n        server_name abc.com www.abc.com; #绑定域名\n        index index.html index.htm;\n        root  /www/app/dist; #Vue-cli编译后的dist目录\n\n        location ~ .*\\.(gif|jpg|jpeg|png|bmp|swf)$\n        {\n            expires      30d;\n        }\n\n        location ~ .*\\.(js|css)?$\n        {\n            expires      12h;\n        }\n\n        location ~ /\\.\n        {\n            deny all;\n        }\n\n        access_log off; #访问日志路径\n    }\n```\n\nDocker 中 Nginx 运行命令(将上述配置文件任意命名放置于 nginx_config 目录中即可)：\n\n```bash\ndocker run -itd -p 80:80 -p 443:443 -v `pwd`/nginx_config:/etc/nginx/conf.d nginx\n```\n\n### 关于 Token 使用的特别说明（JWT 身份认证）\n\n`src\\app.js`目录中有一行代码：\n`.use(jwt({ secret: publicKey }).unless({ path: [/^\\/public|\\/user\\/login|\\/assets/] }))`\n\n在 path 里面的开头路径则不进行身份认证，否则都将进行 \b 鉴权。\n\n前端处理方案：\n\n```javascript\nimport axios from \"axios\";\nimport { getToken } from \"./tool\";\n\nconst DevBaseUrl = \"http://127.0.0.1:8080\";\nconst ProdBashUrl = \"https://xxx.xxx\";\n\nlet config = {\n  baseURL: process.env.NODE_ENV !== \"production\" ? DevBaseUrl : ProdBashUrl, // 配置API接口地址\n};\n\nlet token = getToken();\nif (token) {\n  config.headers = { Authorization: \"Bearer \" + token };\n}\n\nlet request = axios.create(config);\n\n// http request 拦截器\naxios.interceptors.request.use(\n  (config) =\u003e {\n    if (window) {\n      let token = getToken();\n      if (token) {\n        // 判断是否存在token，如果存在的话，则每个http header都加上token\n        config.headers.Authorization = `Bearer ${token}`;\n      }\n    }\n    // if (config.method === 'get') {\n    //   config.url = config.url + 'timestamp=' + Date.now().toString()\n    // }\n    return config;\n  },\n  (err) =\u003e {\n    return Promise.reject(err);\n  }\n);\n\nexport default request;\n```\n\n`tool.js`文件\n\n```javascript\n// 写 cookies\nexport let setCookie = function setCookie(name, value, time) {\n  if (time) {\n    let strsec = getsec(time);\n    let exp = new Date();\n    exp.setTime(exp.getTime() + parseInt(strsec));\n    document.cookie =\n      name + \"=\" + escape(value) + \";expires=\" + exp.toGMTString();\n  } else {\n    document.cookie = name + \"=\" + escape(value);\n  }\n};\n\n// 读 cookies\nexport let getCookie = function (name) {\n  let reg = new RegExp(\"(^| )\" + name + \"=([^;]*)(;|$)\");\n  let arr = document.cookie.match(reg);\n  return arr ? unescape(arr[2]) : null;\n};\n\n// 删 cookies\nexport let delCookie = function (name) {\n  var exp = new Date();\n  exp.setTime(exp.getTime() - 1);\n  var cval = getCookie(name);\n  if (cval != null) {\n    document.cookie = name + \"=\" + cval + \";expires=\" + exp.toGMTString();\n  }\n};\n\n// 获取Token\nexport let getToken = function () {\n  if (window.sessionStorage \u0026\u0026 window.sessionStorage.Bearer) {\n    return window.sessionStorage.Bearer;\n  } else if (window.localStorage \u0026\u0026 window.localStorage.Bearer) {\n    return window.localStorage.Bearer;\n  } else if (window.document.cookie) {\n    return getCookie(\"Bearer\");\n  }\n};\n\n// 设置Token\nexport let setToken = function (token, rememberTime) {\n  if (window.sessionStorage) {\n    window.sessionStorage.Bearer = token;\n  }\n\n  if ((rememberTime \u0026\u0026 window.localStorage) || !window.sessionStorage) {\n    window.localStorage.Bearer = token;\n  }\n\n  if (\n    window.document.cookie \u0026\u0026\n    !window.sessionStorage \u0026\u0026\n    !window.localStorage\n  ) {\n    if (rememberTime) {\n      setCookie(\"Bearer\", token, rememberTime);\n    } else {\n      setCookie(\"Bearer\", token);\n    }\n  }\n};\n\n// 删除Token\nexport let delToken = function () {\n  if (window.sessionStorage \u0026\u0026 window.sessionStorage.Bearer) {\n    window.sessionStorage.removeItem(\"Bearer\");\n  }\n\n  if (window.localStorage \u0026\u0026 window.localStorage.Bearer) {\n    window.localStorage.removeItem(\"Bearer\");\n  }\n\n  if (window.document.cookie) {\n    delCookie(\"Bearer\");\n  }\n};\n```\n\n大概原理：\n通过某个 API（通常是登录 API）获取成功后的 Token，存于本地，然后每次请求的时候在 Header 带上`Authorization: \"Bearer \" + token`，通常情况下无需担心本地 Token 被破解。\n\n## 引入插件介绍\n\n\u003e 引入插件的版本将会持续更新\n\n引入的插件：  \n`koa@2 koa-body@2 koa-router@next koa-static2 koa-compose require-directory babel-cli babel-register babel-plugin-transform-runtime babel-preset-es2015 babel-preset-stage-2 gulp gulp-eslint eslint eslint-config-standard eslint-friendly-formatter eslint-plugin-html eslint-plugin-promise nodemailer promise-mysql 等`\n\n**koa2**: HTTP 框架  \n\u0026nbsp;Synopsis: HTTP framework.  \n\u0026nbsp;From: https://github.com/koajs/koa v2\n\n**koa-body**: body 解析器  \n\u0026nbsp;Synopsis: A full-feature koa body parser middleware.  \n\u0026nbsp;From: https://github.com/dlau/koa-body\n\n**koa-router**: Koa 路由  \n\u0026nbsp;Synopsis: Router middleware for koa.  \n\u0026nbsp;From: https://github.com/alexmingoia/koa-router/tree/master/\n\n**koa-static2**: 静态资源中间件  \n\u0026nbsp;Synopsis: Middleware for Koa2 to serve a folder under a name declared by user.  \n\u0026nbsp;From: https://github.com/Secbone/koa-static2\n\n**koa-compose**: 多个中间件组合成一个  \n\u0026nbsp;Synopsis: Compose several middleware into one.  \n\u0026nbsp;From: https://github.com/koajs/compose\n\n**require-directory**: 递归遍历指定目录  \n\u0026nbsp;Synopsis: Recursively iterates over specified directory.  \n\u0026nbsp;From: https://github.com/troygoode/node-require-directory\n\n**babel-cli**: Babel 编译 ES6 代码为 ES5 代码  \n\u0026nbsp;Synopsis: Babel is a JavaScript compiler, ES6 to ES5.  \n\u0026nbsp;From: https://github.com/babel/babel/tree/master/packages/babel-cli\n\n**babel-register**: Babel 开发环境实时编译 ES6 代码  \n\u0026nbsp;Synopsis: Babel hook.  \n\u0026nbsp;From: https://github.com/babel/babel/tree/master/packages/babel-cli\n\n**babel-plugin-transform-runtime**: Babel 配置 ES6 的依赖项  \n**babel-preset-es2015**: 同上  \n**babel-preset-stage-2**: 同上\n\n**gulp**: 基于流的自动化构建工具  \n\u0026nbsp;Synopsis: Gulp is a toolkit for automating painful or time-consuming tasks.  \n\u0026nbsp;From: https://github.com/gulpjs/gulp\n\n**gulp-eslint**: gulp 的 ESLint 检查插件  \n\u0026nbsp;Synopsis: A gulp plugin for ESLint.  \n\u0026nbsp;From: https://github.com/adametry/gulp-eslint\n\n**gulp-nodemon**: 修改 JS 代码后自动重启  \n\u0026nbsp;Synopsis: nodemon will watch the files in the directory in which nodemon was started, and if any files change, nodemon will automatically restart your node application.  \n\u0026nbsp;From: https://github.com/remy/nodemon\n\n**eslint**: JavaScript 语法检查工具  \n\u0026nbsp;Synopsis: A fully pluggable tool for identifying and reporting on patterns in JavaScript.  \n\u0026nbsp;From:\n\n**eslint-config-standard**: 一个 ESlint 配置\u0026nbsp;Synopsis: ESLint Shareable Config for JavaScript Standard Style.  \n\u0026nbsp;From: https://github.com/feross/eslint-config-standard\n\n**eslint-friendly-formatter**: 使得 ESlint 提示在 Sublime Text 或 iterm2 中更友好，Atom 也有对应的 ESlint 插件。  \n\u0026nbsp;Synopsis: A simple formatter/reporter for ESLint that's friendly with Sublime Text and iterm2 'click to open file' functionality  \n\u0026nbsp;From: https://github.com/royriojas/eslint-friendly-formatter\n\n**eslint-plugin-html**: 检查 HTML 文件中的 JS 代码规范  \n\u0026nbsp;Synopsis: An ESLint plugin to extract and lint scripts from HTML files.  \n\u0026nbsp;From: https://github.com/BenoitZugmeyer/eslint-plugin-html\n\n**eslint-plugin-promise**: 检查 JavaScript promises  \n\u0026nbsp;Synopsis: Enforce best practices for JavaScript promises.\u0026nbsp;From: https://github.com/xjamundx/eslint-plugin-promise\n\n**eslint-plugin-promise**: ESlint 依赖项  \n\u0026nbsp;Synopsis: ESlint Rules for the Standard Linter.\u0026nbsp;From: https://github.com/xjamundx/eslint-plugin-standard\n\n**nodemailer**: 发送邮件  \n\u0026nbsp;Synopsis: Send e-mails with Node.JS.  \n\u0026nbsp;From: https://github.com/nodemailer/nodemailer\n\n**promise-mysql**: 操作 MySQL 数据库依赖  \n\u0026nbsp;Synopsis: Promise Mysql.  \n\u0026nbsp;From: https://github.com/lukeb-uk/node-promise-mysql\n\n**sequelize**: 关系型数据库 ORM  \n\u0026nbsp;Synopsis: Sequelize is a promise-based ORM for Node.js.  \n\u0026nbsp;From: https://github.com/sequelize/sequelize\n\n**mysql**: MySQL 库  \n\u0026nbsp;Synopsis: A pure node.js JavaScript Client implementing the MySql protocol.  \n\u0026nbsp;From: https://github.com/mysqljs/mysql\n\n支持 Koa2 的中间件列表：https://github.com/koajs/koa/wiki\n\n**其它经常配合 Koa2 的插件：**\n\n**koa-session2**: Session 中间件  \n\u0026nbsp;Synopsis: Middleware for Koa2 to get/set session.  \n\u0026nbsp;From: https://github.com/Secbone/koa-session2\n\n**koa-nunjucks-2**:  \n一个好用的模版引擎，可用于前后端，nunjucks：https://github.com/mozilla/nunjucks\n\n**koa-favicon**:  \nKoa 的 favicon 中间件：https://github.com/koajs/favicon\n\n**koa-server-push**:  \nHTTP2 推送中间件：https://github.com/silenceisgolden/koa-server-push\n\n**koa-convert**: 转换旧的中间件支持 Koa2  \n\u0026nbsp;Synopsis: Convert koa generator-based middleware to promise-based middleware.  \n\u0026nbsp;From: https://github.com/koajs/convert\n\n**koa-logger**: 请求日志输出，需要配合上面的插件使用  \n\u0026nbsp;Synopsis: Development style logger middleware for Koa.  \n\u0026nbsp;From: https://github.com/koajs/logger\n\n**koa-onerror**:  \nKoa 的错误拦截中间件，需要配合上面的插件使用：https://github.com/koajs/onerror\n\n**koa-multer**: 处理数据中间件  \n\u0026nbsp;Synopsis: Multer is a node.js middleware for handling multipart/form-data for koa.  \n\u0026nbsp;From: https://github.com/koa-modules/multer\n\n## 目录结构说明\n\n```bash\n.\n├── README.md\n├── .babelrc                # Babel 配置文件\n├── .editorconfig           # 编辑器风格定义文件\n├── .eslintignore           # ESlint 忽略文件列表\n├── .eslintrc.js            # ESlint 配置文件\n├── .gitignore              # Git 忽略文件列表\n├── gulpfile.js             # Gulp配置文件\n├── package.json            # 描述文件\n├── pm2.js                  # pm2 部署示例文件\n├── build                   # build 入口目录\n│   └── dev-server.js       # 开发环境 Babel 实时编译入口\n├── src                     # 源代码目录，编译后目标源代码位于 dist 目录\n│   ├── app.js              # 入口文件\n│   ├── config.js           # 主配置文件（*谨防泄密！）\n│   ├── plugin              # 插件目录\n│       └── smtp_sendemail  # 示例插件 - 发邮件\n│   ├── tool                # 工具目录\n│       ├── PluginLoader.js # 插件引入工具\n│       └── Common.js       # 示例插件 - 发邮件\n│   ├── lib                 # 库目录\n│   ├── controllers         # 控制器\n│   ├── models              # 模型\n│   ├── routes              # 路由\n│   └── services            # 服务\n├── assets                  # 静态资源目录\n└── logs                    # 日志目录\n```\n\n## 集成 NUXT 请求时身份认证说明\n\n```\nimport Vue from 'vue'\nimport axios from 'axios'\n\nconst DevBaseUrl = 'http://127.0.0.1:3000'\nconst ProdBashUrl = 'https://api.xxx.com'\n\nlet config = {\n  baseURL: process.env.NODE_ENV !== 'production' ? DevBaseUrl : ProdBashUrl // 配置API接口地址\n}\n\nif (process.env.VUE_ENV !== 'server') {\n  let token = getToken() // 此函数自行实现\n  if (token) {\n    config.headers = {Authorization: 'Bearer ' + token}\n  }\n}\n\nlet request = axios.create(config)\n\n// http request 拦截器\naxios.interceptors.request.use(\n  (config) =\u003e {\n    if (window) {\n      let token = getToken()\n      if (token) { // 判断是否存在token，如果存在的话，则每个http header都加上token\n        config.headers.Authorization = `Bearer ${token}`\n      }\n    }\n    return config\n  },\n  (err) =\u003e {\n    return Promise.reject(err)\n  }\n)\n\nVue.prototype.$request = request\n```\n\n## 各类主流框架调用 RESTful API 的示例代码（仅供参考）\n\n### AngularJS (Ionic 同)\n\n```javascript\n$http({\n  method: \"post\",\n  url: \"http://localhost:3000/xxx\",\n  data: { para1: \"para1\", para2: \"para2\" },\n  headers: {\n    \"Content-Type\": \"application/x-www-form-urlencoded\",\n  },\n})\n  .success(function (data) {\n    // do something\n  })\n  .error(function (data) {\n    // do something\n  });\n```\n\n### jQuery\n\n```javascript\n$.ajax({\n  cache: false,\n  type: \"POST\",\n  url: \"http://localhost:3000/xxx\",\n  data: {\n    para1: para1,\n  },\n  async: false,\n  dataType: \"json\",\n  success: function (result) {},\n  error: function (err) {\n    console.log(err);\n  },\n});\n\n// 上传文件\n//创建FormData对象\nvar data = new FormData();\n//为FormData对象添加数据\n//\n$.each($(\"#inputfile\")[0].files, function (i, file) {\n  data.append(\"upload_file\", file);\n});\n$.ajax({\n  url: \"http://127.0.0.1:3000/api/upload_oss_img_demo\",\n  type: \"POST\",\n  data: data,\n  cache: false,\n  contentType: false, //不可缺\n  processData: false, //不可缺\n  success: function (data) {\n    console.log(data);\n    if (data.result == \"ok\") {\n      $(\"#zzzz\").attr(\"src\", data.img_url);\n    }\n  },\n});\n```\n\n### MUI\n\n```javascript\nmui.ajax({\n  url: \"http://localhost:3000/xxx\",\n  dataType: \"json\",\n  success: function (data) {},\n  error: function (data) {\n    console.log(\"error!\");\n  },\n});\n```\n\n### JavaScript\n\n```javascript\nvar xhr = new XMLHttpRequest();\nxhr.open(\"POST\", \"http://localhost:3000/xxx\", true); //POST或GET，true（异步）或 false（同步）\nxhr.setRequestHeader(\"Content-type\", \"application/x-www-form-urlencoded\");\nxhr.withCredentials = true;\nxhr.onreadystatechange = function () {\n  if ((obj.readyState == 4 \u0026\u0026 obj.status == 200) || obj.status == 304) {\n    var gotServices = JSON.parse(xhr.responseText);\n  } else {\n    console.log(\"ajax失败了\");\n  }\n};\nxhr.send({ para1: para1 });\n```\n\n### vue-resource\n\nhttps://github.com/pagekit/vue-resource\n\n```javascript\n// global Vue object\nVue.http.post('/someUrl', [body], {\n  headers: {'Content-type', 'application/x-www-form-urlencoded'}\n}).then(successCallback, errorCallback)\n```\n\n### fetch\n\nhttps://github.com/github/fetch\n\n```javascript\nfetch('/users', {\n  method: 'POST',\n  headers: {\n    'Content-Type': 'application/json'\n  },\n  body: JSON.stringify({\n    name: 'Hubot',\n    login: 'hubot',\n  })\n}).then(function(response) {\n  // response.text()\n}).then(function(body) {\n  // body\n})\n\n// 文件上传\nvar input = document.querySelector('input[type='file']')\n\nvar data = new FormData()\ndata.append('file', input.files[0])\ndata.append('user', 'hubot')\n\nfetch('/avatars', {\n  method: 'POST',\n  body: data\n})\n```\n\n### superagent\n\nhttps://github.com/visionmedia/superagent\n\n```javascript\nrequest.post('/user')\n .set('Content-Type', 'application/json')\n .send('{'name':'tj','pet':'tobi'}')\n .end(callback)\n```\n\n### request\n\nhttps://github.com/request/request\n\n```javascript\nrequest.post('/api').form({key:'value'}), function(err,httpResponse,body){ /* ... */ })\n```\n\n在 React 中可以将上述任意方法其置于 componentDidMount()中，Vue.js 同理。\n\n## 彻底移除 ESlint 方法\n\n删除 package.json 的 devDependencies 中所有 eslint 开头的插件，根目录下的“.eslintignore、.eslintrc.js”文件，并且修改 package.json 的 dev 为：\n\n```bash\n'dev': 'gulp start'\n```\n\n删除 gulpfile.js 中的 lint、eslint_start 两个任务，并且把 default 改为“gulp.task('default', ['start']”。\n\n## 更新说明\n\n_v1.0.4 2020 年 04 月 10 日 17:46:51_\n\n1. 升级依赖版本。\n\n_v1.0.3 2019 年 9 月 11 日 13:21:56_\n\n1. 升级依赖版本。\n\n_v1.0.2 2019 年 06 月 07 日 15:15:37_\n\n1. 解决`WS-2019-0064`警告，升级依赖项版本。\n2. 规范路由引入方式，增加不同写法的示例。\n\n_v1.0.1 2019 年 06 月 02 日 21:54:00_\n\n1. 添加 Dockerfile\n\n_v1.0.0 2019 年 04 月 07 日 21:19:59_\n\n1. 升级依赖项版本（node11.13.0）。\n2. 添加 Jest。\n\n_v0.2.6 2018 年 03 月 24 日 22:16:43_\n\n1. 升级依赖项版本（node9.9.0）。\n\n_v0.2.5 2018 年 01 月 13 日 10:37:29_\n\n1. 升级依赖项版本（node9.3.0）。\n2. 添加了 Token 使用说明。\n\n_v0.2.4 2017 年 12 月 01 日 14:16:03_\n\n1. 升级依赖项版本（node9.2.0）。\n\n_v0.2.3 2017 年 10 月 23 日 23:26:56_\n\n1. 升级依赖项版本（node8.7.0）。\n\n_v0.2.2 2017 年 09 月 17 日 17:45:07_\n\n1. 升级依赖项版本（在 node8.5.0 测试）。\n\n_v0.2.1 2017 年 07 月 19 日 19:38:19_\n\n1. 移除 MySQL 模块（重复了）。\n2. 添加更详细的说明。\n\n_v0.2 2017 年 07 月 16 日 22:48:34_\n\n1. 升级 koa 为 2.3.0 版本。\n2. 将 koa-session2 替换为 koa-jwt，添加了 jsonwebtoken。\n3. 升级了以下依赖的版本： koa@2.3.0, koa-body@2.3.0, koa-router@7.2.1, babel-cli@6.24.1, babel-preset-es2015@6.24.1, babel-preset-stage-2@6.24.1, babel-register@6.24.1, eslint-plugin-promise@3.5.0, koa-compose@4.0.0, nodemailer@4.0.1, sequelize@4.3.2, eslint@4.2.0, eslint-config-standard@10.2.1, eslint-friendly-formatter@3.0.0, eslint-plugin-html@3.1.0, gulp-eslint@4.0.0, koa-logger@3.0.1\n\n_v0.1 2017 年 04 月 07 日 11:46:02_\n\n1. 升级 koa 为 2.2.0 版本。\n2. 升级了以下依赖版本到“建议版本”：\n\n```\n依赖项                     原版本  建议版本 最新版本        项目\neslint                   3.18.0  3.19.0  3.19.0  koa2-API-scaffold\neslint-plugin-standard    2.1.1   3.0.1   3.0.1  koa2-API-scaffold\nkoa-router                7.1.0   7.1.1   7.1.1  koa2-API-scaffold\npromise-mysql             3.0.0   3.0.1   3.0.1  koa2-API-scaffold\nsequelize                3.30.2  3.30.4  3.30.4  koa2-API-scaffold\n```\n\n_v0.0.9_1 2017 年 03 月 30 日 15:51:03_\n\n1. 完善了 gulpfile.js，不是重要的更新。\n\n_v0.0.9 2017 年 03 月 27 日 17:25:58_\n\n1. 修改了`src/controllers/upload.js`文件，添加了上传文件示例代码。\n2. 修复了`src/lib/mysql.js`引用路径错误的 BUG。\n3. 修改了`src/controllers/api.js`GET 参数获取的示例。\n\n_v0.0.8 2017 年 03 月 01 日 23:03:44_  \n1、在 src/app.js 18 行 后添加了\n\n```\n    jsonLimit: '20mb',\n    formLimit: '10mb',\n    textLimit: '20mb',\n```\n\n以免表单过长导致提交失败。\n\n_v0.0.7 2017 年 02 月 18 日 19:01:48_  \n1、修改了 index.js、config.js（详情请看 github 记录），完善了对跨域的处理。 更新建议：对应 github 修改记录同步修改，方便将来部署调试。\n\n_v0.0.6 2017 年 02 月 17 日 21:17:23_  \n1、修改了 src/lib/sequelize.js 文件,添加了对 utf8mb4 的支持（要求 MySQL 版本\u003e5.5）。\n\n_v0.0.5 2017 年 02 月 12 日 01:25:34_  \n1、修改了 gulpfile.js 文件，在更改文件热重启的时候无需检查全部文件，仅检查改动文件，开发速度更快。  \n2、修改了 package.json 中\"start\"项的值为\"gulp nodemon\"配合 gulpfile.js 文件的修改。\n\n_v0.0.4 2017 年 02 月 07 日 15:57:17_  \n1、修改了部分配置文件的配置方法，使之更为规范（老版本用户无须理会，对程序没有影响）。  \n2、修改了 eslintrc.js 文件中的 JavaScript 版本配置，改为 ES8，兼容 async、await。  \n3、修改 gulpfile.js 文件第 12 行，检查`src/**/*.js`文件。\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyi-ge%2Fkoa2-api-scaffold","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyi-ge%2Fkoa2-api-scaffold","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyi-ge%2Fkoa2-api-scaffold/lists"}