去年上半年開始接觸了一些JS的后端編程碧查,參與了一個(gè)基于node(其實(shí)是Meteor)的開源項(xiàng)目运敢,有一些知識(shí)上的積累,現(xiàn)在回歸了Java老本行忠售,怕再過段時(shí)間就忘了传惠,在這里記錄一下,好記性不如爛筆頭稻扬,說不定以后會(huì)有用卦方。node大神可以看來(lái)消遣,跟我一樣是外行但是需要寫一些node程序的可以看看經(jīng)驗(yàn)泰佳。這篇文章里會(huì)包含以下內(nèi)容:
- 背景
- 關(guān)于Wekan
- 關(guān)于Meteor
- 關(guān)于publication&subscription
- 關(guān)于Jade&Stylus
- 關(guān)于JS
背景
第一次知道nodejs是在12年實(shí)習(xí)時(shí)盼砍,那時(shí)只感覺寫出來(lái)的代碼好難看,覺得JS寫服務(wù)端性能肯定也不咋滴逝她。直到2016年之前衬廷,我對(duì)于JS的使用還僅限于在網(wǎng)頁(yè)端偶爾用來(lái)做一些字段驗(yàn)證,甚至連JQuery都不怎么會(huì)用汽绢,老忘記各種selector的語(yǔ)法吗跋。
16年開始接觸了一些nodejs的框架,忽然好像發(fā)現(xiàn)了個(gè)新天地,ES6的語(yǔ)法太美妙跌宛,nodejs的「單線程異步IO」的設(shè)計(jì)也可以最大限度地發(fā)揮CPU的性能酗宋。后來(lái)為了提高工作效率,開始在公司推敏捷疆拘,于是找到了一個(gè)開源的KANBAN(關(guān)于KANBAN可以看這里)工具Wekan蜕猫,使用一段時(shí)間后發(fā)現(xiàn)少了兩個(gè)很重要的feature:
Wekan設(shè)計(jì)的理念是像Trello那樣的一個(gè)開放的KANBAN平臺(tái),所以默認(rèn)是開放注冊(cè)的哎迄,但是有很多用戶會(huì)像我這樣把它部署在自己的私服上(像gitlab一樣)回右,所以希望有一個(gè)開關(guān),可以控制不開放注冊(cè)漱挚,而只能邀請(qǐng)注冊(cè)翔烁。
在卡片中沒有一個(gè)可以check的列表,讓任務(wù)的管理者去更細(xì)粒度地控制這個(gè)任務(wù)旨涝。
于是去issue和PR里找蹬屹,發(fā)現(xiàn)好多人都在等待著兩個(gè)feature,于是想白华,等他們搞不如自己搞慨默。于是開始了第一次真正的node項(xiàng)目的開發(fā)。之前做過一些基于Koa和Express的開發(fā)弧腥,和Meteor還是有很大的區(qū)別厦取。
關(guān)于Wekan
Wekan是一個(gè)開源的KANBAN(看板管理)工具,是一種較簡(jiǎn)單(相對(duì)于Scrum和XP)的敏捷開發(fā)的理念管搪。KANBAN工具比較有名的有Trello等蒜胖。Wekan和Trello十分相似,具體的可以去查閱Wekan項(xiàng)目的Wiki抛蚤。Wekan的優(yōu)勢(shì)就是,對(duì)于不想在公共平臺(tái)上部署自己的項(xiàng)目管理工具的公司寻狂,以MIT協(xié)議開源的Wekan是一個(gè)很好的選擇岁经,如果你也有這方面的需求,不妨試一試Wekan蛇券。
Wekan is an open-source kanban board which allows a card-based task and to-do management, similar to tools like WorkFlowy or Trello.
---- Wekan Wiki
從技術(shù)上講缀壤,Wekan的后端整體和前端的渲染引擎是基于Meteor的,前端的模板和樣式使用了Jade和Stylus纠亚,對(duì)于這三個(gè)東西都是比較陌生的塘慕,本文主要講的就是如何快速地融入這種技術(shù)棧不熟悉的項(xiàng)目開發(fā)中去。
關(guān)于Meteor
首先就是去搜索了一下關(guān)于這個(gè)框架的文章蒂胞,這樣可以簡(jiǎn)單地建立起來(lái)對(duì)它的一個(gè)感性認(rèn)識(shí)图呢。找到了一些簡(jiǎn)單的介紹,和一個(gè)中文的社區(qū),但是剛剛建立蛤织,資料也很少赴叹。于是果斷開始閱讀官方文檔,所幸官方文檔十分詳細(xì)指蚜。
Meteor是一個(gè)基于nodejs的全棧開發(fā)框架乞巧,致力于使開發(fā)者快速、高效地構(gòu)建高響應(yīng)的富客戶端Web應(yīng)用摊鸡。技術(shù)棧包括MongoDB绽媒、WebSocket、Blaze等免猾。Meteor引入了客戶端DB的概念是辕,使得Meteor開發(fā)的應(yīng)用,可以天然的達(dá)到前端的實(shí)時(shí)響應(yīng)掸刊。
從上圖中可以看到免糕,服務(wù)端通過publication把一部分?jǐn)?shù)據(jù)發(fā)布到前端,前端通過subscription可以直接調(diào)用這些數(shù)據(jù)忧侧。對(duì)于前端來(lái)說石窑,它只和前端數(shù)據(jù)庫(kù)交互,基本上等于本地交互蚓炬,所以響應(yīng)很快松逊,而前端數(shù)據(jù)庫(kù)再通過和后端實(shí)時(shí)同步數(shù)據(jù)來(lái)達(dá)到和后端交互的目的。
像聊天應(yīng)用這種實(shí)時(shí)性要求比較高的服務(wù)肯夏,可以直接從這種架構(gòu)受益经宏,用戶幾乎感受不到延遲,而且服務(wù)器上的數(shù)據(jù)更新也會(huì)實(shí)時(shí)同步到訂閱它的客戶端驯击。
安裝
根據(jù)官網(wǎng)的介紹烁兰,安裝Meteor只需要在Console中執(zhí)行curl https://install.meteor.com/ | sh
,然而徊都,由于網(wǎng)絡(luò)原因沪斟,在中國(guó)直接這么做簡(jiǎn)直是折磨人,要等到花兒都謝了(除非你有一個(gè)強(qiáng)大的穩(wěn)定的合法的VPN)暇矫。
我的做法是首先把網(wǎng)頁(yè)https://install.meteor.com/的內(nèi)容保存到本地主之,下載其中TARBALL_URL
的包,保存到INSTALL_TMPDIR
中的目錄李根,然后注釋掉文件中的下載命令(echo "Downloading Meteor distribution"
這一行的后面的一坨)幻赚,然后執(zhí)行文件冗荸。
Meteor目錄結(jié)構(gòu)
Meteor也遵循「convention over configuration」阶淘,它有默認(rèn)的一套目錄結(jié)構(gòu)栽渴,遵循這套規(guī)則可以極大地提高開發(fā)效率所森。Meteor項(xiàng)目的文件載入順序如下:
- HTML模板文件總是比其他文件先被載入
- 以main為名字的文件總是最后被載入
- lib目錄下的文件隨后被載入
- 更深目錄中的文件隨后被載入
- 其他文件按照字符順序被載入
還有一些特殊目錄:
- imports
這個(gè)文件夾中的文件不會(huì)被載入,除非使用import
語(yǔ)句映入到其他文件琼讽。 - client
這個(gè)文件中的文件不會(huì)被服務(wù)端的程序載入必峰,相當(dāng)于在程序中使用if (Meteor.isClient) { ... }
來(lái)執(zhí)行代碼。在production環(huán)境這個(gè)文件夾下的相關(guān)文件會(huì)被壓縮钻蹬。 - server
與client相對(duì)應(yīng)吼蚁,這里的代碼不會(huì)被客戶端程序載入。相當(dāng)于在if (Meteor.isServer) { ... }
中執(zhí)行问欠。 - public
項(xiàng)目頂級(jí)目錄下public文件夾內(nèi)的文件可以被任何人引用肝匆。
再看Wekan的目錄結(jié)構(gòu)如下,項(xiàng)目的代碼結(jié)構(gòu)和相互間的關(guān)系就很清晰了:
lkMacBook-Pro:wekan-setting lk$ tree -dL 2
.
├── client
│ ├── components
│ ├── config
│ └── lib
├── config
├── i18n
├── meta
│ ├── icons
│ ├── screenshots
│ └── t9n-changelog
├── models
├── node_modules
│ ├── fibers
│ ├── node-gyp
│ └── xss
├── public
│ └── fonts
└── server
├── lib
├── notifications
└── publications
21 directories
通過讀文檔和讀代碼顺献,基本上對(duì)于現(xiàn)有項(xiàng)目的結(jié)構(gòu)有了個(gè)初步認(rèn)識(shí)旗国,看到各個(gè)目錄和文件,大致知道其代表的意義注整,那么接下來(lái)就是寫代碼了能曾。對(duì)于這種已經(jīng)有了大量代碼基礎(chǔ)的項(xiàng)目,有個(gè)優(yōu)勢(shì)就是「有很多可以參考的代碼」肿轨,可以幫助剛接觸的人更容易寫出更好的代碼寿冕。
關(guān)于publication&subscription
開篇時(shí)談到的兩個(gè)需求,第一個(gè)是先想到的椒袍,所以剛開始是拿這個(gè)來(lái)實(shí)驗(yàn)的驼唱。分析這個(gè)需求,大約有以下幾個(gè)點(diǎn):
要有限制注冊(cè)的功能
用戶注冊(cè)時(shí)驹暑,必須輸入邀請(qǐng)碼玫恳,否則無(wú)法注冊(cè)。要有一個(gè)默認(rèn)的管理員
系統(tǒng)部署好之后优俘,系統(tǒng)是可以任意注冊(cè)的京办,這時(shí)需要管理員去注冊(cè)一個(gè)賬號(hào),然后這個(gè)賬號(hào)自然地成為管理員帆焕,然后他可以設(shè)置系統(tǒng)為僅限邀請(qǐng)用戶注冊(cè)惭婿。要有邀請(qǐng)碼的管理
設(shè)計(jì)一個(gè)管理頁(yè)面(Admin Panel),讓管理員可以發(fā)送邀請(qǐng)视搏,邀請(qǐng)通過郵件發(fā)送,同時(shí)要可以配置Email發(fā)件地址县袱。
這三點(diǎn)對(duì)于服務(wù)端的需求很簡(jiǎn)單浑娜,首先增加兩張表,一張存儲(chǔ)系統(tǒng)的設(shè)置models/setting.js式散,一張存儲(chǔ)邀請(qǐng)碼models/invitationCode.js筋遭,然后在用戶的表中添加isAdmin的屬性。只要參照已有的一些表的寫法,肯定不會(huì)錯(cuò)到哪里去漓滔,另外寫的過程中再看一看官方文檔中關(guān)于「Collection」的一章编饺,很快就可以搞定了。
其中setting和isAdmin的屬性是需要publish給前端使用响驴,結(jié)合上邊的一些知識(shí)透且,很容易就知道是在server/publication中稍微改動(dòng)一些東西就好了。還好Meteor的文檔很完整也很詳細(xì)豁鲤,這部分開發(fā)沒有碰到什么比較大的阻力秽誊。
publication和subscription之間的通信使用了Meteor的一個(gè)自定義的RPC協(xié)議(DDP,一種基于WebSocket的自定義協(xié)議)琳骡,對(duì)這個(gè)東西并沒有作更深的探究锅论,簡(jiǎn)單看了一下,貌似WebSocket協(xié)議是Meteor自己實(shí)現(xiàn)的楣号,并沒有使用更廣為使用的WebSocket組件ws最易,如果服務(wù)器不支持WebSocket,則會(huì)使用sockjs實(shí)現(xiàn)長(zhǎng)輪訓(xùn) 炫狱。
關(guān)于Jade&Stylus
Wekan的前端使用了一系列增加開發(fā)效率的JS組件藻懒,下面是其中涉及到賬戶系統(tǒng)的部分:
# Account system
accounts-password
kenton:accounts-sandstorm
service-configuration
useraccounts:core
useraccounts:unstyled
useraccounts:flow-routing
要修改和賬戶管理相關(guān)的東西,則首先要先去看一下這幾個(gè)組件(這里花了很多時(shí)間毕荐,看文檔看的想哭)束析,然后Wekan的UI是用Jade和Stylus寫的,第一次接觸憎亚,這酸爽你懂的员寇。幸好網(wǎng)上資料挺多,用習(xí)慣了之后覺得這兩個(gè)東西真的不是一般的好第美,強(qiáng)大簡(jiǎn)介蝶锋,關(guān)鍵是可以裝逼。
關(guān)于JS
隨著最近幾年node商用的越來(lái)越多什往,JS也已經(jīng)成為成本最低的全棧開發(fā)語(yǔ)言扳缕,而且ES6出來(lái)之后,感覺JS其語(yǔ)言本身已經(jīng)可以和任何一門其他語(yǔ)言進(jìn)行媲美了别威,純個(gè)人觀點(diǎn)躯舔。
關(guān)于縮進(jìn)
在開始大量寫JS之前,也寫過一段時(shí)間底層的c語(yǔ)言省古,記憶中一個(gè)Tab代表4個(gè)空格粥庄,兩個(gè)基本等價(jià)。渾然不知豺妓,Tab和空格的爭(zhēng)論竟然這么激烈惜互。
一直習(xí)慣寫Tab布讹,在提交項(xiàng)目時(shí),想起來(lái)run一下eslint吧训堆,結(jié)果一大堆的錯(cuò)誤描验。對(duì)于開源項(xiàng)目來(lái)說,代碼樣式的一致性很重要坑鱼,這里還是乖乖地全部改掉了膘流。
Meteor建議開發(fā)者遵循Airbnb style guide ,仔細(xì)去翻了翻姑躲,一些要求其實(shí)是為了提高性能睡扬,比如const的大量使用,關(guān)鍵是可讀性的提高會(huì)直接帶來(lái)代碼可維護(hù)性的提高黍析。
Wekan的eslint都配置好了卖怜,如果懶得配置編輯器的eslint插件,只需要執(zhí)行meteor npm run lint
阐枣,如果結(jié)果如下马靠,則可以放心提交了。
lkMacBook-Pro:wekan lk$ meteor npm run lint
> wekan@0.11.1-rc1 lint ~/github/wekan
> eslint .
lkMacBook-Pro:wekan lk$
后續(xù)
這里并沒有多高深的技術(shù)討論蔼两,關(guān)于Meteor的底層實(shí)現(xiàn)——如DDP的實(shí)現(xiàn)——也并沒有作很深的探究甩鳄,但是做了這個(gè)項(xiàng)目后拓寬了一些視野,了解了node作為一個(gè)新興崛起的技術(shù)的大概和發(fā)展現(xiàn)狀额划。同時(shí)出于對(duì)WebSocket的好奇也對(duì)它做了一些小小的研究妙啃,有興趣可以看一看:刨根問底HTTP和WebSocket協(xié)議。
對(duì)于第二個(gè)需求俊戳,有了第一個(gè)的知識(shí)基礎(chǔ)揖赴,開發(fā)起來(lái)流暢了很多,很快就做出來(lái)了抑胎。