摘要:滬江網(wǎng)校現(xiàn)在的架構(gòu)是怎么樣的基于以上原則,在搭建架構(gòu)的時(shí)候,經(jīng)過討論和嘗試,我們最終確定出個(gè)方向,模塊化,組件化,工程化,規(guī)范化。
正文如下 沒有統(tǒng)一架構(gòu)的時(shí)候是怎樣的一種情況?作者: 未來
本文轉(zhuǎn)自互聯(lián)網(wǎng)技術(shù)聯(lián)盟(ITA1024)技術(shù)分享實(shí)錄
起初前端是沒有架構(gòu)的,大家只是在完成一個(gè)一個(gè)的頁面。我們來看看會(huì)發(fā)生什么。
A同事是一個(gè)非常有意思的人,他喜歡把跟這個(gè)頁面相關(guān)的所有的JS都寫在同一個(gè)文件里面。嗯,傳說中2000行代碼的JS文件就是這么出來的。
B同事是一個(gè)對(duì)技術(shù)比較有追求的人。他覺得模塊化不錯(cuò),所以他在自己做的頁面里選用了requireJS。看上去不錯(cuò)哦,巧的是C同事也是一個(gè)對(duì)技術(shù)有追求的人,但是他不喜歡AMD的規(guī)范,所以他支持國貨seaJS,哦,他還在里面使用了他喜歡的模版引擎Jade。
嗯,同一個(gè)網(wǎng)站,每個(gè)頁面的技術(shù)選擇完全不一樣的。別忘了,網(wǎng)站是需要維護(hù)的,修Bug阿,改需求啊。有一天B同事跑去負(fù)責(zé)C同事做的那個(gè)頁面的需求改動(dòng),當(dāng)他看到那些他不熟悉的技術(shù)時(shí),內(nèi)心是極度崩潰的。
D同事玩的就比較高級(jí)了,他喜歡寫es6,也用sass。這就要求無論在開發(fā)的時(shí)候還是發(fā)布的時(shí)候代碼都要先編譯,而且顯然你是不可能每次都是手動(dòng)去做這個(gè)事情的。這就是他對(duì)工程化有需求了。
這個(gè)時(shí)候他很可能選擇放棄,或者妥協(xié)(只使用少部分構(gòu)建工具很好支持的功能),畢竟要實(shí)現(xiàn)一套完整的工程化是很花時(shí)間的事情(即使只是支持他自己的頁面),而程序員的時(shí)間往往會(huì)被業(yè)務(wù)需求所淹沒。畢竟以單個(gè)人和單個(gè)頁面的單位來看,工程化這個(gè)東西是得不償失的,如果以團(tuán)隊(duì)和整個(gè)系統(tǒng)去看那就不一樣了。
其實(shí)到這里就可以看出來,個(gè)人所使用的技術(shù)的天花板往往會(huì)被整個(gè)團(tuán)隊(duì)的現(xiàn)狀所制約。
架構(gòu)是不是必須的?上面描述的是沒有架構(gòu)的時(shí)候發(fā)生的情況,這些情況看上去當(dāng)然都不太好,但是如果跳出前端這個(gè)角色,我們?cè)趺慈ッ枋稣f這些問題會(huì)造成的影響,反過來的意思就是,如果有一個(gè)統(tǒng)一架構(gòu)能夠帶來的好處。
回答出這個(gè)問題,可以解決兩方面的困擾。
第一是說服大團(tuán)隊(duì)里的其它角色前端架構(gòu)這件事情的重要性(在現(xiàn)在的大環(huán)境下,這個(gè)其實(shí)很重要);
第二是自己要時(shí)刻記住架構(gòu)的目的,能夠不忘初心,不沉迷于形式和概念。
現(xiàn)在回過頭來看看,
架構(gòu)的目的是什么?答案是提升質(zhì)量和效率。
沒有架構(gòu)的情況下,新技術(shù)無法得到引入,技術(shù)無法統(tǒng)一,使得團(tuán)隊(duì)的整體技術(shù)能力無法得到提升,也無法提供技術(shù)上的通用解決方案,從團(tuán)隊(duì)的角度來考量的話,效率是非常低下的。
同時(shí),因?yàn)榧夹g(shù)過于陳舊,再加上代碼沒有統(tǒng)一規(guī)范,導(dǎo)致碰到頁面業(yè)務(wù)邏輯比較復(fù)雜,或者對(duì)老頁面進(jìn)行維護(hù)的時(shí)候,產(chǎn)生Bug的概率非常高,產(chǎn)品質(zhì)量堪憂。
架構(gòu)應(yīng)該怎么玩?上面講到,架構(gòu)的目的是提升質(zhì)量和效率。那我們看看架構(gòu)應(yīng)該做到哪些方面才能實(shí)現(xiàn)這個(gè)目的。
架構(gòu)是一個(gè)抽象的過程,它是架構(gòu)師根據(jù)自己的經(jīng)驗(yàn)對(duì)大量具體的業(yè)務(wù)項(xiàng)目進(jìn)行分析,發(fā)現(xiàn)其中的規(guī)律,抽象出具體的規(guī)范,最終又應(yīng)用于具體的業(yè)務(wù)項(xiàng)目中去。比如常說的MVVM就是一種規(guī)范。
要把跟業(yè)務(wù)無關(guān)的問題都在架構(gòu)層面處理掉。比如代碼壓縮,打包這種工程化的問題都要在架構(gòu)層面統(tǒng)一解決的。要做到業(yè)務(wù)的歸業(yè)務(wù),架構(gòu)的歸架構(gòu)。
架構(gòu)要考慮到可以方便團(tuán)隊(duì)成員提供和使用通用技術(shù)解決方案。比如分頁組件這種。
架構(gòu)設(shè)計(jì)的時(shí)候要綜合考慮當(dāng)前的主流技術(shù)跟自己業(yè)務(wù)系統(tǒng)的實(shí)際情況。因?yàn)榍岸苏幵诟咚侔l(fā)展,各種新技術(shù),工具,插件,框架層出不窮,這個(gè)時(shí)候要特別謹(jǐn)慎,有時(shí)候一個(gè)坑跳下去,就呵呵了。
滬江網(wǎng)?,F(xiàn)在的架構(gòu)是怎么樣的?基于以上原則,在搭建架構(gòu)的時(shí)候,經(jīng)過討論和嘗試,我們最終確定出4個(gè)方向,模塊化,組件化,工程化,規(guī)范化。(你也看出來了,大方向是跟主流走的,太陽底下沒有新鮮事啊。)
說了這么多虛的^_^,下面來點(diǎn)干貨。
第一點(diǎn)-工程化:構(gòu)建工具用的是webpack,發(fā)布系統(tǒng)用的是jekins。
構(gòu)建這里是分開發(fā)環(huán)境和生產(chǎn)環(huán)境。開發(fā)環(huán)境需要提供jsmap, css map,livereload等開發(fā)時(shí)候需要的功能,而生產(chǎn)環(huán)境需要壓縮,打包,靜態(tài)資源文件名添加hash等功能的。這里插一句,如果要啟動(dòng)開發(fā)環(huán)境,只需要 npm start。
第二點(diǎn)-模塊化:現(xiàn)在都是commonJS當(dāng)?shù)懒?,所以選擇es6+ babel。這里順便提下我們使用的框架,PC端knockout(為了支持IE7), 觸屏端和hybrid端redux+react。
第三點(diǎn)-組件化:這一塊我們是做的挺徹底的,也思考了很多。
我們的頁面是由一顆組件樹組成的??聪聢D,invitationActivity代表了一個(gè)頁面,components下面的每一個(gè)文件夾都代表一個(gè)組件。每個(gè)組件包含自己需要的js,css,image等資源。
保證組件的封閉性。因?yàn)镴S方面是模塊化的,在css方面我們也引入了cssmodule來做到這點(diǎn)。
組件的功能界限問題。也就是什么是應(yīng)該在組件內(nèi)部實(shí)現(xiàn),什么是應(yīng)該由組件的調(diào)用者來實(shí)現(xiàn)的??聪聢D,下面這個(gè)界面會(huì)封裝成一個(gè)業(yè)務(wù)組件,因?yàn)楹芏囗撁嫔隙紩?huì)有這個(gè)組件,所以在我們的系統(tǒng)里面,它是被當(dāng)作一個(gè)公用組件的。順便提下,這個(gè)組件本身是由多個(gè)子組件組成的。
現(xiàn)在有兩個(gè)問題需要考慮下:為了顯示熱門詞匯有哪些熱詞,需要調(diào)接口從后臺(tái)獲取。那在哪里去調(diào)用接口呢,是組件本身去調(diào)用,還是由使用者傳進(jìn)來。
現(xiàn)在點(diǎn)擊搜索按鈕,需要跳轉(zhuǎn)到搜索結(jié)果頁(還有可能要打點(diǎn))。那完成這些操作的代碼寫在哪里呢?是直接寫在組件里面還是由調(diào)用者傳入,由組件在相應(yīng)的時(shí)機(jī)調(diào)用傳入的函數(shù)。
這就是組件的功能界限問題。我們的做法是組件只負(fù)責(zé)跟UI顯示相關(guān)的部分,所有業(yè)務(wù)邏輯都不屬于組件本身的功能。
根據(jù)這個(gè)原則,我們來回答上面的問題。
組件只負(fù)責(zé)顯示熱詞,至于具體有哪些熱詞,由它的調(diào)用者傳入。
組件只知道搜索按鈕被點(diǎn)擊了,至于按鈕被點(diǎn)擊具體要做些什么,它是不知道的,它能做的就是調(diào)用傳給它的回調(diào)函數(shù)。
備注:關(guān)于組件的功能界限問題我們也思考了很長時(shí)間,并且做過不同的嘗試。比如把 點(diǎn)擊搜索按鈕要做的事情放在組件里面自己做怎么樣呢,后來發(fā)現(xiàn)不同的頁面上點(diǎn)擊搜索按鈕需要打點(diǎn)的關(guān)鍵字是不一樣的,這時(shí)候你如果把組件寫死了就沒法重用 這個(gè)組件了。其中關(guān)于接口調(diào)用是不是要寫在組件內(nèi)部的問題更是一度相持不下,似乎兩邊都有點(diǎn)道理。后來碰到一個(gè)真實(shí)的事情就是因?yàn)榻涌谡{(diào)用都寫在組件里 面,導(dǎo)致同一個(gè)接口在某個(gè)頁面上被調(diào)用了兩次。當(dāng)這件事情發(fā)生之后,天平似乎往另外一邊傾斜了點(diǎn)。
一般組件化開發(fā)之后,我們會(huì)碰到兩個(gè)方面的問題。
第一個(gè)問題是我們?nèi)タ磩e人的代碼的時(shí)候,沒辦法方便的知道這個(gè)頁面的組件樹是怎么組成的,以及每個(gè)組件需要哪些數(shù)據(jù)。
第二個(gè)問題是當(dāng)組件樹的層次很深的時(shí)候,父子組件間參數(shù)的傳遞會(huì)非常繁瑣。而且一旦需要增加或刪減掉某個(gè)參數(shù)的時(shí)候,整個(gè)父組件到根組件路徑上所有組件參數(shù)的傳遞都要修改。
關(guān)于第二個(gè)問題,也就是父子組件之間參數(shù)傳遞的問題,我舉個(gè)例子來詳細(xì)說明。假設(shè)現(xiàn)在組件樹的結(jié)構(gòu)是這樣的。
A組件所有子組件加起來需要的參數(shù)是9個(gè),那么調(diào)用A組件的寫法是
然后在A組件內(nèi)部,A組件本身只需要參數(shù)a1,其它的八個(gè)參數(shù)是被它的子組件B1,B2消費(fèi)的。那么A組件內(nèi)部的寫法大概是這樣的。
,
B1組件本身不需要參數(shù),四個(gè)參數(shù)都是被子組件C1,C2消費(fèi)。那么B1組件內(nèi)部的寫法大概是這樣的。
,
這個(gè)時(shí)候已經(jīng)可以看出來,如果C1需要增加或者刪減一個(gè)參數(shù),從組件本身C1到根組件A之間的所有組件都需要改動(dòng)。想象一下當(dāng)組件樹的橫向和縱向的層次都變的非常深的時(shí)候,這個(gè)時(shí)候每個(gè)組件的參數(shù)傳遞都會(huì)變的非常龐大而且混亂。
如果要把一個(gè)組件的位置換一下的話,要改變的地方之多,也是讓人非常頭疼的。我們想了一個(gè)方案來同時(shí)解決這兩個(gè)問題,看下圖,
我們每個(gè)頁面都有一個(gè)param.js文件,可以看到從param.js里面可以清晰的看到當(dāng)前這顆組件樹的結(jié)構(gòu),以及每個(gè)組件自己需要的參數(shù)。而在組件內(nèi)部,寫法也相當(dāng)簡(jiǎn)單,以A組件內(nèi)部為例,組件內(nèi)部的寫法是這樣的,
,
可以看到,這樣的話,無論是增減參數(shù)還是移動(dòng)某個(gè)組件,都會(huì)變的非常簡(jiǎn)單。
由于我們對(duì)組件功能界限的定義是只負(fù)責(zé)UI相關(guān)的功能,所有的業(yè)務(wù)邏輯都是從調(diào)用者傳遞過的。也即是寫在param.js。所以param.js文件是非常重要的一個(gè)文件,里面基本包涵了這個(gè)頁面所有業(yè)務(wù)處理邏輯。
很顯然,隨著頁面業(yè)務(wù)邏輯變的復(fù)雜,param.js將會(huì)變得越來越大。沒關(guān)系,把不同的組件參數(shù)分拆到不同的js文件里面去實(shí)現(xiàn),然后建個(gè)params文件夾把它們組織起來。
第四點(diǎn)-規(guī)范化:JS語法檢查選用了eslint。
項(xiàng)目目錄結(jié)構(gòu)非常清晰。當(dāng)進(jìn)行開發(fā)的時(shí)候,哪些代碼應(yīng)該放到哪里都進(jìn)行了明確的規(guī)定,并且每個(gè)文件的功能都盡量清晰并且單一。
頂層目錄結(jié)構(gòu)如下圖:
src文件夾存放的是所有的的源代碼和其他靜態(tài)資源(比如圖片,iconfont)。
dist文件夾存放的是所有編譯后的代碼。
build文件夾存放的是所有工程化所需要的代碼。
document文件夾當(dāng)然存放的文檔。
下面重點(diǎn)看下src目錄結(jié)構(gòu),如下圖:
app文件夾里的每一個(gè)子文件夾代表了一個(gè)頁面,每個(gè)頁面所用到的所有靜態(tài)資源都存放在這個(gè)子文件下面(除了引用的公共資源以外),構(gòu)建的時(shí)候,每個(gè)子文件夾會(huì)生成自己的靜態(tài)資源供頁面引用。
common文件夾里面的所有代碼在構(gòu)建的時(shí)候會(huì)多帶帶生成js文件和css文件供頁面引用。所以一個(gè)頁面會(huì)引用兩個(gè)js和兩個(gè)css.里面存放的是每個(gè)頁面都會(huì)用到的一些共用資源。比如觸屏端使用了react,那么跟react相關(guān)的那些包就會(huì)放在common里面。
components文件夾里面存放的是共用組件,每一個(gè)子文件夾代表了一個(gè)組件。有可能是通用的功能組件,比如分頁組件,Loading組件,ModalDialog組件。也有可能是一個(gè)通用的業(yè)務(wù)組件,比如站點(diǎn)通用頭部,通用footer,通用分享組件。注意,在其他地方引用這些組件時(shí),是不需要寫相對(duì)路徑的,直接寫組件名字就可以了,比如import pager from ‘pager’。這樣對(duì)使用者更方便。
lib文件夾存放的是通用的js類庫。比如檢測(cè)瀏覽器用的browserDetect.js,處理日期用的dateUtil.js。同樣的,在其他地方需要引入這些JS時(shí),也不需要寫相對(duì)路徑,直接寫JS的名字就可以了。比如import{isIE} from ‘browserDetect’。
style文件夾里面存放的一些公用的sass資源。比如function,mixing, variable。其他的sass文件需要引入這些資源的時(shí)候,使用方式跟使用通用js一樣,直接@import “base.scss"即可。
寫在最后滬江網(wǎng)校的架構(gòu)才剛剛有個(gè)雛形,后面還有更多的功能會(huì)加進(jìn)來,比如腳手架(等到架構(gòu)更成熟的時(shí)候在出一套完整的),NodeJS中間層(在大方向上已經(jīng)達(dá)成統(tǒng)一),前端監(jiān)控系統(tǒng)等。
架構(gòu)是個(gè)不斷完善的過程,而把架構(gòu)尤其是跟規(guī)范相關(guān)的部分落實(shí)到具體業(yè)務(wù)系統(tǒng)里面更是個(gè)團(tuán)隊(duì)不斷磨合的過程。它最終考驗(yàn)的,同時(shí)也是最終磨合出來的是團(tuán)隊(duì)的成熟度。
謝謝大家。
iKcamp原創(chuàng)新書《移動(dòng)Web前端高效開發(fā)實(shí)戰(zhàn)》已在亞馬遜、京東、當(dāng)當(dāng)開售。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/85160.html
摘要:招聘高級(jí)計(jì)算機(jī)相關(guān)專業(yè)優(yōu)先,年以上工作經(jīng)驗(yàn)優(yōu)先,年以上互聯(lián)網(wǎng)產(chǎn)品開發(fā)經(jīng)驗(yàn)精通等網(wǎng)絡(luò)協(xié)議瀏覽器渲染原理前端性能優(yōu)化前端安全策略多端開發(fā)熟悉,熟練使用任意一種構(gòu)建工具具備框架開發(fā)經(jīng)驗(yàn),如了解最佳實(shí)踐,追求高效率把遇到的問題當(dāng)作學(xué)習(xí)機(jī)會(huì),打破沙 showImg(https://segmentfault.com/img/bVbq5tQ?w=1080&h=3812); 招聘高級(jí)FE 1、計(jì)算機(jī)...
摘要:招聘高級(jí)計(jì)算機(jī)相關(guān)專業(yè)優(yōu)先,年以上工作經(jīng)驗(yàn)優(yōu)先,年以上互聯(lián)網(wǎng)產(chǎn)品開發(fā)經(jīng)驗(yàn)精通等網(wǎng)絡(luò)協(xié)議瀏覽器渲染原理前端性能優(yōu)化前端安全策略多端開發(fā)熟悉,熟練使用任意一種構(gòu)建工具具備框架開發(fā)經(jīng)驗(yàn),如了解最佳實(shí)踐,追求高效率把遇到的問題當(dāng)作學(xué)習(xí)機(jī)會(huì),打破沙 showImg(https://segmentfault.com/img/bVbq5tQ?w=1080&h=3812); 招聘高級(jí)FE 1、計(jì)算機(jī)...
摘要:月號(hào)哈志輝前端工程化滬江實(shí)踐哈志輝滬江前端架構(gòu)師,移動(dòng)前端高效開發(fā)實(shí)戰(zhàn)作者之一在線地址月號(hào)陳達(dá)孚實(shí)現(xiàn)漸進(jìn)式應(yīng)用陳達(dá)孚香港中文大學(xué)計(jì)算機(jī)碩士,移動(dòng)前端高效開發(fā)實(shí)戰(zhàn)作者之一,前端開發(fā)者指南譯者之一,中國前端開發(fā)者大會(huì)中生代技術(shù)大會(huì)榮譽(yù)講師,滬江 12月2號(hào)-哈志輝-前端工程化滬江CCtalk實(shí)踐 哈志輝:滬江CCtalk前端架構(gòu)師,《移動(dòng)Web前端高效開發(fā)實(shí)戰(zhàn)》作者之一 在線地址:htt...
摘要:期待大家提供高見建設(shè)我們的服務(wù)之路參考服務(wù)之路漫談一服務(wù)之路漫談二網(wǎng)易云計(jì)算基礎(chǔ)服務(wù)深度整合了及容器技術(shù),提供彈性計(jì)算工具鏈及微服務(wù)基礎(chǔ)設(shè)施等服務(wù),幫助企業(yè)解決架構(gòu)及運(yùn)維等問題,使企業(yè)更聚焦于業(yè)務(wù),是新一代的云計(jì)算平臺(tái),點(diǎn)擊可免費(fèi)試用。 此文已由作者堯飄海授權(quán)網(wǎng)易云社區(qū)發(fā)布。 歡迎訪問網(wǎng)易云社區(qū),了解更多網(wǎng)易技術(shù)產(chǎn)品運(yùn)營經(jīng)驗(yàn)。 Monolithic架構(gòu)在產(chǎn)品訪問量很大的情況下,有可能常...
閱讀 2576·2023-04-25 19:47
閱讀 3418·2019-08-29 17:18
閱讀 875·2019-08-29 15:26
閱讀 3385·2019-08-29 14:17
閱讀 1197·2019-08-26 13:49
閱讀 3362·2019-08-26 13:22
閱讀 3051·2019-08-26 10:44
閱讀 2722·2019-08-23 16:51