亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > JS > 正文

搭建一個Koa后端項目腳手架的方法步驟

2024-05-06 16:51:37
字體:
來源:轉載
供稿:網友

一、背景

結合當前的node比較火的三大框架,Express、Koa、egg。筆者之前用的Express,后面發現回調把我搞死了,實在太無奈了。終于有一天去嘗試了Koa來進行開發,發現實在太舒服了。ES6語法支持很多,同步模式也很到位,但是在學習koa的過程中,發現基本的基礎知識都了解了,也按照官方的文檔走了一遍,但發現好像無從下手。感覺開發過程中,分層不太明顯,業務邏輯簡單還好,一多麻煩就來了。查看了資料后,有一個koa的腳手架叫做 koa-generator ,馬上嘗試后發現不是我想要的模板??磥韌ithub已經有2年沒有維護了,koa2一些新特性也沒有加上,感覺有點快落伍了。于是結合其他人的模式,也避免后面自己過多的重復造輪子。編寫一個Koa項目的初始模板。這個模板主要的功能集成了Logger、Router、JWT、Mongoose、redis、PM2等模塊,還有部分的中間件集合,該模板對于簡單的后臺項目來說基本夠用了,沒有考慮高并發處理,后期會繼續完善。對于初學者來說,可以快速的新項目開發,在開始之前先好好看下面的解讀。

二、目錄結構

下面的目錄是該模板基礎目錄結構,后面的章節會對每一個目錄的配置進行介紹,讓大家在開發中對項目的結構比較清晰,出了問題容易定位。

├─.gitignore    // 忽略文件配置├─app.js     // 應用入口├─config.js     // 公共配置文件├─ecosystem.config.js  // pm2配置文件├─package.json    // 依賴文件配置├─README.md     // README.md文檔├─routes     // 路由| ├─private.js    // 校驗接口| └public.js     // 公開接口├─models     // 數據庫配置及模型| ├─index.js     // 數據庫配置| └user.js     // 用戶的schema文件├─middlewares    // 中間件|  ├─cors.js    // 跨域中間件|  ├─jwt.js     // jwt中間件|  ├─logger.js    // 日志打印中間件|  └response.js    // 響應及異常處理中間件├─logs      // 日志目錄| ├─koa-template.log| └koa-template.log-2019-05-28├─lib      // 工具庫| ├─error.js     // 異常處理| └mongoDB.js     // mongoDB配置├─controllers    // 操作數據庫及業務邏輯|  ├─index.js    // 配置|  ├─login.js    // 登錄|  └test.js     // 測試├─bin      // 啟動目錄| └www       // 啟動文件配置

 

 
Koa,后端項目,腳手架 

 

bin文件

bin文件目錄中,只有一個文件,即為www,因為我們后端的項目基本上是在Linux上進行運行的,其實我們不必去擔心文件的后綴是什么,只需知道該文件是可執行文件還是不可執行文件就行了。這個文件有什么用呢?其實我們這個文件是用來部署的時候可以啟動我們一整個后端程序,也就是我們前端中的集成的運行環境。我們的運行、關閉、重啟都在這文件進行即可?;敬a如下:

#!/usr/bin/env node/** * Module dependencies. */const app = require('../app')const http = require('http')const config = require('../config')/** * Get port from environment and store in Express. */const port = normalizePort(process.env.PORT || config.port)// app.set('port', port);/** * Create HTTP server. */const server = http.createServer(app.callback())/** * Listen on provided port, on all network interfaces. */server.listen(port)server.on('error', onError)server.on('listening', onListening)/** * Normalize a port into a number, string, or false. */function normalizePort(val) { const port = parseInt(val, 10) if (isNaN(port)) { // named pipe return val } if (port >= 0) { // port number return port } return false}/** * Event listener for HTTP server "error" event. */function onError(error) { if (error.syscall !== 'listen') { throw error } const bind = typeof port === 'string' ? 'Pipe ' + port : 'Port ' + port // handle specific listen errors with friendly messages switch (error.code) { case 'EACCES':  console.error(bind + ' requires elevated privileges')  process.exit(1)  break case 'EADDRINUSE':  console.error(bind + ' is already in use')  process.exit(1)  break default:  throw error }}/** * Event listener for HTTP server "listening" event. */function onListening() { const addr = server.address() const bind = typeof addr === 'string' ? 'pipe ' + addr : 'port ' + addr.port console.log('Listening on ' + bind)}

相信用過koa-generator對這個代碼斌并不陌生,這其實就是他里面的代碼,express項目的www文件也基本差不多。還是希望大家可以把這里面的代碼過一遍,它的基本思路就是利用了node.js中的http模塊,讓http暴露你的端口并進行監聽,這個端口是在配置文件config.js中引入的。

app.js

先簡單的看一下代碼

'use strict'const Koa = require('koa')const bodyParser = require('koa-bodyparser')()const staticCache = require('koa-static-cache')const config = require('./config')const publicRouter = require('./routes/public')const privateRouter = require('./routes/private')const { loggerMiddleware } = require('./middlewares/logger')const { errorHandler, responseHandler } = require('./middlewares/response')const app = new Koa()// Loggerapp.use(loggerMiddleware)// Error Handlerapp.use(errorHandler)// Global Middlewaresapp.use(bodyParser)app.use(staticCache(config.publicDir))// Routesapp.use(publicRouter.routes(), publicRouter.allowedMethods())app.use(privateRouter.routes(), privateRouter.allowedMethods())// Responseapp.use(responseHandler)module.exports = app

這個文件中,我們可以看到較多的中間件,中間件的執行順序是從外到內,再從內到外,也就是洋蔥模式。如果還不大了解中間的小伙伴可以去查找相關資料。中間件的執行過程是依靠 app.use() 進行傳遞的,你可以簡單的理解為自己編寫的函數,依次去執行即可。每一個中間件會在app調用是傳入2個參數,分別為: ctx 和 next

ctx: 

Koa Context 將 node 的 request 和 response 對象封裝在一個單獨的對象里面,其為編寫 web 應用和 API 提供了很多有用的方法。

這些操作在HTTP服務器開發中經常使用,因此其被添加在上下文這一層,而不是更高層框架中,因此將迫使中間件需要重新實現這些常用方法。

next: 

下一個中間件函數,也就是每一個中間件如果要往下走必須寫上這個,否則無法執行。

可以理解為前端的vue-Router中的路由守衛中的next(), 執行下一步或者進行傳參。

middlewares

在這個項目主要用到了幾個中間件,一個是 logger.js 、 response.js 和 jwt.js 等其他中間件。

logger.js

大家可以想一下,如果我們項目在開發中,或者上線了,我們要看我們執行的日志或者請求的參數以及報錯等信息,如果沒有再每一個請求中體現出來,那么遇到問題我們會很難定位到是前端的問題還是后端。而logger這個中間件就是用來對這些情況進行處理的,原來的koa模板中,只是簡單的進行log的打印而已,這個中間件是用了log4js模塊進行封裝的。詳細使用方法查看官方文檔,這個中間件會在控制臺或者日志中打印出固定的格式,http請求方法、返回狀態、請求url、IP地址、請求時間等,而且我們也可以很好的利用log4js中的配置,來打印出自定義的日志??梢源?nbsp;console.log() 使用,在使用這個中間件的時候,必須放在第一個中間件,才能保證所以的請求及操作會先經過logger進行記錄再到下一個中間件。其代碼如下:

'use strict'const fs = require('fs')const path = require('path')const log4js = require('log4js')const config = require('../config')const logsDir = path.parse(config.logPath).dirif (!fs.existsSync(logsDir)) { fs.mkdirSync(logsDir)}log4js.configure({ appenders: { console: { type: 'console' }, dateFile: { type: 'dateFile', filename: config.logPath, pattern: '-yyyy-MM-dd' } }, categories: { default: {  appenders: ['console', 'dateFile'],  level: 'info' } }})const logger = log4js.getLogger('[Default]')const loggerMiddleware = async (ctx, next) => { const start = new Date() await next() const ms = new Date() - start const remoteAddress = ctx.headers['x-forwarded-for'] || ctx.ip || ctx.ips || (ctx.socket && (ctx.socket.remoteAddress || (ctx.socket.socket && ctx.socket.socket.remoteAddress))) let logText = `${ctx.method} ${ctx.status} ${ctx.url} 請求參數: ${JSON.stringify(ctx.request.body)} 響應參數: ${JSON.stringify(ctx.body)} - ${remoteAddress} - ${ms}ms` logger.info(logText)}module.exports = { logger, loggerMiddleware}

response.js

這個中間件主要是用來對返回前端的響應進行處理,基礎的koa模板中,我們可以用 ctx.body 進行返回前端,但是發現有些東西經常重復寫,還不如提出來進行封裝,而且還不用擔心返回的格式會不一致。 先看看代碼:

'use strict'const { logger } = require('./logger')// 這個middleware用于將ctx.result中的內容最終回傳給客戶端// 回傳的格式遵循這樣的格式:{ code: 0, msg: any data: any }const responseHandler = (ctx) => { if (ctx.result !== undefined) { ctx.type = 'json' ctx.body = {  code: 200,  msg: ctx.msg || '',  data: ctx.result } }}// 這個middleware處理在其它middleware中出現的異常// 并將異常消息回傳給客戶端:{ code: '錯誤代碼', msg: '錯誤信息' }const errorHandler = (ctx, next) => { return next().catch(err => { if (err.code == null) {  logger.error(err.stack) } ctx.body = {  code: err.code || -1,  data: null,  msg: err.message.trim() } ctx.status = 200 // 保證返回狀態是 200, 這樣前端不會拋出異常 return Promise.resolve() })}module.exports = { responseHandler, errorHandler}

代碼的后面會暴露出 responseHandler 和 errorHandler , responseHandler 正確響應,我們在業務中,只需要對 ctx.result 進行寫入即可。這個中間件可以放在所有中間件的最后面,這樣可以保證前面中間件都需要經過它,再返回前端。 errorHandler 錯誤響應,這個主要是用來進行出錯或者異常的捕獲,可以返回響應給前端,要不前端會出現一直padding的狀態直到超時。

jwt.js

'use strict'const koaJwt = require('koa-jwt')const jwt = require('jsonwebtoken')const config = require('../config')const jwtMiddleware = koaJwt({ secret: config.secret })module.exports = function (ctx, next) { // 將 token 中的數據解密后存到 ctx 中 try { if (typeof ctx.request.headers.authorization === 'string') {  const token = ctx.request.headers.authorization.slice(7)  ctx.jwtData = jwt.verify(token, config.secret) } else {  throw {code: 401, message: 'no authorization'} } } catch (err) { throw {code: 401, message: err.message} } next()}

其實這個中間件是對 koa-jwt 進行封裝的,JWT我們用來生成token,用來判斷用戶的唯一性,每次登錄后返回前端,前端每一個需要鑒權的api都需要進行token驗證,我們利用了 koa-jwt 進行token的生成,但是怎樣才能在每一個接口中獲取到token解析后的用戶呢。這個中間件就起到很大的關鍵作用。會結合在需要鑒權的 router 中,驗證通過后保存信息到ctx中,可以供全局使用。

cors.js

在前后端接口請求中,由于瀏覽器的限制,會出現跨域的情況。常用的跨域方案有:

1、JSONP跨域

2、nginx反向代理

3、服務器端修改heade

4、document.domain

5、window.name

6、postMessage

7、后臺配置運行跨域

koa中如何設置跨域

先看看koa中如何設置跨域,cors具體的實現過程,具體的詳細介紹,已經在代碼中進行注釋了。先看一下原生的配置,后面直接使用中間件即可,不過還是需要了解一下具體實現方式,萬一出了問題,能快熟的排查。

app.use(async (ctx, next) => { // 允許來自所有域名請求 ctx.set("Access-Control-Allow-Origin", "*"); // 這樣就能只允許 http://localhost:8080 這個域名的請求了 // ctx.set("Access-Control-Allow-Origin", "http://localhost:8080");  // 設置所允許的HTTP請求方法 ctx.set("Access-Control-Allow-Methods", "OPTIONS, GET, PUT, POST, DELETE"); // 字段是必需的。它也是一個逗號分隔的字符串,表明服務器支持的所有頭信息字段. ctx.set("Access-Control-Allow-Headers", "x-requested-with, accept, origin, content-type"); // 服務器收到請求以后,檢查了Origin、Access-Control-Request-Method和Access-Control-Request-Headers字段以后,確認允許跨源請求,就可以做出回應。 // Content-Type表示具體請求中的媒體類型信息 ctx.set("Content-Type", "application/json;charset=utf-8"); // 該字段可選。它的值是一個布爾值,表示是否允許發送Cookie。默認情況下,Cookie不包括在CORS請求之中。 // 當設置成允許請求攜帶cookie時,需要保證"Access-Control-Allow-Origin"是服務器有的域名,而不能是"*"; ctx.set("Access-Control-Allow-Credentials", true); // 該字段可選,用來指定本次預檢請求的有效期,單位為秒。 // 當請求方法是PUT或DELETE等特殊方法或者Content-Type字段的類型是application/json時,服務器會提前發送一次請求進行驗證 // 下面的的設置只本次驗證的有效時間,即在該時間段內服務端可以不用進行驗證 ctx.set("Access-Control-Max-Age", 300); /* CORS請求時,XMLHttpRequest對象的getResponseHeader()方法只能拿到6個基本字段:  Cache-Control、  Content-Language、  Content-Type、  Expires、  Last-Modified、  Pragma。 */ // 需要獲取其他字段時,使用Access-Control-Expose-Headers, // getResponseHeader('myData')可以返回我們所需的值 //https://www.rails365.net/articles/cors-jin-jie-expose-headers-wu ctx.set("Access-Control-Expose-Headers", "myData");  await next();})

相對用得較多是的大神封裝好得koa-cors中間件,可以自行查看npm上得文檔,在這個項目中用的就是koa-cors的中間件,基本的配置寫在cors.js里面了,再通過中間件進行引用。注意要寫在router前面,避免在沒有進行跨域配置前就去請求接口。

app.js中的引用,記得安裝引入koa-cors

// corsapp.use(cors(corsHandler))
'use strict'const corsHandler = { origin: function (ctx) {  if (ctx.url === '/test') {   // 這里可以配置不運行跨域的接口地址   return false;  }  return '*'; }, exposeHeaders: ['WWW-Authenticate', 'Server-Authorization'], maxAge: 5, credentials: true, allowMethods: ['GET', 'POST', 'DELETE'], allowHeaders: ['Content-Type', 'Authorization', 'Accept'],}module.exports = { corsHandler}

koa-helmet 中間件

koa-helmet 可以幫助你的 app 抵御一些比較常見的安全 web 安全隱患,它其實是將 9 個安全中間件集中到了一起,做了合并,大部分都是對于 http header 的操作,下圖為默認開啟的功能。

 

 
Koa,后端項目,腳手架

 

在項目中使用先安裝該中間件, npm i koa-helmet --save ,該項目中直接引用默認配置即可,如果有需要,可以看官方文檔自己進行配置。

const helmet = require("koa-helmet")// Helmetapp.use(helmet())

其他中間件

koa的中間件可以說很多大神給我們做好了輪子,我們直接可以拿來用就行,例如: bodyParser 、 koa-session、將將中間件轉換成koa2可以使用的中間件 koa-convert 、EJS模板使用 koa-ejs ,大家根據自己需要進行引用,由于是基礎模板,暫時沒有加上過多中間件,減少體積。

lib文件

這個文件夾主要是用來做存放工具類的文件夾,一些全局的工具處理文件可以放到這邊來,目前這個項目中只有2個文件, error.js 和 mongoDB.js

error.js 中主要是在中間件中拋出異常,由于前面我們已經加入了異常捕獲的中間件,在中間件操作過程中,如果有錯誤,我們可以直接拋出異常,這個方法就是為了方便我們配置所用的。文件中的方法是 CodedError 方法繼承了Error, ForbiddenError 和 InvalidQueryError 是繼承了 CodedError ,記得在使用的時候得實例化一下該構造函數。如果小伙伴對ES6的繼承還不熟悉,可以先看一下文檔再來看該工具類。

'use strict'class CodedError extends Error { constructor (message = '未知錯誤', code = -1) { super(message) this.code = code }}module.exports = { CodedError, /** * 拒絕訪問構造函數 */ ForbiddenError: class ForbiddenError extends CodedError { constructor (message = '拒絕訪問') {  super(message, 403) } }, /** * 無效的參數構造函數 */ InvalidQueryError: class InvalidQueryError extends CodedError { constructor (message = '無效的參數') {  super(message, 400) } }}

mongoDB.js 文件是對mongoDB的鏈接配置,后續在models中會講到。

models文件

該項目中是使用 mongoose 對 mongoDB 對數據庫進行操作, mongoose 語法簡單,需要過多的學習成本。按照官方文檔的配置以及api操作,即可對 mongoBD 進行靈活性存儲。 mongoose 的配置包括三大部分: connect 、 Models 和 Schema

connect :用于創建數據庫連接及監聽

Schema :Schema主要用于定義MongoDB中集合Collection里文檔document的結構,可以理解為mongoose對表結構的定義(不僅僅可以定義文檔的結構和屬性,還可以定義文檔的實例方法、靜態模型方法、復合索引等),每個schema會映射到mongodb中的一個collection,schema不具備操作數據庫的能力,簡單理解是對字段的定義,操作數據庫必須按照這些字段進行,否在會報錯。

Models : Model是由Schema編譯而成的假想(fancy)構造器,具有抽象屬性和行為。Model的每一個實例(instance)就是一個document,document可以保存到數據庫和對數據庫進行操作。簡單說就是model是由schema生成的模型,可以對數據庫的操作。

在我們項目中,我們把它全局集合在models文件中進行配置。 index.js 文件里面操作了 connect 、 Models這兩個步驟。先看代碼:

const fs = require('fs');const path = require('path');const mongoose = require('mongoose'); //引用mongoose模塊const config = require('../config')const { logger } = require('../middlewares/logger')let url = "mongodb://" + config.mongoDB.host + ":" + config.mongoDB.port + "/" + config.mongoDB.database;var mongo = mongoose.createConnection(url); //創建一個數據庫連接let db = { mongoose: mongoose, mongo: mongo, models: {}};// 錯誤mongo.on('error', function (err) { logger.error(new Error(err));});// 開啟mongo.once('open', function () { logger.info("mongo is opened");});// 整合models文件下的其他js文件fs.readdirSync(__dirname) .filter(function (file) {  return (file.indexOf(".") !== 0) && (file !== "index.js"); }).forEach(function (file) { var modelFile = require(path.join(__dirname, file)); var schema = new mongoose.Schema(modelFile.schema); db.models[modelFile.name] = mongo.model(modelFile.name, schema, modelFile.name);});// 根據name選擇modeldb.getModel = function (name) { return this.models[name];};module.exports = db;

代碼中的鏈接部分一看基本就明白了,可是 models 部分怎么看不出所以然。其實是模塊化開發的一部分,這里是為了整合models文件下的其他js文件,方便開發者使用,不用每寫一個文件就要進行引入和導出。

初始情況下, models 引入只需 mongoose.model('名稱', schema); 并將其暴露出去,即可對數據庫進行操作。

fs.readdirSync(__dirname) .filter(function (file) {  return (file.indexOf(".") !== 0) && (file !== "index.js"); }).forEach(function (file) { var modelFile = require(path.join(__dirname, file)); var schema = new mongoose.Schema(modelFile.schema); db.models[modelFile.name] = mongo.model(modelFile.name, schema, modelFile.name);});

在這個文件內,我們做了這樣一件事:讀取 models 目錄下所有文件名不為 index.js 且以 .js 為后綴名的文件,使用 require 進行引用,并將其整合為一個 schema對象后再引入到models并且暴露出去給操作數據庫。這樣子做的好處是,在項目越來越龐大以后,如果我們需要添加新的 schema ,只需直接在 models 目錄下新建 .js 文件即可,則不用再進行引入的關系操作

由于有了上一步的操作,我們后面直接新增一個schema的配置文件即可。index.js會自動的引入并暴露出model

'use strict'module.exports = { name: "user", schema: { uuid: String, // UUID userName: String, // 用戶名 password: String, // 密碼 }};

我們使用時可以這樣操作,

const User = require('../models/index').getModel('user')const user = await User.findOne({userName: userName})

PM2配置

PM2是可以用于生產環境的Nodejs的進程管理工具,并且它內置一個負載均衡。它不僅可以保證服務不會中斷一直在線,并且提供0秒reload功能,還有其他一系列進程管理、監控功能。并且使用起來非常簡單。pm2的官方文檔已經進行詳細的配置說明,在這里就不進行一一簡述,主要講的時我的koa項目怎樣配合PM2進行相關管理或者說部署。PM2常用命令需要用的時候可以進行查看,沒必要去背,用多就熟悉了。也可以結合在package.json里面,用自定義命令運行。我們在 package.json 的 script 配置和初始化文件 ecosystem.config.js 進行了多環境運行的配置,我們可以根據需要進行切換環境。

package.json 文件添加如下:

 "scripts": { "start": "node ./bin/www", "dev": "pm2 start ecosystem.config.js --env dev", "test": "pm2 start ecosystem.config.js --env test", "pro": "pm2 start ecosystem.config.js --env pro", "logs": "pm2 logs", "stop": "pm2 stop ecosystem.config.js" },

其中的

npm run start: 直接跑www文件,可用于調試
npm run dev: 開發環境
npm run test:測試環境
npm run pro:生產環境
npm run logs: 查看pm2的日志
npm run stop: 停止pm2服務

新增 ecosystem.config.js 文件:

module.exports = { apps : [{ name: 'API', script: './bin/www', // Options reference: https://pm2.io/doc/en/runtime/reference/ecosystem-file/ args: 'one two', instances: 1, autorestart: true, watch: true, ignore_watch: [       // 不用監聽的文件  'node_modules',  'logs' ], max_memory_restart: '1G', env_pro: {  "NODE_ENV": "production",  "REMOTE_ADDR": "" }, env_dev: {  "NODE_ENV": "development",  "REMOTE_ADDR": "" }, env_test: {  "NODE_ENV": "test",  "REMOTE_ADDR": "" } }]};

這個文件主要是對pm2的基本配置,不用每次都進行配置,直接在文件進行改動即可。我們需要關注的是可以在 env 中,增加我們需要的環境及變量即可,文件中的 watch 屬性是可以配置監聽文件改動后,自動重啟項目,比較好用。如果想忽略某一個文件夾的變動可以 ignore_watch ,更多的配置如果有興趣的小伙伴可以查看官方文檔的文檔說明。

路由配置

該目錄下存放路由基本配置,有 private 和 public 兩個文件,引入路由后,我們對其前綴做了處理, router.prefix('/api') 在每一個請求的時候都需要帶上這個前綴,抽出來也是為了服務目錄的改變,可以直接更改即可,做了全局的操作。每一個路由都必須暴露出去,這樣在app.js文件中使用該中間件。 publicRouter.allowedMethods() 根據 ctx.status 設置 response 響應頭

// Routesapp.use(publicRouter.routes(), publicRouter.allowedMethods())app.use(privateRouter.routes(), privateRouter.allowedMethods())

private :該文件下的路由是需要通過jwt驗證的,才能進行訪問。前面我們做了jwt的中間件,我們直接引入即可 router.use(jwtMiddleware) 記得要放在請求路由的前面,才能保證每次都經過它。

'use strict'const Router = require('koa-router')const controllers = require('../controllers')const jwtMiddleware = require('../middlewares/jwt')const router = new Router()router.prefix('/api')router.use(jwtMiddleware)router.get('/test', controllers.test.test)module.exports = router

public :該文件與上面相反,主要用來不進行登錄的校驗,也就是我們常用的登錄、注冊等不需要驗證的接口。

'use strict'const Router = require('koa-router')const controllers = require('../controllers')const router = new Router()router.prefix('/api')router.post('/login', controllers.login.login)module.exports = router

為什么我們沒在這里處理業務邏輯呢?其實這里是遵循了MVC的思想,進行了分離。把數據庫的操作放到了controllers文件中。這如果我們接口一多,不會顯示得特別混亂。下面我們就來講這個文件。

controllers文件

為了讓整個項目更為模塊化,該目錄下主要是處理對應的路由的回調函數,一般我們不會在router文件中去操作數據庫和邏輯操作等步驟,這里采用 routes 和 controller 分開,在方便代碼的查看同時,也方便代碼的維護和開發。

index.js文件:

該文件與models中的index.js文件中的集合該目錄下的文件類似,這里是將其他文件導出統一到index暴露出去。

'use strict'const fs = require('fs')const files = fs.readdirSync(__dirname).filter(file => file !== 'index.js')const controllers = {}for (const file of files) { if (file.toLowerCase().endsWith('js')) { const controller = require(`./${file}`) controllers[`${file.replace(//.js/, '')}`] = controller }}module.exports = controllers

其他文件的編寫可以按照下面基本框架進行,在這里會用到前面封裝好的業務,例如數據庫操作、響應、jwt等操作。大家可以認真看以下代碼分析一下。

'use strict'const jwt = require('jsonwebtoken')const config = require('../config')const User = require('../models/index').getModel('user')const login = {}login.login = async (ctx, next) => { const {userName, password} = ctx.request.body const user = await User.findOne({userName: userName}) if (!user) {  ctx.result = ''  ctx.msg = '用戶不存在' } else {  ctx.result = jwt.sign({   data: user._id,   // 設置 token 過期時間   exp: Math.floor(Date.now() / 1000) + (60 * 60), // 60 seconds * 60 minutes = 1 hour  }, config.secret) } return next()}module.exports = login

config.js文件

該文件主要用來存放全局的配置,如果一個項目中沒有全局的配置,那么一個地方改動牽動的其他地方很多,這樣很不利于工作效率,在開發過程中,我們一般會把常用的都放在這個文件,例如:數據庫參數,端口,密鑰,全局變量等??醋约旱男枨筮m當的更改。該文件將變量進行了暴露,引用時進行require即可。

'use strict'const path = require('path')module.exports = { port: '3001', secret: 'secret', publicDir: path.resolve(__dirname, './public'), logPath: path.resolve(__dirname, './logs/koa-template.log'), mongoDB: { database: 'mall', username: 'root', password: 'root', host: '127.0.0.1', port: 27017 }}

package.json文件

每個Nodejs項目的根目錄下面,一般都會有一個package.json文件。該文件可以由npm init生成,定義了項目所需要的各種模塊,以及項目的配置信息(比如名稱、版本、許可證等元數據)。 package.json文件內部就是一個JSON對象,該對象的每一個成員就是當前項目的一項設置。我們也可在里面配置我們的 npm run XXX 的命令,大家可以根據需求進行配置。這是這項目需要用到的package.json文件。

{ "name": "koa-template", "version": "0.1.0", "author": "bayi", "private": true, "scripts": { "start": "node ./bin/www", "dev": "pm2 start ecosystem.config.js --env dev", "test": "pm2 start ecosystem.config.js --env test", "pro": "pm2 start ecosystem.config.js --env pro", "logs": "pm2 logs", "stop": "pm2 stop ecosystem.config.js" }, "dependencies": { "koa": "^2.6.2", "koa-bodyparser": "^4.2.1", "koa-helmet": "^4.1.0", "koa-jwt": "^3.5.1", "koa-router": "^7.4.0", "koa-static-cache": "^5.1.2", "koa2-cors": "^2.0.6", "log4js": "^3.0.6", "mongoose": "^5.5.5" }}

三、其他

####github地址:

https://github.com/bayi-lzp/koa-template (star! star!star?。?/p>

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。


注:相關教程知識閱讀請移步到JavaScript/Ajax教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
中文字幕国产亚洲| 日韩欧美在线视频免费观看| 国产综合久久久久| 国产99久久久欧美黑人| 亚洲影视九九影院在线观看| 国产精品美女主播在线观看纯欲| 国产精品久久久久久av下载红粉| 最近2019年中文视频免费在线观看| 国产精品久久久久久久久久久不卡| 国产一区红桃视频| 日韩精品视频中文在线观看| 一区二区三区国产在线观看| 国产精品网址在线| 午夜伦理精品一区| 北条麻妃在线一区二区| 久久影院资源站| 国产精品18久久久久久麻辣| 在线精品国产成人综合| 91精品久久久久久久久久久久久| 国产精品狠色婷| 伊人久久久久久久久久久| 韩国欧美亚洲国产| 97免费视频在线| 国产精品福利无圣光在线一区| 精品亚洲一区二区三区在线观看| 国外视频精品毛片| 亚洲欧洲成视频免费观看| 亚洲自拍另类欧美丝袜| 国产美女主播一区| 日韩中文视频免费在线观看| 国产极品精品在线观看| 亚洲片国产一区一级在线观看| 美女撒尿一区二区三区| 国产视频精品久久久| 亚洲人成啪啪网站| 欧美国产日产韩国视频| xxxxx成人.com| 亚洲人成在线观看| 欧美成人午夜激情视频| 色诱女教师一区二区三区| 国产精品久久久久久婷婷天堂| 亚洲精品一区二区三区婷婷月| 日韩在线播放一区| 精品视频久久久| 国内精品模特av私拍在线观看| 日韩精品在线观看视频| 国产亚洲一级高清| 日本sm极度另类视频| 国产一区二区三区在线看| 欧美在线国产精品| 在线观看精品国产视频| 国产精品吹潮在线观看| 97在线视频免费观看| 欧美成人激情图片网| 国产免费一区二区三区香蕉精| 国产精品无码专区在线观看| 最近免费中文字幕视频2019| 一区二区三区国产视频| 国自产精品手机在线观看视频| 91免费视频网站| 九九精品视频在线| 在线看福利67194| 91久久精品国产91久久性色| 久久久国产一区二区| 亚洲国产精品yw在线观看| 国产日韩欧美视频在线| 欧美裸体男粗大视频在线观看| 国产日韩欧美在线播放| 久久久免费在线观看| 91精品国产综合久久久久久蜜臀| 不用播放器成人网| 91精品国产乱码久久久久久久久| 国产成人av在线| 久久久国产视频| 亚洲欧美一区二区精品久久久| 久久久国产精品一区| 亚洲国产天堂久久国产91| 国产精品一区久久久| 日本午夜精品理论片a级appf发布| 国产精品麻豆va在线播放| 亚洲国产精久久久久久| 国产综合在线看| 精品国偷自产在线视频99| 亚洲视频在线免费观看| 国产欧美韩国高清| 日本韩国在线不卡| 久久综合伊人77777尤物| 日韩性生活视频| 精品视频在线播放色网色视频| 日韩一区二区久久久| 亚洲激情电影中文字幕| 国产精品jvid在线观看蜜臀| 亚洲最大成人免费视频| 亚洲国产成人久久综合| 亚洲成人久久一区| 中文综合在线观看| 欧美日韩一区二区三区| 国产视频精品一区二区三区| 日韩精品中文字幕久久臀| 夜夜躁日日躁狠狠久久88av| 国产三级精品网站| 91精品视频免费看| 亚洲第一免费网站| 日韩成人av网| 国产精品精品一区二区三区午夜版| 国产伦精品一区二区三区精品视频| 在线播放国产一区中文字幕剧情欧美| 综合av色偷偷网| 久久久国产视频91| 欧美日韩精品在线| 亚洲精品福利资源站| 国产精品视频免费在线观看| 亚洲成人激情视频| 精品久久久久久久久久国产| 国产亚洲福利一区| 中文亚洲视频在线| 上原亚衣av一区二区三区| 91网站免费观看| 国产不卡在线观看| 亚洲缚视频在线观看| 亚洲一二在线观看| 九九热精品视频| 日本精品免费一区二区三区| 亚洲精品一区二区在线| 精品久久久久久久久中文字幕| 精品国产一区久久久| 91精品国产一区| 日韩精品极品在线观看播放免费视频| 日韩av一区二区在线| 亚洲va久久久噜噜噜| 欧美日韩国产一区中文午夜| 精品国产一区二区三区久久狼黑人| 精品视频在线播放免| 亚洲第一页自拍| 中文字幕精品—区二区| 色琪琪综合男人的天堂aⅴ视频| 日韩视频在线观看免费| 亚洲成人激情在线| 97人洗澡人人免费公开视频碰碰碰| 国产va免费精品高清在线| 亚洲女人天堂色在线7777| 亚洲精品国产品国语在线| 国产精品第二页| 国产日本欧美一区二区三区在线| 中文字幕一区二区三区电影| 国产亚洲视频在线| 亚洲精品aⅴ中文字幕乱码| 久久精品国产99国产精品澳门| 午夜精品久久久久久久久久久久| 亚洲国产精品国自产拍av秋霞| 国内精品国产三级国产在线专| 欧美疯狂做受xxxx高潮| 欧美性xxxxxxx| 夜夜嗨av一区二区三区免费区| 久久婷婷国产麻豆91天堂| 久久久久久香蕉网| 亚洲欧美日韩视频一区| 成人激情春色网| 亚洲aaaaaa| 国产日本欧美在线观看| 国产小视频91| 欧美日韩高清在线观看| 久久久噜久噜久久综合| 久久久噜噜噜久久|