ThinkJS (官網(wǎng) https://thinkjs.org) 是一款非常優(yōu)秀的 Node.js 國產(chǎn) MVC 開發(fā)框架,下面摘自官網(wǎng)的介紹:
ThinkJS 是一款使用 ES6/7 特性全新開發(fā)的 Node.js MVC 框架,使用 ES7 中 async/await埂陆,或者 ES6 中的 */yield 特性徹底解決了 Node.js 中異步嵌套的問題滑负。同時(shí)吸收了國內(nèi)外眾多框架的設(shè)計(jì)理念和思想骡技,讓開發(fā) Node.js 項(xiàng)目更加簡單、高效榛斯。
使用 ES6/7 特性來開發(fā)項(xiàng)目可以大大提高開發(fā)效率蔓钟,是趨勢(shì)所在永票。并且新版的 Node.js 對(duì) ES6 特性也有了較好的支持,即使有些特性還沒有支持,也可以借助 Babel 編譯來支持瓦侮。
目前 ThinkJS 版本發(fā)布到了 v2.2.19 (更新日志)艰赞,并且 v3.0beta 版本已經(jīng)進(jìn)入公測(cè)階段佣谐。
本系列教程以 v2.x 版本為例進(jìn)行介紹肚吏,教程以實(shí)際操作為主,ThinkJS 的安裝詳見官網(wǎng)文檔說明狭魂。
原創(chuàng):荊秀網(wǎng) 網(wǎng)頁即時(shí)推送 https://xxuyou.com | 轉(zhuǎn)載請(qǐng)注明出處
鏈接:https://blog.xxuyou.com/nodejs-thinkjs-study-start/
官網(wǎng)提供了創(chuàng)建一個(gè)空項(xiàng)目罚攀,以及空項(xiàng)目的代碼結(jié)構(gòu)介紹,這里不再贅述雌澄。以下是一些官網(wǎng)沒有提到的小技巧斋泄,先做個(gè)了解~
新項(xiàng)目
為了確保用戶錯(cuò)誤操作導(dǎo)致現(xiàn)有文件被覆蓋,thinkjs new
命令僅適用于文件夾不存在的镐牺,或者空文件夾炫掐。否則會(huì)收到類似如下的錯(cuò)誤提示:
path `/data/www/demo` is already a thinkjs project.
實(shí)現(xiàn)這一特性其實(shí)是依賴一個(gè)項(xiàng)目根目錄下的隱藏文件 .thinkjsrc
,使用 ls -a
可以查看隱藏文件睬涧,打開這個(gè)文件可以看到如下內(nèi)容:
{
"createAt": "2017-02-12 19:08:38",
"mode": "module",
"es": true
}
按模塊分解
創(chuàng)建項(xiàng)目之后募胃,基本的代碼框架已經(jīng)建立起來了(詳見 https://thinkjs.org/zh-cn/doc/2.2/app_structure.html),其中默認(rèn)的 home
和 common
肯定是無法滿足要求的畦浓。我們需要給自己的項(xiàng)目建立起相關(guān)的層次結(jié)構(gòu)痹束。
以下是幾個(gè)較為典型的項(xiàng)目模塊結(jié)構(gòu)參考。
簡單網(wǎng)站
例如官方網(wǎng)站讶请、博客祷嘶、社區(qū)等,這類系統(tǒng)結(jié)構(gòu)較為簡單夺溢,通常一個(gè)前端一個(gè)后端管理即可滿足要求论巍。
模塊結(jié)構(gòu)如下:
src/
src/common/ # 通用模塊,放置主配置參數(shù)风响、boostrap adapter middleware service 等相關(guān)組件
src/home/ # 前端默認(rèn)模塊
src/backend/ # 后端管理模塊
src/util/ # 系統(tǒng)工具類
電商平臺(tái)
電商平臺(tái)系統(tǒng)主要考慮到入駐的商戶嘉汰、注冊(cè)的客戶、管理人員钞诡、運(yùn)營人員等使用人群郑现,還需要考慮到較大的功能模塊切分(如果足夠大到類似京東、天貓那種體量的系統(tǒng)荧降,則需要進(jìn)行數(shù)據(jù)接箫、功能、服務(wù)朵诫、位置等角度的分割)辛友。
模塊結(jié)構(gòu)如下:
src/
src/common/
src/home/
src/sso/ # 單點(diǎn)登錄、令牌管理等
src/rest/ # 針對(duì)Wap、App等多客戶端的 rest api
src/goods/ # 商品管理及服務(wù)
src/storage/ # 庫存管理及服務(wù)
src/cart/ # 購物車
src/order/ # 訂單
src/delivery/ # 快遞
src/pay/ # 在線支付废累、空中支付
src/member/ #
src/coupon/ # 電子券
src/promotion/ # 促銷
src/points/ # 積分
src/merchant/ # 入駐商戶
src/shop/ # 商戶門店
src/finance/ # 財(cái)務(wù)核算及款項(xiàng)清算
src/stat/
src/log/
src/monitor/
src/util/
src/task/
src/message/ # 消息隊(duì)列
即時(shí)消息平臺(tái)
實(shí)時(shí)推送平臺(tái)不僅僅要處理 WebSocket 連接和消息囤積發(fā)送邓梅,還要處理多用戶購買相應(yīng)服務(wù)套餐、統(tǒng)計(jì)連接數(shù)邑滨、統(tǒng)計(jì)下行流量日缨、進(jìn)行連接鑒權(quán)等,Firebase掖看、野狗匣距、荊秀即時(shí)推送 等都是這類的服務(wù)商。
模塊結(jié)構(gòu)如下:
src/
src/common/
src/home/
src/rest/
src/storage/
src/websocket/ # ws 或者 wss 服務(wù)
src/webhook/ # 鉤子服務(wù)
src/middleware/ # 搭載中間件運(yùn)行
src/pay/
src/member/
src/stat/
src/log/
src/monitor/
src/util/
src/message/ # 消息隊(duì)列
代駕哎壳、租車運(yùn)營平臺(tái)
代駕毅待、租車、共享單車等平臺(tái)需要解決的是資源(客戶归榕、車尸红、目的地)定位、路線計(jì)算刹泄、實(shí)時(shí)定點(diǎn)跟蹤外里、GPS圍欄監(jiān)測(cè)等技術(shù)問題,然后才是商務(wù)行為的電子化處理循签。
模塊結(jié)構(gòu)如下:
src/
src/common/
src/home/
src/rest/
src/map/ # 地圖資源级乐、路線計(jì)算、電子圍欄運(yùn)算
src/storage/
src/websocket/ # 實(shí)時(shí)消息傳遞
src/pay/
src/member/
src/driver/
src/assets/ # 資源費(fèi)效評(píng)估
src/stat/
src/log/
src/math/ # 計(jì)算服務(wù)
src/monitor/
src/util/
在線教育县匠、直播平臺(tái)
在線教育或直播平臺(tái)通常具備實(shí)時(shí)音視頻上傳风科、轉(zhuǎn)碼、存儲(chǔ)乞旦、廣播等硬性要求贼穆,因此系統(tǒng)除了管理相關(guān)課件、學(xué)生兰粉、教師故痊、選課等,還要負(fù)責(zé)處理相關(guān)媒體文件玖姑。
模塊結(jié)構(gòu)如下:
src/
src/common/
src/home/
src/rest/
src/sso/ # 單點(diǎn)登錄愕秫、令牌管理等
src/media/ # 課件、音視頻等媒體文件
src/bulk/ # 流媒體
src/process/ # 編解碼處理
src/storage/
src/live/ # 直播
src/pay/
src/student/
src/teacher/
src/schedule/
src/stat/
src/log/
src/monitor/
src/util/
src/task/
src/message/ # 消息隊(duì)列
注:以上結(jié)構(gòu)為示例焰络,并不具備通用性戴甩,研發(fā)時(shí)應(yīng)當(dāng)需要根據(jù)實(shí)際情況進(jìn)行設(shè)計(jì)或調(diào)整。
項(xiàng)目模式
項(xiàng)目模式其實(shí)官網(wǎng)有介紹闪彼,但是太過簡略甜孤,基本上是一筆帶過。看看如下兩種創(chuàng)建 thinkjs 項(xiàng)目的方式:
# 用 mode 參數(shù)創(chuàng)建一個(gè)簡單結(jié)構(gòu)項(xiàng)目
thinkjs new thinkjs_normal --mode=normal
# 無 mode 參數(shù)創(chuàng)建一個(gè)較為復(fù)雜結(jié)構(gòu)的項(xiàng)目
thinkjs new thinkjs_module
兩者創(chuàng)建的項(xiàng)目結(jié)構(gòu)區(qū)別其實(shí)很簡單:
-
normal mode 的結(jié)構(gòu)直接把
config
controller
logic
model
提到src
下面缴川,因此適用于一個(gè)簡單的網(wǎng)站系統(tǒng)茉稠。 -
module mode 則建立了基本的
home
和common
兩個(gè)應(yīng)用模塊,顯然是為了較為復(fù)雜把夸、多人協(xié)作的中大型項(xiàng)目進(jìn)行的邏輯分割而线。
thinkjs_normal 項(xiàng)目結(jié)構(gòu)
thinkjs_normal/package.json
thinkjs_normal/.babelrc
thinkjs_normal/.thinkjsrc
thinkjs_normal/nginx.conf
thinkjs_normal/pm2.json
thinkjs_normal/.gitignore
thinkjs_normal/README.md
thinkjs_normal/www
thinkjs_normal/www/development.js
thinkjs_normal/www/production.js
thinkjs_normal/www/testing.js
thinkjs_normal/www/README.md
thinkjs_normal/www/static
thinkjs_normal/www/static/js
thinkjs_normal/www/static/css
thinkjs_normal/www/static/img
thinkjs_normal/src
thinkjs_normal/src/bootstrap
thinkjs_normal/src/bootstrap/middleware.js
thinkjs_normal/src/bootstrap/global.js
thinkjs_normal/src/config
thinkjs_normal/src/config/config.js
thinkjs_normal/src/config/view.js
thinkjs_normal/src/config/db.js
thinkjs_normal/src/config/hook.js
thinkjs_normal/src/config/session.js
thinkjs_normal/src/config/error.js
thinkjs_normal/src/config/env
thinkjs_normal/src/config/env/development.js
thinkjs_normal/src/config/env/testing.js
thinkjs_normal/src/config/env/production.js
thinkjs_normal/src/config/locale
thinkjs_normal/src/config/locale/en.js
thinkjs_normal/src/controller
thinkjs_normal/src/controller/error.js
thinkjs_normal/view
thinkjs_normal/view/error_400.html
thinkjs_normal/view/error_403.html
thinkjs_normal/view/error_404.html
thinkjs_normal/view/error_500.html
thinkjs_normal/view/error_503.html
thinkjs_normal/src/controller/base.js
thinkjs_normal/src/controller/index.js
thinkjs_normal/src/logic
thinkjs_normal/src/logic/index.js
thinkjs_normal/src/model
thinkjs_normal/src/model/index.js
thinkjs_normal/view/index_index.html
thinkjs_module 項(xiàng)目結(jié)構(gòu)
thinkjs_module/package.json
thinkjs_module/.babelrc
thinkjs_module/.thinkjsrc
thinkjs_module/nginx.conf
thinkjs_module/pm2.json
thinkjs_module/.gitignore
thinkjs_module/README.md
thinkjs_module/www
thinkjs_module/www/development.js
thinkjs_module/www/production.js
thinkjs_module/www/testing.js
thinkjs_module/www/README.md
thinkjs_module/www/static
thinkjs_module/www/static/js
thinkjs_module/www/static/css
thinkjs_module/www/static/img
thinkjs_module/src
thinkjs_module/src/common/bootstrap
thinkjs_module/src/common/bootstrap/middleware.js
thinkjs_module/src/common/bootstrap/global.js
thinkjs_module/src/common/config
thinkjs_module/src/common/config/config.js
thinkjs_module/src/common/config/view.js
thinkjs_module/src/common/config/db.js
thinkjs_module/src/common/config/hook.js
thinkjs_module/src/common/config/session.js
thinkjs_module/src/common/config/error.js
thinkjs_module/src/common/config/env
thinkjs_module/src/common/config/env/development.js
thinkjs_module/src/common/config/env/testing.js
thinkjs_module/src/common/config/env/production.js
thinkjs_module/src/common/config/locale
thinkjs_module/src/common/config/locale/en.js
thinkjs_module/src/common/controller
thinkjs_module/src/common/controller/error.js
thinkjs_module/view/common
thinkjs_module/view/common/error_400.html
thinkjs_module/view/common/error_403.html
thinkjs_module/view/common/error_404.html
thinkjs_module/view/common/error_500.html
thinkjs_module/view/common/error_503.html
thinkjs_module/src/home/config
thinkjs_module/src/home/config/config.js
thinkjs_module/src/home/controller
thinkjs_module/src/home/controller/base.js
thinkjs_module/src/home/controller/index.js
thinkjs_module/src/home/logic
thinkjs_module/src/home/logic/index.js
thinkjs_module/src/home/model
thinkjs_module/src/home/model/index.js
thinkjs_module/view/home
thinkjs_module/view/home/index_index.html
配置參數(shù)
官網(wǎng)是這么描述配置文件加載順序的:
框架默認(rèn)的配置 -> 項(xiàng)目模式下框架配置 -> 項(xiàng)目公共配置 -> 項(xiàng)目模式下的公共配置 -> 模塊下的配置
先問個(gè)問題:這五個(gè)配置都指的是哪里呢?
前兩個(gè)可以忽略掉扎即,那是 thinkjs 框架自身的配置設(shè)置吞获,通常里面不會(huì)有我們項(xiàng)目會(huì)用到的配置參數(shù)况凉。
第三個(gè)和第四個(gè)則是在不同的項(xiàng)目創(chuàng)建模式下的默認(rèn) config 配置文件夾谚鄙,位置在:
# normal mode
thinkjs_normal/src/config/*
# module mode
thinkjs_module/src/common/config/*
最后一個(gè)是指的在 module mode 下的項(xiàng)目,每個(gè) module 自己的 config刁绒,位置在:
thinkjs_module/src/home/config/*
明白了多個(gè)地方多個(gè)配置文件的玩法之后闷营,你可以創(chuàng)建多個(gè) module,并給每個(gè) module 配置自身獨(dú)特的配置參數(shù)知市。
需要注意的是:thinkjs 加載配置文件是有順序的傻盟!回到本節(jié)一開始提到的加載順序,你應(yīng)當(dāng)明白:多個(gè)配置文件最終會(huì)在 thinkjs 運(yùn)行時(shí)被全部加載嫂丙,并合并在一起(注意加粗文字)娘赴。
所以當(dāng)存在多個(gè)配置文件時(shí),需要注意配置參數(shù)的 key(即屬性名)盡量不要重復(fù)跟啤,因?yàn)榘凑占虞d順序诽表,后加載的 key 的值會(huì)覆蓋先加載的 key 的值,導(dǎo)致出現(xiàn)不希望的結(jié)果隅肥。
舉例來說竿奏,有兩個(gè)配置文件 src/common/config/assets.js
和 src/home/config/assets.js
,其中內(nèi)容是:
// src/common/config/assets.js
export default {
"site_title": "my site"
};
// src/home/config/assets.js
export default {
"site_title": "my test"
};
// src/home/controller/index.js
let assets = this.config('assets');
let siteTitle = assets['site_title'];
console.log('siteTitle is: ', siteTitle); // my test
注:當(dāng)然也有辦法獲取到 "my site" 這個(gè)值腥放,后面的教程會(huì)提到方法泛啸。
公共方法
thinkjs 提供了一個(gè) src/common/bootstrap/global.js
文件來放置全局變量/函數(shù)。
// 可以直接在 global.js 中增加自己定義的函數(shù)
global.formatDate = obj => {
//...
}
如果你的自定義函數(shù)很多秃症,想分門別類的組織候址,也可以在 src/common/bootstrap/
文件夾下新增文件來定義函數(shù)。當(dāng)項(xiàng)目啟動(dòng)時(shí)种柑,該目錄下的文件會(huì)自動(dòng)加載岗仑,無需手動(dòng) require。
src/common/bootstrap/global_datetime.js
src/common/bootstrap/global_math.js
src/common/bootstrap/global_string.js
注:thinkjs v3.x 可能會(huì)取消 bootstrap
莹规,想要升級(jí)的朋友們注意了赔蒲。 ThinkJS v3.x 設(shè)計(jì)圖
Babel 編譯時(shí)刪除注釋
開發(fā)時(shí)的工作代碼都在 src
下面,運(yùn)行時(shí)才會(huì)編譯到 app
下面成為運(yùn)行腳本(經(jīng)過 Babel 編譯),如果不想自己寫的各種注釋也出現(xiàn)在 app
下面的代碼中舞虱,可以修改項(xiàng)目目錄下的一個(gè)隱藏文件 .babelrc
增加相應(yīng) comments
參數(shù)欢际。
增加該參數(shù)后編譯速度會(huì)比較慢,因?yàn)樾枰幚淼拇a內(nèi)容多了~
{
"presets": [
["es2015", {"loose": true}],
"stage-1"
],
"plugins": ["transform-runtime"],
"sourceMaps": true,
"comments": false # <-- 就是這個(gè)參數(shù)
}
注:給喜歡在生產(chǎn)服務(wù)器就地編譯的筒子們矾兜。
完善 package.json 字段
package 打包描述文件雖然會(huì)被 thinkjs 自動(dòng)生成损趋,不過如果能夠手工維護(hù)這個(gè)文件,添加必要的屬性椅寺,會(huì)讓我們的項(xiàng)目工程更加規(guī)范浑槽、有序。
參考一下 thinkjs v2.x 源碼的 package.json 文件:
{
"name": "thinkjs",
"description": "ThinkJS - Use full ES6/7 features to develop web applications, Support TypeScript",
"version": "2.2.18",
"author": {
"name": "welefen",
"email": "welefen@gmail.com"
},
"scripts": {
"test": "npm run eslint && npm run test-cov",
"test-cov": "istanbul cover ./node_modules/mocha/bin/_mocha -- -t 50000 --recursive -R spec test/",
"compile": "babel src/ --out-dir lib/",
"watch-compile": "npm run compile -- --watch",
"watch": "npm run watch-compile",
"prepublish": "npm run compile",
"eslint": "eslint src/"
},
"bin": {
"thinkjs": "./bin/index.js"
},
"contributors": [
{
"name": "welefen",
"email": "welefen@gmail.com"
},
{
"name": "im-kulikov",
"email": "im@kulikov.im"
},
{
"name": "maxzhang",
"email": "zhangdaiping@gmail.com"
},
{
"name": "akira-cn",
"email": "akira.cn@gmail.com"
},
{
"name": "qgy18",
"email": "quguangyu@gmail.com"
}
],
"main": "lib/index.js",
"dependencies": {
"ejs": "2.4.1",
"multiparty": "4.1.2",
"mime": "1.3.4",
"mysql": "2.11.1",
"thinkit": "4.10.0",
"babel-runtime": "6.6.1",
"bluebird": "3.3.5",
"co": "4.6.0",
"colors": "1.1.2",
"validator": "4.2.0",
"commander": "2.9.0"
},
"devDependencies": {
"mocha": "1.20.1",
"muk": "0.3.1",
"istanbul": "0.4.0",
"babel-cli": "^6.18.0",
"babel-preset-es2015": "^6.18.0",
"babel-preset-stage-1": "^6.16.0",
"babel-plugin-transform-runtime": "^6.15.0",
"babel-core": "^6.20.0",
"babel-eslint": "^6.0.4",
"eslint": "2.8.0",
"typescript": "^2.1.6",
"source-map": "0.5.3"
},
"keywords": [
"thinkjs",
"framework",
"web",
"rest",
"restful",
"router",
"api",
"es6",
"es7",
"async",
"await",
"yield",
"websocket",
"generator-function",
"typescript"
],
"repository": {
"type": "git",
"url": "https://github.com/thinkjs/thinkjs"
},
"engines": {
"node": ">=0.12.0"
},
"license": "MIT",
"readmeFilename": "README.md",
"bugs": {
"url": "https://github.com/thinkjs/thinkjs/issues"
}
}
修改 pm2 日志位置
pm2 (官網(wǎng) http://pm2.keymetrics.io)是一個(gè)優(yōu)秀的 Node.js 進(jìn)程管理器返帕。
它的強(qiáng)大之處在于不僅可以作為 Node.js 項(xiàng)目的守護(hù)進(jìn)程桐玻,還具備可配置化啟動(dòng)、分布式支持荆萤、內(nèi)存監(jiān)控镊靴、熱重載(優(yōu)雅重載)、支持?jǐn)?shù)據(jù)統(tǒng)計(jì)链韭、運(yùn)行日志記錄偏竟、實(shí)時(shí)運(yùn)行監(jiān)控、API 和腳本支持等強(qiáng)大的特性敞峭。(更多的特性踊谋,另文描述~)
thinkjs 推薦使用 pm2 來管理項(xiàng)目運(yùn)行,并自動(dòng)生成了 pm2 的配置文件 pm2.json
旋讹。
默認(rèn)生成的 pm2 配置文件不含日志記錄部分殖蚕,如果不單獨(dú)配置,pm2 的日志將會(huì)保存在安裝目錄中骗村,查找起來很不方便(當(dāng)然你可以使用 pm2 logs [id|name]
來直接查看某個(gè)進(jìn)程的日志嫌褪,不過有些時(shí)候還是需要直接查看日志文件的)。
我的做法是:在項(xiàng)目目錄下建立 logs
文件夾胚股,用來放置 pm2 以及其他(諸如 log4js 等等)日志笼痛,打開 pm2.json
,給 apps[0]
增加如下幾行配置參數(shù):
{
"apps": [{
"error_file" : "/data/www/thinkjs_module/logs/pm2-err.log",
"out_file" : "/data/www/thinkjs_module/logs/pm2-out.log",
"log_date_format" : "YYYY-MM-DD HH:mm:ss Z",
"merge_logs" : false
}]
}
- error_file pm2 捕捉到的致命錯(cuò)誤記錄在這里
- out_file pm2 接收到的 console 輸出記錄在這里
- log_date_format 日期和時(shí)間格式
- merge_logs 是否給日志文件增加進(jìn)程id的后綴
注:更詳細(xì)的參數(shù)配置琅拌,可前往 pm2 官網(wǎng)查閱缨伊。
done~
下一篇:Node.js 國產(chǎn) MVC 框架 ThinkJS 開發(fā) config 篇(荊秀網(wǎng))
原創(chuàng):荊秀網(wǎng) 網(wǎng)頁即時(shí)推送 https://xxuyou.com | 轉(zhuǎn)載請(qǐng)注明出處
鏈接:https://blog.xxuyou.com/nodejs-thinkjs-study-start/