- 前端工程化:體系設計與實踐
- 周俊鵬
- 2880字
- 2019-11-18 14:53:58
1.2 Node.js帶給前端的改革
1.2.1 前端的兩次新生
Brendan Eich可能也沒有想到JavaScript這門第1版只用了10天便完成設計的腳本語言在今天會如此流行。JavaScript目前不僅可以開發(fā)傳統(tǒng)的Web站點,而且還跨足了手機App、小程序、物聯(lián)網等開發(fā)領域。JavaScript經歷過兩次革命性的突破,這兩次突破也帶給了前端兩次新生。
1.第一次新生:AJAX
AJAX技術起步于微軟Outlook的XMLHTTP組件,微軟將其作為ActiveX組件的一部分加入Internet Explorer 5。隨后,其他瀏覽器廠商,包括Mozilla、Safari、Opera等,實現(xiàn)了一個同樣功能的JavaScript對象——XMLHttpRequest。微軟是AJAX技術的布道者,Google的進一步推廣將其帶到了普通民眾眼前。人們驚嘆于Google地圖、Gmail等Web應用程序絕佳的用戶體驗。Jesse James Garrett在2005年2月“Ajax: A New Approach to Web Applications”一文中正式提出了“AJAX”一詞,并一直沿用至今。隨后,W3C在2006年正式發(fā)布了XMLHttpRequest規(guī)范草案。
AJAX技術可以實現(xiàn)異步請求和局部刷新,徹底改變了傳統(tǒng)Web站點的交互模式。Web不僅是供靜態(tài)展示的網站,而且是一種由瀏覽器展現(xiàn)、資源寄存于Internet的應用程序。以此為契機,Web開發(fā)者開始在AJAX技術的基礎之上探索和開發(fā)更加豐富的功能和優(yōu)雅的用戶體驗。與此同時,用戶對Web應用的需求也不斷提高,這間接推動了Web技術的發(fā)展。
這是AJAX技術帶給前端的第一次新生。
2.第二次新生:Node.js
2009年第1版Node.js(只支持Linux和Mac OS X系統(tǒng))的發(fā)布是值得銘記的里程碑。Node.js的作者Ryan Dahl設計Node.js的靈感來自Flickr(一個提供網絡圖片服務的平臺)上的一個上傳進度條,瀏覽器為了能夠獲取上傳文件的進度而不得不頻繁地向服務器發(fā)起查詢請求。與這種方式相比,如果服務器能夠在文件上傳完畢之后主動推送一條消息給瀏覽器的話,會節(jié)省很多瀏覽器和網絡資源消耗。這種理念便是Node.js實現(xiàn)異步操作的核心Event Loop(事件驅動)的雛形,如圖1-2所示。

圖1-2
2011年,Node.js發(fā)布了支持Windows系統(tǒng)的版本,Node.js在Web開發(fā)界進一步流行起來。在此之前的十幾年內,JavaScript一直被認為只能在瀏覽器里耍點小把戲。即便AJAX技術徹底改變了網站的交互模式,JavaScript也仍然未脫離瀏覽器這個“宿主”。Node.js帶來的改革不僅僅是讓JavaScript進入了服務器端開發(fā)領域,更重要的意義是豐富了JavaScript的生態(tài)。JavaScript能做的事情越來越多,業(yè)內泛起了JavaScript學習潮,這在一定程度上加速了ECMAScript規(guī)范的迭代。
這是Node.js帶給前端的第二次新生。
小貼士:隨著用戶對Web應用的期待越來越高,承載Web應用的瀏覽器也“被迫”加速了發(fā)展,尤其是JavaScript引擎。在AJAX技術問世之前,JavaScript引擎只要能夠穩(wěn)定運行幾十行JavaScript代碼即可,但是如今Web應用的JavaScript代碼已經遠遠超過這個量級,動輒幾百上千行。2008年,Google推出了全新的瀏覽器Chrome,搭載代號為V8的JavaScript引擎。V8引擎采用實時編譯(JIT)技術將JavaScript代碼編譯為機器碼執(zhí)行,大大提高了JavaScript代碼的運行效率。Node.js便是使用V8引擎執(zhí)行JavaScript代碼的。
1.2.2 Node.js帶來的改革
Node.js并非一個JavaScript框架,而是一個集成了Google V8 JavaScript引擎、事件驅動和底層I/O API,并且可使用JavaScript語言開發(fā)服務器端應用的運行環(huán)境。與PHP不同的是,Node.js可以直接提供網絡服務,不需要借助Apache、Nginx等專業(yè)的服務器軟件。雖然并不建議在生產環(huán)境下直接將Node.js服務暴露給用戶,但是Node.js這種特性可以讓我們更方便地開發(fā)各種工具,比如將在后續(xù)章節(jié)中講解的前端工程化方案中本地服務器的搭建。
1.服務器端開發(fā)
Node.js作為服務器端平臺已經逐步被國內外公司和團隊接納。2015年10月,著名的開源博客系統(tǒng)WordPress發(fā)布了使用Node.js重寫的4.3版本。許多企業(yè)(國內的,比如阿里巴巴、美團等;國外的,比如IBM、LinkedIn、GoDaddy等)對Node.js也均有不同程度的使用。雖然Node.js尚未威脅到PHP、Java等傳統(tǒng)Web服務器端語言的地位,但Node.js的事件驅動和異步I/O機制,以及其易學習、易部署和對前端工程師天然的語言共通性,讓其成為實時應用、微服務以及前端工程化等應用場景的最佳技術選型之一。
2.同構JavaScript
Node.js在使用JavaScript語言開發(fā)Web服務器端平臺的同時,還提高了同構JavaScript開發(fā)的可行性。
同構(isomorphism)一詞是數(shù)學領域的專業(yè)術語,指的是數(shù)學對象之間屬性或者操作關系的一類映射。數(shù)學中研究同構的主要目的是為了把數(shù)學知識應用于更多不同的領域,同理,在JavaScript開發(fā)領域研究同構的主要目的也是為了將這門編程語言應用于不同的開發(fā)領域。同構JavaScript的概念最早由Airbnb工程師Spike Brehm提出,簡單講就是令JavaScript編寫的代碼既可以在瀏覽器端工作,也可以在服務器端工作,如圖1-3所示。這意味著服務器端和瀏覽器端都可以承載網頁的渲染工作。

圖1-3
傳統(tǒng)網站的渲染流程是由瀏覽器主動發(fā)起請求,然后服務器端生成HTML文檔后發(fā)送響應給瀏覽器,瀏覽器接到響應后將HTML文檔渲染為可視網頁。這是自瀏覽器發(fā)明以來就沿用至今的渲染流程。這種工作模式的優(yōu)點是節(jié)省客戶端資源,在客戶終端設備以及瀏覽器性能普遍比較落后的情況下能夠保證良好的渲染效果,并且服務器端渲染的網頁更利于SEO(Search Engine Optimization,搜索引擎優(yōu)化)。而其缺點是每訪問一個頁面都要發(fā)起請求,每個請求都需要服務器進行路由匹配、數(shù)據庫查詢、生成HTML文檔后再發(fā)送響應給瀏覽器,這個過程會消耗服務器的大量計算資源,如圖1-4所示。

圖1-4
隨著個人終端設備和瀏覽器性能的不斷提升,Web開發(fā)者嘗試將渲染以及路由工作交給客戶端,服務器端RESTFul API只提供渲染HTML所需的JSON數(shù)據。這種形態(tài)的Web應用被稱為SPA(Single Page Application,單頁應用)。SPA有以下優(yōu)點。
·減輕了服務器的資源消耗。
·與HTML文檔比起來,JSON數(shù)據的體積小很多,減少了網絡請求的時間消耗。
·頁面路由控制更快速靈活。
·可以離線使用。
同時SPA也帶來了新問題。首先,瀏覽器需要等待JavaScript文件加載完成之后才可以渲染后續(xù)的HTML文檔內容,用戶在等待的過程中頁面是空白的,這就是我們在進行Web產品性能評估時經常談到的“白屏時間”;其次,由于客戶端和服務器端編程語言不同,可能會存在一些諸如數(shù)據格式的差異,甚至路由邏輯沖突,比如vue-router history模式的路由,這些問題增加了維護難度;最后,SPA不利于常規(guī)的SEO(搜索引擎優(yōu)化)爬蟲(之所以說常規(guī)是因為Google已經針對SPA進行了SEO優(yōu)化,但是目前國內的搜索引擎對SPA的支持并不理想)。
與傳統(tǒng)的服務器端渲染模式和客戶端渲染的單頁應用相比,同構JavaScript擁有更好的性能、可維護性以及對SEO更好的支持。同構JavaScript的理念類似于Java秉承的“Write once, run anywhere”, JavaScript除命名以外終于又跟Java扯上了關系。Node.js是實現(xiàn)同構JavaScript開發(fā)的關鍵。一方面,JavaScript在瀏覽器環(huán)境下可以執(zhí)行渲染工作;另一方面,Node.js運行環(huán)境下同樣可以使用JavaScript創(chuàng)建HTML字符串。在這個前提下,JavaScript開發(fā)生態(tài)中浮現(xiàn)了一大批支持同構開發(fā)的框架和庫,比如Facebook推出的React.js和國內的Vue.js。
3.前端工具
除了服務器端開發(fā)外,Node.js對前端最大的貢獻是豐富了前端工具生態(tài)。在Node.js出現(xiàn)以前,沒有Grunt、Gulp、webpack等便捷且強大的工具,壓縮合并JavaScript、CSS代碼對于前端工程師來說是一項非常艱難的任務。前端工程師不得不使用不熟悉的語言、工具來處理靜態(tài)文件的壓縮合并。而這些工具往往并不是為了處理靜態(tài)文件的,比如Apache Ant。使用Ant處理靜態(tài)文件可以說是殺雞用了牛刀,而且這把牛刀用來殺雞還并不好使。除此之外,也可以使用shell腳本完成這項工作,但對于并不擅長編寫shell腳本的前端工程師來說學習成本和時間成本太高,往往要麻煩團隊中的服務器端工程師代寫。不論哪種選擇,都會對項目的開發(fā)進度產生影響。
Node.js的出現(xiàn)徹底解決了這些問題。目前耳熟能詳?shù)那岸斯ぞ撸热鏕runt、Gulp、webpack,無一不是由Node.js承載的。結合JavaScript的靈活性與Node.js提供的API,前端工程師可以編寫各種工具滿足項目的開發(fā)需求。本書所介紹的前端工程化解決方案中的各個功能模塊全部是由JavaScript語言實現(xiàn)的。