主要介紹node.js的框架的技術選型和框架搭建,以及如何在服務器上部署發佈。這裏客戶端使用小程序來介紹。小程序主要功能涉及到用戶受權登陸,地圖定位,webSocket發送定位,二維碼掃描添加設備。javascript
Koa+Typescript,除了自己類型系統對數據庫的數據模型定義有好處外。Koa中間件的context有不少庫或者用戶自定義數據結構掛載在上面,若是沒有類型聲明,開發者可能不知道context上有哪些類型,致使工程維護性增長。html
Mongodb(www.mongodb.com/cn)Mongodb自己查詢語法是JS寫的,很符合前端的使用。基於文檔處理,自己查詢速度也比較快。關聯表的結構設計,也至關簡單,學習成本低。對於前端來講對錶的設計經驗不足,若是使用mysql之類的關係型數據庫,若是設計不當,極可能致使性能問題。前端
pm2是node社區比較成熟的進程管理框架,自己自帶日誌查看,錯誤重啓,服務器部署的能力。java
總體工程的設計使用mvc的結構,Koa中間件,使用TS類型輔助。node
-src --api 接口的api好比微信小程序登陸受權相關的api --config 配置項 --const 常量 --controllers 控制層 --interfaces 接口 --middleware 自定義中間層 --modules 模型層,主要放數據庫相關的模型數據 --types ts 拓展類型 --utils 工具包,放請求,logger,配置,jwt相關的工具 --server.ts 服務啓動入口 -.env 全局常量配置(用戶自定義的,不提交git) -.env.example 全局常量配置 -ecosystem.config.js pm2的配置文件,部署的時候自動執行mysql
數據庫:docs.mongodb.com/manual/inst… 可視化工具:www.mongodb.com/download-ce… 選擇社區免費版本linux
輸入mongo就能夠鏈接。最好配置用戶和密碼,雖然本地未必要配置密碼,可是服務端確定要配置的,因此就先介紹下如何配置。nginx
db.createUser({ user: "useradmin", pwd: "adminpassword", roles: [{ role: "userAdminAnyDatabase", db: "admin" }] }) 複製代碼
security:
authorization: enabled
複製代碼
6.重啓服務git
brew services restart
複製代碼
7.建立一個應用的數據庫 use app_db 8.對這個應用的數據庫建立權限web
// 擁有者 db.createUser({ user: "youruser", pwd: "yourpassword", roles: [{ role: "dbOwner", db:"app_db" }] }) // 可讀寫 db.createUser({ user: "youruser2", pwd: "yourpassword2", roles: [{ role: "readWrite",db: "app_db" }] }) 複製代碼
9.最後能夠輸入鏈接來啓動
mongodb://youruser2:yourpassword2@localhost/app_db 複製代碼
十、可使用可視化工具compass鏈接
重命名.env.example爲.env,基本的.env代碼以下
# 這個是ENV全局變量,其中變量NODE_ENV在開始執行建立, development: 是開發環境,production:是生產環境。 # mongodb的地址 production生產環境依賴 MONGODB_URI=mongodb://<mlab_user>:<mlab_password>@<mlab_connection_url> # mongodb的地址 developmet開發環境依賴 MONGODB_URI_LOCAL=mongodb://localhost:27017/go_app # token的祕鑰 TOKEN_KEY=ting.ting@huang_GO!GO!GO!!! # 微信AppId WX_APP_ID=wx0840e0b26c481112 # 微信的AppSecret WX_APP_SECRET=34c4824eb1115281d249e85dba4f8157 複製代碼
安裝ts-node和typescript到開發環境
使用npm start命令啓動,安裝nodemon到開發環境,而後以下輸入命令
nodemon --watch 'src/**/*' -e ts,tsx --exec 'ts-node' ./src/server.ts
複製代碼
使用vscode,這裏是我推薦的方式。而後配置launch.json,使用F5啓動、調試。
{
// 使用 IntelliSense 瞭解相關屬性。
// 懸停以查看現有屬性的描述。
// 欲瞭解更多信息,請訪問: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"runtimeArgs": ["-r", "ts-node/register"],
"args": ["${workspaceFolder}/src/server.ts"],
"env": {
"NODE_ENV": "development"
},
"sourceMaps": true,
"cwd": "${workspaceRoot}",
"protocol": "inspector",
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen"
}
]
}
複製代碼
服務器使用CentOS,之因此不使用ubuntu,是由於不必使用到界面,也是大多數服務器採用到的方案。固然使用ubuntu也沒什麼問題,內核都同樣。而後使用yum安裝一些經常使用的工具庫。
首先在本機上建立ssh公鑰和祕鑰,而後去服務器添加公鑰,而後鏈接服務器。 命令以下 ssh -q -l root -p 22 111.230.28.25
和開發環境配置相似,只是都是linux下的,建立密碼和本地使用compass鏈接驗證。這裏注意記得在要給服務開端口。
網上教程不少,我這裏主要介紹使用yum來安裝Nginx,使用yum安裝很是簡單。使用systemctl來啓動(固然也有使用service,可是不能開機啓動了),有興趣想了解systemctl相關命令能夠看看這個www.ruanyifeng.com/blog/2016/0…
$ sudo rpm -ivh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
複製代碼
$ sudo yum install nginx
複製代碼
安裝完Nginx,會生成一個配置文件,路徑是:/etc/nginx/nginx.conf。輸入命令 vim nginx.conf 來編輯
user nginx; worker_processes 1; events { worker_connections 1024; } error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; http { server { listen 80; server_name localhost; location / { proxy_pass http://127.0.0.1:8088; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location ^~ /websocket/ { proxy_pass http://127.0.0.1:8088; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; } } server { listen 443 ssl; server_name localhost ssl on; ssl_certificate cert/2760618_www.dayuan.tech.pem; ssl_certificate_key cert/2760618_www.dayuan.tech.key; ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers ECDH:AESGCM:HIGH:!RC4:!DH:!MD5:!3DES:!aNULL:!eNULL; ssl_prefer_server_ciphers on; location / { proxy_pass http://127.0.0.1:8088; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location ^~ /websocket/ { proxy_pass http://127.0.0.1:8088; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } } include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; keepalive_timeout 65; gzip on; include /etc/nginx/conf.d/*.conf; } 複製代碼
設置開機啓動
systemctl enable nginx
複製代碼
啓動服務
systemctl start nginx
複製代碼
中止服務
systemctl stop nginx
複製代碼
從新啓動服務
systemctl restart nginx
複製代碼
熱更新,也就是不想從新啓動整個服務,只想從新加載配置文件
systemctl reload nginx
複製代碼
和這裏圖有點不一樣的是,登陸憑證校驗完後,我是使用一個會過時token來驗證。驗證成功後客戶端會發送一次獲取頭像和暱稱等用戶基本信息的請求,獲取後,再把這些傳回給開發者服務器。之後用戶基本信息都從開發者服務器獲取就好。 還有一個主意點微信的auth.getAccessToken,須要按期獲取,具體以下developers.weixin.qq.com/miniprogram…。
// 路由模塊使用前須要先安裝和實例化 import Router from 'koa-router' import fs from 'fs' import checkToken from '@/middleware/checkToken' const router = new Router() /** * 將全部controller下的文件都加載到router */ let urls = fs.readdirSync(__dirname + '/../controllers') // 全部請求api路由前都要通過這個控制層 router.use('/api', checkToken) urls.forEach((element: string) => { let module = require(__dirname + '/../controllers/' + element) router.use('/api', module.default.routes(), module.default.allowedMethods()) }) export default router 複製代碼
若是不用Typegoose
interface Car { model?: string; } interface Job { title?: string; position?: string; } interface User { name?: string; age: number; job?: Job; car: Car | string; } mongoose.model('User', { name: String, age: { type: Number, required: true }, job: { title: String; position: String; }, car: { type: Schema.Types.ObjectId, ref: 'Car' } }); mongoose.model('Car', { model: string, }); 複製代碼
用了之後
class Job { @prop() title?: string; @prop() position?: string; } class Car extends Typegoose { @prop() model?: string; } class User extends Typegoose { @prop() name?: string; @prop({ required: true }) age!: number; @prop() job?: Job; @prop({ ref: Car }) car?: Ref<Car>; } 複製代碼
不管是kos還webSocket都是調用Node標準的http模塊建立的http.Server監聽的,koa只是把響應的函數註冊到http.Server,同理WebSocket也能夠把響應的函數註冊到http.Server,因此可使用同一個端口。我是對webSokcet作了一層封裝,其中鏈接的代碼以下
function connectSocket(server: Server) { wss = new WebSocketServer({ server }) wss.on('connection', onConnection) server.on('upgrade', (request, socket, head) => { const pathname = url.parse(request.url).pathname if (pathname === '/websocket/location') { wss.handleUpgrade(request, socket, head, ws => { wss.emit('connection', ws, request) }) } }) } 複製代碼