0.引言css
做爲互聯網項目,最重要的即是用戶體驗。在舉國「互聯網+」的熱潮中,用戶至上也已經被大多數企業所接收,特別是在現在移動端快速發展的時代,咱們的網頁不只只是呈如今用戶的PC瀏覽器裏,更多的時候,用戶是經過移動產品瀏覽咱們的網頁。加之有愈來愈多的開發者投入到Web APP和Hybrid APP的開發隊伍中,性能這一問題又再一次被提上了程序員們重點關注的要素。我曾經看到過這樣一句話:一個網站的體驗,決定了用戶是否願意去了解網站的功能;而網站的功能,決定了用戶是否會一票否決網站的體驗。這是改版自網絡上的一句流行語,但卻把網站性能這件事說的十分透徹,特別是在網站這樣的項目中,若是一個用戶須要超過5s才能看見頁面,他會絕不猶豫地關閉它。性能優化,做爲工程師界的「上乘武功」,是咱們在開發中老生常談的話題,也是一名開發者從入門向資深進階的必經階段,雖然咱們看到過不少的標準、軍規,但在真正實踐中,卻經常力不從心,不知道落下了什麼,不知道性能是否還有進一步優化的空間。前端
對於網站的性能,在行業內有不少既定的指標,但就之前端er而言,咱們應該更加關注如下指標:白屏時間、首屏時間、整頁時間、DNS時間、CPU佔用率。而我以前本身搭建的一個網站(網址:jerryonlyzrj.com/resume/ ,近日因域名備案沒法打開,幾往後即恢復正常),徹底沒作性能優化時,首屏時間是12.67s,最後通過多方面優化,終於將其下降至1.06s,而且還未配置CDN加速。其中過程我踩了不少坑,也翻了許多專業書籍,最後決定將這幾日的努力整理成文,幫助前端愛好者們少走彎路。文章更新可能以後不會實時同步在論壇上,歡迎你們關注個人Github,我會把最新的文章更新在對應的項目裏,讓咱們一塊兒在代碼的海洋裏策馬奔騰:github.com/jerryOnlyZR… 。node
今天,咱們將從性能優化的三大方面工做逐步展開介紹,其中包括網絡傳輸性能、頁面渲染性能以及JS阻塞性能,系統性地帶着讀者們體驗性能優化的實踐流程。webpack
1.網絡傳輸性能優化nginx
在開始介紹網絡傳輸性能優化這項工做以前,咱們須要瞭解瀏覽器處理用戶請求的過程,那麼就必須奉上這幅神圖了:git
這是navigation timing監測指標圖,從圖中咱們能夠看出,瀏覽器在獲得用戶請求以後,經歷了下面這些階段:重定向→拉取緩存→DNS查詢→創建TCP連接→發起請求→接收響應→處理HTML元素→元素加載完成。不着急,咱們對其中的細節一步步展開討論:程序員
1.1.瀏覽器緩存github
咱們都知道,瀏覽器在向服務器發起請求前,會先查詢本地是否有相同的文件,若是有,就會直接拉取本地緩存,這和咱們在後臺部屬的Redis和Memcache相似,都是起到了中間緩衝的做用,咱們先看看瀏覽器處理緩存的策略:web
由於網上的圖片太籠統了,並且我翻過不少講緩存的文章,不多有將狀態碼還有何時將緩存存放在內存(memory)中何時緩存在硬盤中(disk)系統地整理出來,因此我本身繪製了一張瀏覽器緩存機制流程圖,結合這張圖再更深刻地說明瀏覽器的緩存機制。chrome
這裏咱們可使用chrome devtools裏的network面板查看網絡傳輸的相關信息:
(這裏須要特別注意,在咱們進行緩存調試時,須要去除network面板頂部的Disable cache 勾選項,不然瀏覽器將始終不會從緩存中拉取數據)
瀏覽器默認的緩存是放在內存內的,但咱們知道,內存裏的緩存會由於進程的結束或者說瀏覽器的關閉而被清除,而存在硬盤裏的緩存纔可以被長期保留下去。不少時候,咱們在network面板中各請求的size項裏,會看到兩種不一樣的狀態:from memory cache 和 from disk cache,前者指緩存來自內存,後者指緩存來自硬盤。而控制緩存存放位置的,不是別人,就是咱們在服務器上設置的Etag字段。在瀏覽器接收到服務器響應後,會檢測響應頭部(Header),若是有Etag字段,那麼瀏覽器就會將本次緩存寫入硬盤中。
之因此拉取緩存會出現200、304兩種不一樣的狀態碼,取決於瀏覽器是否有向服務器發起驗證請求。只有向服務器發起驗證請求並確認緩存未被更新,纔會返回304狀態碼。
這裏我以nginx爲例,談談如何配置緩存:
首先,咱們先進入nginx的配置文檔
$ vim nginxPath/conf/nginx.conf
在配置文檔內插入以下兩項:
打開咱們的網站,在chrome devtools的network面板中觀察咱們的請求資源,若是在響應頭部看見Etag和Expires字段,就說明咱們的緩存配置成功了。
【!!!特別注意!!!】 在咱們配置緩存時必定要切記,瀏覽器在處理用戶請求時,若是命中強緩存,瀏覽器會直接拉取本地緩存,不會與服務器發生任何通訊,也就是說,若是咱們在服務器端更新了文件,並不會被瀏覽器得知,就沒法替換失效的緩存。因此咱們在構建階段,須要爲咱們的靜態資源添加md5 hash後綴,避免資源更新而引發的先後端文件沒法同步的問題。
1.2.資源打包壓縮
咱們以前所做的瀏覽器緩存工做,只有在用戶第二次訪問咱們的頁面才能起到效果,若是要在用戶首次打開頁面就實現優良的性能,必須對資源進行優化。咱們常將網絡性能優化措施歸結爲三大方面:減小請求數、減少請求資源體積、提高網絡傳輸速率。如今,讓咱們逐個擊破:
結合前端工程化思想,咱們在對上線文件進行自動化打包編譯時,一般都須要打包工具的協助,這裏我推薦webpack,我一般都使用Gulp和Grunt來編譯node,Parcel太新,並且webpack也一直在自身的特性上向Parcel靠攏。
在對webpack進行上線配置時,咱們要特別注意如下幾點:
①JS壓縮:(這點應該算是耳熟能詳了,就很少介紹了)
②HTML壓縮:
④提取css並壓縮:
在使用webpack的過程當中,咱們一般會以模塊的形式引入css文件(webpack的思想不就是萬物皆模塊嘛),可是在上線的時候,咱們還須要將這些css提取出來,而且壓縮,這些看似複雜的過程只須要簡單的幾行配置就行:
(PS:咱們須要用到mini-css-extract-plugin ,因此還得你們自行npm install)
若是你能按照上述六點將webpack上線配置完整配置出來,基本能將文件資源體積壓縮到極致了,若有疏漏,還但願你們能加以補充。
最後,咱們還應該在服務器上開啓Gzip傳輸壓縮,它能將咱們的文本類文件體積壓縮至原先的四分之一,效果立竿見影,仍是切換到咱們的nginx配置文檔,添加以下兩項配置項目:
【!!!特別注意!!!】 不要對圖片文件進行Gzip壓縮!不要對圖片文件進行Gzip壓縮!不要對圖片文件進行Gzip壓縮!我只會告訴你效果拔苗助長,至於具體緣由,還得考慮服務器壓縮過程當中的CPU佔用還有壓縮率等指標,對圖片進行壓縮不但會佔用後臺大量資源,壓縮效果其實並不可觀,能夠說是「弊大於利」,因此請在gzip_types 把圖片的相關項去掉。針對圖片的相關處理,咱們接下來會更加具體地介紹。
1.3.圖片資源優化
剛剛咱們介紹了資源打包壓縮,只是停留在了代碼層面,而在咱們實際開發中,真正佔用了大量網絡傳輸資源的,並非這些文件,而是圖片,若是你對圖片進行了優化工做,你能馬上看見明顯的效果。
1.3.1.不要在HTML裏縮放圖像
不少開發者可能會有這樣的錯覺(其實我曾經也是這樣),咱們會爲了方便在一個200✖200的圖片容器內直接使用一張400✖400的圖片,咱們甚至認爲這樣能讓用戶以爲圖片更加清晰,其實否則,在普通的顯示器上,用戶並不會感到縮放後的大圖更加清晰,但這一切卻致使網頁加速速度降低,同時照成帶寬浪費,你可能不知道,一張200KB的圖片和2M的圖片的傳輸時間會是200m和12s的差距(親身經歷,深受其害(┬_┬))。因此,當你須要用多大的圖片時,就在服務器上準備好多大的圖片,儘可能固定圖片尺寸。
1.3.2.使用雪碧圖(CSS Sprite)
雪碧圖的概念你們必定在生活中常常聽見,其實雪碧圖是減少請求數的顯著運用。並且很奇妙的是,多張圖片聘在一塊後,整體積會比以前全部圖片的體積之和小(你能夠親自試試)。這裏給你們推薦一個自動化生成雪碧圖的工具:https://www.toptal.com/developers/css/sprite-generator (圖片來自官網首頁)
只要你添加相關資源文件,他就會自動幫你生成雪碧圖以及對應的CSS樣式。
其實咱們在工程中還有更爲自動的方法,即是一款雪碧圖生成插件webpack-spritesmith。首先,先簡單介紹一下使用插件生成雪碧圖的思路:
首先,咱們會把咱們所須要的小圖標放置在一個文件夾內以便於管理:
(這裏的@2x圖片是爲了適配視網膜二倍屏的圖片資源,webpack-spritesmith內有專門爲適配多倍屏提供的配置項,稍候將會講到)
而後,咱們須要插件去讀取這個文件夾內的全部圖片資源文件,以文件夾名稱爲圖片名稱生成一張雪碧圖到指定位置,而且輸出可以正確使用這些雪碧圖的CSS文件。
現在,webpack-spritesmith這款插件能實現咱們想要的一切,先奉上配置內容:具體可參照webpack-spritesmith官方文檔
執行webpack以後,就會在開發目錄裏生成上面兩張圖的結果,咱們能夠看看common.css裏面的內容:
咱們能夠看到,全部咱們以前放在common文件夾裏的圖片資源都自動地生成了相應的樣式,這些都不須要咱們手動處理,``webpack-spritesmith`這款插件就已經幫咱們完成了!
1.3.3.使用字體圖標(iconfont)
不管是壓縮後的圖片,仍是雪碧圖,終歸仍是圖片,只要是圖片,就仍是會佔用大量網絡傳輸資源。可是字體圖標的出現,卻讓前端開發者看到了另一個神奇的世界。
我最喜歡用的是阿里矢量圖標庫(網址:www.iconfont.cn/),裏面有大量的矢量圖…
圖片能作的不少事情,矢量圖都能做,並且它只是往HTML裏插入字符和CSS樣式而已,和圖片請求比起來資源佔用徹底不在一個數量級,若是你的項目裏有小圖標,就是用矢量圖吧。
但若是咱們作的是公司或者團隊的項目,須要使用到許多自定義的字體圖標,可愛的設計小姐姐們只是丟給你了幾份.svg圖片,你又該如何去作呢?
其實也很簡單,阿里矢量圖標庫就提供了上傳本地SVG資源的功能,這裏另外推薦一個網站——icomoon。icomoon這個網站也爲咱們提供了將SVG圖片自動轉化成CSS樣式的功能。(圖片來自icomoon首頁)
咱們能夠點擊Import Icons按鈕導入咱們本地的SVG資源,而後選中他們,接下來生成CSS的事情,就交給icomoon吧,具體的操做,就和阿里矢量圖標庫類同了。
1.3.4.使用WebP
WebP格式,是谷歌公司開發的一種旨在加快圖片加載速度的圖片格式。圖片壓縮體積大約只有JPEG的2/3,並能節省大量的服務器帶寬資源和數據空間。Facebook、Ebay等知名網站已經開始測試並使用WebP格式。
咱們可使用官網提供的Linux命令行工具對項目中的圖片進行WebP編碼,也可使用咱們的線上服務,這裏我推薦叉拍雲(網址:www.upyun.com/webp)。可是在實際…
1.4.網絡傳輸性能檢測工具——Page Speed
除了network版塊,其實chrome還爲咱們準備好了一款監測網絡傳輸性能的插件——Page Speed,我們的文章封面,就是用的Page Speed的官方宣傳圖(由於我以爲這張圖再合適不過了)。咱們只須要經過下面步驟安裝,就能夠在chrome devtools裏找到它了:chrome菜單→更多工具→拓展程序→chrome網上應用商店→搜索pagespeed後安轉便可。
(PS:使用chrome應用商店須要***,怎麼***我就不便多說了)
這就是Page Speed的功能界面:
咱們只須要打開待測試的網頁,而後點擊Page Speed裏的 Start analyzing按鈕,它就會自動幫咱們測試網絡傳輸性能了,這是個人網站測試結果:
Page Speed最人性化的地方,即是它會對測試網站的性能瓶頸提出完整的建議,咱們能夠根據它的提示進行優化工做。這裏個人網站已經優化到最好指標了(•́⌄•́๑)૭✧,Page Speed Score表示你的性能測試得分,100/100表示已經沒有須要優化的地方。
優化完畢後再使用chorme devtools的network版塊測量一下咱們網頁的白屏時間還有首屏時間,是否是獲得了很大的提高?
1.5.使用CDN
Last but not least,
再好的性能優化實例,也必須在CDN的支撐下才能到達極致。
若是咱們在Linux下使用命令$ traceroute targetIp 或者在Windows下使用批處理 > tracert targetIp,均可以定位用戶與目標計算機之間通過的全部路由器,不言而喻,用戶和服務器之間距離越遠,通過的路由器越多,延遲也就越高。使用CDN的目的之一即是解決這一問題,固然不只僅如此,CDN還能夠分擔IDC壓力。
固然,憑着咱們單我的的資金實力(除非你是王思聰)是一定搭建不起來CDN的,不過咱們可使用各大企業提供的服務,諸如騰訊雲等,配置也十分簡單,這裏就請你們自行去推敲啦。
2.頁面渲染性能優化
2.1.瀏覽器渲染過程(Webkit)
其實你們應該對瀏覽器將的HTML渲染機制比較熟悉了,基本流程同上圖所述,你們在入門的時候,你的導師或者前輩可能會告訴你,在渲染方面咱們要減小重排和重繪,由於他們會影響瀏覽器性能。不過你必定不知道其中原理是什麼,對吧。今天咱們就結合《Webkit技術內幕》(這本書我仍是很推薦你們買來看看,好歹做爲一名前端工程師,你得知道咱們每天接觸的瀏覽器內核是怎樣工做的)的相關知識,給你們普及普及那些深層次的概念。
PS:這裏提到了Webkit內核,我順帶提一下瀏覽器內部的渲染引擎、解釋器等組件的關係,由於常常有師弟或者一些前端愛好者向我問這方面的知識,分不清他們的關係,我就拿一張圖來講明:(若是你對着不感興趣,能夠直接跳過)
瀏覽器的解釋器,是包括在渲染引擎內的,咱們常說的Chrome(如今使用的是Blink引擎)和Safari使用的Webkit引擎,Firefox使用的Gecko引擎,指的就是渲染引擎。而在渲染引擎內,還包括着咱們的HTML解釋器(渲染時用於構造DOM樹)、CSS解釋器(渲染時用於合成CSS規則)還有咱們的JS解釋器。
2.2.DOM渲染層與GPU硬件加速
若是我告訴你,一個頁面是有許多許多層級組成的,他們就像千層麪那樣,你能想象出這個頁面實際的樣子嗎?這裏爲了便於你們想象,我附上一張以前Firefox的3D View插件的頁面Layers層級圖:
對,你沒看錯,頁面的真實樣子就是這樣,是由多個DOM元素渲染層(Layers)組成的,實際上一個頁面在構建完render tree以後,是經歷了這樣的流程才最終呈如今咱們面前的:
①瀏覽器會先獲取DOM樹並依據樣式將其分割成多個獨立的渲染層
②CPU將每一個層繪製進繪圖中
③將位圖做爲紋理上傳至GPU(顯卡)繪製
④GPU將全部的渲染層緩存(若是下次上傳的渲染層沒有發生變化,GPU就不須要對其進行重繪)並複合多個渲染層最終造成咱們的圖像
從上面的步驟咱們能夠知道,佈局是由CPU處理的,而繪製則是由GPU完成的。
其實在chrome中,也爲咱們提供了相關插件供咱們查看頁面渲染層的分佈狀況,以及GPU的佔用率:(因此說,平時咱們得多去嘗試嘗試chrome的那些莫名其妙的插件,真的會發現好多東西都是神器)
chrome開發者工具菜單→more tools→Layers(開啓渲染層功能模塊)
chrome開發者工具菜單→more tools→rendering(開啓渲染性能監測工具)
執行上面的操做後,你會在瀏覽器裏看到這樣的效果:
太多東西了,分模塊講吧:
(一)最早是頁面右上方的小黑窗:其實提示已經說的很清楚了,它顯示的就是咱們的GPU佔用率,可以讓咱們清楚地知道頁面是否發生了大量的重繪。
(二)Layers版塊:這就是用於顯示咱們剛提到的DOM渲染層的工具了,左側的列表裏將會列出頁面裏存在哪些渲染層,還有這些渲染層的詳細信息。
(三)Rendering版塊:這個版塊和咱們的控制檯在同一個地方,你們可別找不到它。前三個勾選項是咱們最常使用的,讓我來給你們解釋一下他們的功能(充當一次免費翻譯)
①Paint flashing:勾選以後會對頁面中發生重繪的元素高亮顯示
②Layer borders:和咱們的Layer版塊功能相似,它會用高亮邊界突出咱們頁面中的各個渲染層
③FPS meter:就是開啓咱們在(一)中提到的小黑窗,用於觀察咱們的GPU佔用率
可能你們會問我,和我提到DOM渲染層這麼深的概念有什麼用啊,好像跟性能優化沒一點關係啊?你們應該還記得我剛說到GPU會對咱們的渲染層做緩存對吧,那麼你們試想一下,若是咱們把那些一直髮生大量重排重繪的元素提取出來,單獨觸發一個渲染層,那樣這個元素不就不會「連累」其餘元素一塊重繪了對吧。
那麼問題來了,什麼狀況下會觸發渲染層呢?你們只要記住:
video元素、WebGL、Canvas、CSS3 3D、CSS濾鏡、z-index大於某個相鄰節點的元素都會觸發新的Layer,其實咱們最經常使用的方法,就是給某個元素加上下面的樣式:
這樣就能夠觸發渲染層啦(__) 。
咱們把容易觸發重排重繪的元素單獨觸發渲染層,讓它與那些「靜態」元素隔離,讓GPU分擔更多的渲染工做,咱們一般把這樣的措施成爲硬件加速,或者是GPU加速。你們以前確定聽過這個說法,如今徹底清楚它的原理了吧。
2.3.重排與重繪
如今到咱們的重頭戲了,重排和重繪。先拋出概念:
①重排(reflow):渲染層內的元素佈局發生修改,都會致使頁面從新排列,好比窗口的尺寸發生變化、刪除或添加DOM元素,修改了影響元素盒子大小的CSS屬性(諸如:width、height、padding)。
②重繪(repaint):繪製,即渲染上色,全部對元素的視覺表現屬性的修改,都會引起重繪。
咱們習慣使用chrome devtools中的performance版塊來測量頁面重排重繪所佔據的時間:
①藍色部分:HTML解析和網絡通訊佔用的時間
②黃色部分:JavaScript語句執行所佔用時間
③紫色部分:重排佔用時間
④綠色部分:重繪佔用時間
不管是重排仍是重繪,都會阻塞瀏覽器。要提升網頁性能,就要下降重排和重繪的頻率和成本,儘量少地觸發從新渲染。正如咱們在2.3中提到的,重排是由CPU處理的,而重繪是由GPU處理的,CPU的處理效率遠不及GPU,而且重排必定會引起重繪,而重繪不必定會引起重排。因此在性能優化工做中,咱們更應當着重減小重排的發生。
這裏給你們推薦一個網站,裏面詳細列出了哪些CSS屬性在不一樣的渲染引擎中是否會觸發重排或重繪:
csstriggers.com/ (圖片來自官網)
2.4.優化策略
談了那麼多理論,最實際不過的,就是解決方案,你們必定都等着急了吧,作好準備,一大波乾貨來襲:
(一)CSS屬性讀寫分離:瀏覽器每次對元素樣式進行讀操做時,都必須進行一次從新渲染(重排 + 重繪),因此咱們在使用JS對元素樣式進行讀寫操做時,最好將二者分離開,先讀後寫,避免出現二者交叉使用的狀況。最最最客觀的解決方案,就是不用JS去操做元素樣式,這也是我最推薦的。
(二)經過切換class或者style.csstext屬性去批量操做元素樣式
(三)DOM元素離線更新:當對DOM進行相關操做時,例如innerHTML、appendChild等均可以使用Document Fragment對象進行離線操做,待元素「組裝」完成後再一次插入頁面,或者使用display:none 對元素隱藏,在元素「消失」後進行相關操做。
(四)將沒用的元素設爲不可見:visibility: hidden,這樣能夠減少重繪的壓力,必要的時候再將元素顯示。
(五)壓縮DOM的深度,一個渲染層內不要有過深的子元素,少用DOM完成頁面樣式,多使用僞元素或者box-shadow取代。
(六)圖片在渲染前指定大小:由於img元素是內聯元素,因此在加載圖片後會改變寬高,嚴重的狀況會致使整個頁面重排,因此最好在渲染前就指定其大小,或者讓其脫離文檔流。
(七)對頁面中可能發生大量重排重繪的元素單獨觸發渲染層,使用GPU分擔CPU壓力。(這項策略須要慎用,得着重考量以犧牲GPU佔用率可否換來可期的性能優化,畢竟頁面中存在太多的渲染層對於GPU而言也是一種沒必要要的壓力,一般狀況下,咱們會對動畫元素採起硬件加速。)
3.JS阻塞性能
JavaScript在網站開發中幾乎已經肯定了壟斷地位,哪怕是一個再簡單不過的靜態頁面,你均可能看到JS的存在,能夠說,沒有JS,就基本沒有用戶交互。然而,腳本帶來的問題就是他會阻塞頁面的平行下載,還會提升進程的CPU佔用率。更有甚者,如今node.js已經在前端開發中普及,稍有不慎,咱們引起了內存泄漏,或者在代碼中誤寫了死循環,會直接形成咱們的服務器奔潰。在現在這個JS已經遍及先後端的時代,性能的瓶頸不僅僅只是停留在影響用戶體驗上,還會有更多更爲嚴重的問題,對JS的性能優化工做不可小覷。
在編程的過程當中,若是咱們使用了閉包後未將相關資源加以釋放,或者引用了外鏈後未將其置空(好比給某DOM元素綁定了事件回調,後來卻remove了該元素),都會形成內存泄漏的狀況發生,進而大量佔用用戶的CPU,形成卡頓或死機。咱們可使用chrome提供的JavaScript Profile版塊,開啓方式同Layers等版塊,這裏我就再也不多說了,直接上效果圖:
咱們能夠清除看見JS執行時各函數的執行時間以及CPU佔用狀況,若是我在代碼裏增長一行while(true){}, 那麼它的佔用率必定會飆升到一個異常的指標(親測93.26%)。
其實瀏覽器強大的內存回收機制在大多數時候避免了這一狀況的發生,即使用戶發生了死機,他只要結束相關進程(或關閉瀏覽器)就能夠解決這一問題,但咱們要知道,一樣的狀況還會發生在咱們的服務器端,也就是咱們的node中,嚴重的狀況,會直接形成咱們的服務器宕機,網站奔潰。因此更多時候,咱們都使用JavaScript Profile版塊來進行咱們的node服務的壓力測試,搭配node-inspector 插件,咱們能更有效地檢測JS執行時各函數的CPU佔用率,針對性地進行優化。
(PS:沒修煉到必定水平,千萬別在服務端使用閉包,一個是真沒啥用,咱們會有更多優良的解決辦法,二是真的很容易內存泄漏,形成的後果是你沒法預期的)
4.【拓展】負載均衡
之因此將負載均衡做爲拓展內容,是由於若是是你本身搭建的我的網站,或者中小型網站,其實並不須要考慮多大的併發量,可是若是你搭建的是大型網站,負載均衡即是開發過程不可或缺的步驟。
4.1.Node.js處理IO密集型請求
如今的開發流程都注重先後端分離,也就是軟件工程中常提到的「高內聚低耦合」的思想,你也能夠用模塊化的思想去理解,先後解耦就至關於把一個項目分紅了前端和後端兩個大模塊,中間經過接口聯繫起來,分別進行開發。這樣作有什麼好處?我就舉最有實際效果的一點:「異步編程」。這是我本身想的名字,由於我以爲先後解耦的形式很像咱們JS中的異步隊列,傳統的開發模式是「同步」的,前端須要等後端封裝好接口,知道了能拿什麼數據,再去開發,時間短,工程大。而解耦以後,咱們只須要提早約定好接口,先後兩端就能夠同時開發,不只高效並且省時。
咱們都知道node的核心是事件驅動,經過loop去異步處理用戶請求,相比於傳統的後端服務,它們都是將用戶的每一個請求分配到異步隊列進行處理,推薦你們去看這樣一篇博文:Node.js : 我只須要一個店小二。特別生動地講解了事件驅動的運行機制,通俗易懂。事件驅動的最大優點是什麼?就是在高併發IO時,不會形成堵塞,對於直播類網站,這點是相當重要的,咱們有成功的先例——快手,快手強大的IO高併發究其本質必定能追溯到node。
其實如今的企業級網站,都會搭建一層node做爲中間層。大概的網站框架如圖所示:
4.2.pm2實現Node.js「多線程」
咱們都知道node的優劣,這裏分享一份連接,找了挺久寫的還算詳細:https://www.zhihu.com/question/19653241/answer/15993549。其實都是老套路,那些說node不行的都是指着node是單線程這一個軟肋開撕,告訴你,咱們有解決方案了——pm2。這是它的官網:pm2.keymetrics.io/ 。它是一款node.js進程管理器,具體的功能,就是能在你的計算機裏的每個內核都啓動一個node.js服務,也就是說若是你的電腦或者服務器是多核處理器(如今也少見單核了吧),它就能啓動多個node.js服務,而且它可以自動控制負載均衡,會自動將用戶的請求分發至壓力小的服務進程上處理。聽起來這東西簡直就是神器啊!並且它的功能遠遠不止這些,這裏我就不做過多介紹了,你們知道咱們在上線的時候須要用到它就好了,安裝的方法也很簡單,直接用npm下到全局就能夠了$ npm i pm2 -g具體的使用方法還有相關特性能夠參照官網。這裏我在build文件夾內添加了pm2.json文件,這是pm2的啓動配置文件,咱們能夠自行配置相關參數,具體可參考github源碼,運行時咱們只要在上線目錄下輸入命令$ pm2 start pm2.json便可。
下面是pm2啓動後的效果圖:
4.3.nginx搭建反向代理
在開始搭建工做以前,首先得知道什麼是反向代理。可能你們對這個名詞比較陌生,先上一張圖:
所謂代理就是咱們一般所說的中介,網站的反向代理就是指那臺介於用戶和咱們真實服務器之間的服務器(說的我都拗口了),它的做用即是可以將用戶的請求分配到壓力較小的服務器上,其機制是輪詢。聽完這句話是否是感受很耳熟,沒錯,在我介紹pm2的時候也說過一樣的話,反向代理起到的做用同pm2同樣也是實現負載均衡,你如今應該也明白了二者之間的差別,反向代理是對服務器實現負載均衡,而pm2是對進程實現負載均衡。你們若是想深刻了解反向代理的相關知識,我推薦知乎的一個貼子:www.zhihu.com/question/24… 。可是你們會想到,配服務器是運維的事情啊,和咱們前端有什麼關係呢?的確,在這部分,咱們的工做只有一些,只須要向運維提供一份配置文檔便可。
也就是說,在和運維對接的時候,咱們只須要將上面這幾行代碼改成咱們配置好的文檔發送給他就好了,其餘的事情,運維小哥會明白的,不用多說,都在酒裏。
可是,這幾行代碼該怎麼去改呢?首先咱們得知道,在nginx中,模塊被分爲三大類:handler、filter和upstream。而其中的upstream模塊,負責完成完成網絡數據的接收、處理和轉發,也是咱們須要在反向代理中用到的模塊。接下來咱們將介紹配置代碼裏的內容所表示的含義
4.3.1.upstream配置信息:
upstream關鍵字後緊跟的標識符是咱們自定義的項目名稱,經過一對花括號在其中增添咱們的配置信息。
ip_hash 關鍵字:控制用戶再次訪問時是否鏈接到前一次鏈接的服務器
server關鍵字:咱們真實服務器的地址,這裏的內容確定是須要咱們去填寫的,否則運維怎麼知道你把項目放在那個服務器上了,也不知道你封裝了一層node而得去監聽3000端口。
4.3.2.server配置信息
server是nginx的基本配置,咱們須要經過server將咱們定義的upstream應用到服務器上。
listen關鍵字:服務器監聽的端口
location關鍵字:和咱們以前在node層說到的路由是起一樣的功能,這裏是把用戶的請求分配到對應的upstream上