談談前端『新』技術,』技術

來源:互聯網
上載者:User

談談前端『新』技術,』技術

最近有位(大家都知道是誰)的『前輩』在微博上天天叫喚,相信很多人都看煩了。我跟他也算是吵了一架,汙染了大家的時間軸,先說聲抱歉。但是我覺得讓這麼一個撒潑的人誤人子弟,實在看不下去,所以咱上點乾貨以正視聽。

對待新事物的態度問題

我這個人在技術討論的時候信奉很簡單的一個道理:沒有研究過就沒有發言權。對於我不懂的東西,我要麼閉嘴,要麼去研究、試用之後再開口。在我看來,這是進行技術討論的一種基本涵養。技術這個行當,永遠會有新東西出來,不進則退。更關鍵的是,前端比起整個軟體工程乃至電腦科學體系來說,是個相對新生草莽的領域,近年來前端生態的發展其實都是在向其他領域吸收和學習,不論是開發理念、工程實踐還是平台本身(規範、瀏覽器)。所謂的『根正苗紅』的前端,不過是整個發展進程中探索的一個階段而已,那個時代的最佳實務,很多到今天都已經不再適用。過往的經驗固然有價值,但這些經驗如果不結合對新事物本身的瞭解,就很難產生正確的判斷。這裡需要強調的是,學習新事物並不是為了不考慮實際需求的濫用,而是為了擷取足夠的資訊從而作出更靠譜的判斷。在這一點上,某人的態度是不停強調自己過去的八年資曆,強調『經驗和觀察』的重要性,卻對新事物本身採取蔑視和抗拒到了誇張的程度,寧可在微博上撕逼,也不願意花一兩個小時FQ瞭解一下外面的世界。舉例來說,他在批評 Angular/React 的時候是以『就是把伺服器 MVC 那一套搬到了前端』這樣的預設去批判的,完全雞同鴨講;在闡述他自己那套 Widget + OO 的時候,也壓根不瞭解這套思維和現在基於組件的新架構的共通點。這樣偏頗的思維方式,如何做得出靠譜的決策?作為一個技術負責人簡直可以說是不負責任。盲目跟風不可取,盲目抗拒也不可取,要有自己的判斷,但是這個判斷要建立在足夠的一手資訊量基礎上。

為什麼要用『新技術』?

說完態度,我們來深入談談為什麼這些『新技術』會有市場。首先明確一點:任何技術都有針對的適用情境取捨。在對一個技術進行評估後發現不適合,這很正常,比如項目的類型、規模、曆史包袱,以及團隊的學習能力,都是制約技術選型的因素。但這並不妨礙我們分析一項技術本身解決了什麼問題,以及我們的實際需求中是否存在這些問題。接下來我們一項項分析:

1. CSS 預/後處理器 
比如:Sass, Less, Stylus, PostCSS。CSS 本身的設計有很多不利於工程化、影響開發效率的地方,這正是 CSS 預/後處理器要解決的問題。 
(1) 預設的全域 namespace。在全域 namespace 下,任何一條規則都可能產生全域的影響,不利於模組化的多人協作;同時選取器的優先順序如果沒有嚴格的書寫規範,很快就會難以管理,然後產生各種 !important hack。這一點藉助前置處理器雖然不能完全解決,但藉助 nesting 可以讓書寫體驗得到改善。 
(2) 作為一個 DSL 缺乏抽象能力:沒有變數,沒有函數,沒有運算子,沒有混入和繼承,代碼的可複用性差,經常需要大量重複,而通過組合類別名的方式來複用靈活性非常有限。這些都可以藉助前置處理器進行緩解,甚至可以抽象出常用技巧的混入,比如一個混入解決垂直置中,大大加強 CSS 代碼的書寫效率和可維護性。 
(3) 檔案組織:通過原生的 @import 引入其他檔案會產生過多的請求,而前置處理器可以直接合并成一個檔案,在檔案組織上不再有顧慮。 
(4) 智能避免重複勞動:自動根據目標瀏覽器範圍添加首碼。 
2. JavaScript 編譯器 
比如:Babel, CoffeeScript, TypeScript。為什麼要編譯 JavaScript,本質上目標依然是:提高開發效率,提高可維護性。以 Babel 為例,JS 本身的 prototype 原型繼承,之前幾乎每個人都有自己實現一套 OO 類比,現在有原生的 class extends 文法,從語言層面進行統一;函數的參數結構和預設值,避免了手動的預設值分配和參數為 0 的坑;箭頭函數避免了 this 內容相關的坑;塊級的 let/const 避免了 var hoisting 的坑;templateString 避免繁瑣的手動字串拼接;更好的 Unicode 支援;ES2015 模組(為什麼,見這個演講 //benjamn.github.io/empirenode-2015/#/) ; 還有 async await 對於非同步流程處理本質上的改善。一個更好的語言,一個已經正式發布的標準,瀏覽器支援情況不一,有人寫了工具讓你今天就能用,某人對此的態度居然是『沒有問題也要創造問題』… 
CoffeeScript 和 TypeScript 很顯然有各自的主要受眾:Ruby 開發人員和 Java/C# 開發人員。這時候某人又要搬出『偽前端』的大帽子來了,問題是,誰能搞前端並不是你說了算,前端的風氣也不會因為這兩個東西而受什麼影響。這兩個東西的意義就在於它們能夠提高特定人群的開發效率,會去用它們的人很少是因為跟風,而是因為它們確實符合了一部分人的開發習慣。你不屬於那部分人,不代表這些東西沒有意義,它們被噴真是躺著也中槍。(web前端學習交流群:328058344 禁止閑聊,非喜勿進!) 
3. 模組化/構建工具 
比如:RequireJS, SeaJS,Webpack, Browserify, SystemJS。模組化的重要性想必不必多言了,連某『前輩』都在用 RequireJS。前面那兩個現在已經漸漸式微了,那為什麼要有後面這三個?其中一個核心價值在於基於模組規範的包管理方案。由於對於 Node 包格式的相容,使得後面三個方案都可以利用 npm 作為包管理的機制。有了包管理器,你可以將跨項目的基礎庫進行細粒度的單獨封裝,通過 semver 版本保證 API 相容性,在多重專案中按需複用代碼邏輯,還可以直接使用發布在 npm 上的海量第三方庫。更進一步,配合下面要提到的組件化架構,更可以實現 UI 組件的跨項目複用。SeaJS/spm 和 Arale 其實有這個願景,但是玉伯明智的發現了社區的方向而選擇了避免重複的努力。 
另一方面,是在於後面這些新工具強大的擴充機制(尤其是 Webpack)所帶來的一種新的前端打包思路:不僅僅是 JavaScript,而是將 HTML、CSS 和其他靜態資源統統作為『模組』來看待。因為在實際開發中,不僅僅是 JavaScript 的模組之間存在依賴關係,HTML、CSS 和其他靜態檔案之間也會有依賴關係。實際開發中,開發環境和生產環境中這些靜態資源之間的相對路徑關係經常是不一樣的,這就導致我們以往在開發環境到生產環境的上線過程中有很多繁瑣的步驟,比如改寫靜態資源引用的 URL(版本戳,靜態資源網域名稱/CDN),圖片最佳化,根據檔案大小做成內聯、模組的切分和按需載入等等,這些瑣碎的事情固然可以手動解決,但我們要的是效率!效率!一次配置完畢,讓開發人員能夠將後續精力專註於應用本身而不是其他東西。除了上面提到的幾個國外方案,國內也有優秀的類似方案 FIS。 最後,就是基於構建工具我們能夠提供更好的開發體驗。Webpack 的熱重載,在修改代碼後不重載頁面的情況下替換單一模組,對開發體驗帶來質的提升。舉例來說,你在修改一個開啟應用後需要 N 次操作才能看到的組件,如果你改一次就要重複這些操作,那樣效率實在太低。 
4. 組件化架構 
比如:React, Angular 2, Vue。在我看來現代化的組件化架構提供三個核心價值: 
(1) 資料到 DOM 的聲明式映射。無論是 virtual dom render 還是模板,其本質都是聲明式地描述『基於這樣的資料,最終應該呈現給使用者這樣的介面』。在大部分情境下,使用者通常不需要再進行命令式的 DOM 操作。聲明式的代碼比命令式的代碼更簡潔,更容易維護。 
(2) 組件的組織方式。一個組件的各個部分是分散在多個檔案中,還是有合理的組織方式?組件如何發布、如何在多重專案中複用?對此,React 的選擇是把所有東西都放進 JS,而 Vue 則是基於構建工具實作類別似 Web Component 的單檔案組件格式(也可以拆分,同時支援前置處理器)。Angular 2 目前要麼分開多個檔案,要麼直接將 HTML/CSS 作為字串內聯。 
(3) 組件之間如何組合與溝通。這裡的共同要點也是聲明式 > 命令式:通過在 render function / 模板中用標籤形式在父組件中渲染子組件,讓資料驅動組件的存在,從而自然地得到樹狀的組件樹結構,而不是命令式地用 this.add(child) 這樣的方法去管理組件樹。資料溝通方面,通常都採用了從上至下的單向資料傳遞,而子組件則可以通過事件冒泡或是傳遞一個回調的方式來對父組件做出反饋。注意這裡的重點是,子組件並不能任意地改寫父組件的狀態,無論是觸發事件還是調用回調,最終父組件發生了什麼還是由父組件自身來決定的,這就保證了子組件對父組件的解耦,從而使得子組件可移植/複用。在大型應用裡,還要考慮如何讓一個事件的後果能夠被清晰的理解,讓一個開發人員可以迅速理解另一個人的代碼的意圖,讓應用不會隨著規模的增長而失控?這則是 Flux Redux 這樣的狀態管理方案試圖解決的問題。其核心在於讓副作用可控,最終目的也是可維護性。 
除了以上三點之外,還有額外的一點,那就是 CSS 和組件的關係。理想情況下,一個高內聚的組件應當包含這個組件所需要的 js 邏輯、HTML 結構和 CSS。但是由於之前提到過的 CSS 全域 namespace 的問題,使得跟隨組件的局部 CSS,尤其是可移植性,一直是一個難題。這一點上目前有幾個方案:React 為代表的 CSS in JS,CSS modules,Shadow DOM(依賴瀏覽器實現),以及 Vue/Angular 2 的編譯時間局部 CSS/模板改寫。幾個方案各有千秋,但核心是都一定程度上解決了 CSS 全域 namespace 的問題,使得跟隨組件的 CSS 不再影響外部,獲得了可移植性,從而讓組件達成真正的高內聚。而高內聚的組件才可以獨立作為包分發,實現跨項目複用。 
5. 測試/代碼規範工具 
據某『前輩』自己說,他因為時間不夠,所以是放棄寫測試的。為什麼時間不夠呢,因為工具落後,開發效率太低唄。而且用古老的比如 Qunit / YUI test 寫的測試,必須手動開啟一個一個瀏覽器測,也沒有程式碼涵蓋範圍資訊。現在呢,代碼規範有 ESLint,單元測試有 Karma,整合測試有 CasperJS/Nightwatch,程式碼涵蓋範圍用 istanbul,配置完畢後一行命令自動多瀏覽器測試彙報結果和覆蓋率,如果搭好持續整合環境,甚至不用你自己手動跑,push 到倉庫就行了。這些東西也不需要團隊人人都懂,架構師搭好底子,新人只要用就行了,但是卻可以大幅提高整體的代碼品質。

說了這麼多,無非是為了說明,新技術的出現,永遠是因為有對應的問題可以解決才出現的,其核心訴求都是提高開發效率和可維護性,這正是作為工程師應該追求的東西。在研究、配置、推廣任何新技術的過程中,肯定會有成本,你覺得為瞭解決這些問題不值得付出這些成本,不代表別人也是這樣,更不代表你有資格去蔑視別人為解決問題做出的努力。至於揣測他人是『靠資訊不對等闖名聲』,除了小人之心我還能說什麼呢?

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.