標籤:

誰能介紹下web前端工程化?

誰能介紹下web前端工程化?


謝邀。對前端工程化有了新的認識,對部分內容做了修改。

目前來說,Web業務日益複雜化和多元化,前端開發已經由以WebPage模式為主轉變為以WebApp模式為主了。現在隨便找個前端項目,都已經不是過去的拼個頁面+搞幾個jQuery插件就能完成的了。工程複雜了就會產生許多問題,比如:如何進行高效的多人協作?如何保證項目的可維護性?如何提高項目的開發質量?...

前端工程化是前端架構中重要的一環,主要就是為了解決上述大部分問題的。而前端工程本質上是軟體工程的一種,因此我們應該從軟體工程的角度來研究前端工程。

那麼前端工程化需要考慮哪些因素?

本人總結經驗,認為前端工程化主要應該從模塊化、組件化、規範化、自動化四個方面來思考,下面一一展開。

## 模塊化

簡單來說,模塊化就是將一個大文件拆分成相互依賴的小文件,再進行統一的拼裝和載入。只有這樣,才有多人協作的可能。

### JS的模塊化

在ES6之前,JavaScript一直沒有模塊系統,這對開發大型複雜的前端工程造成了巨大的障礙。對此社區制定了一些模塊載入方案,如CommonJS、AMD和CMD等,某些框架也會有自己模塊系統,比如Angular1.x。

現在ES6已經在語言層面上規定了模塊系統,完全可以取代現有的CommonJS和AMD規範,而且使用起來相當簡潔,並且有靜態載入的特性。

規範確定了,然後就是模塊的打包和載入問題:

1. 用Webpack+Babel將所有模塊打包成一個文件同步載入,也可以打成多個chunk非同步載入;

2. 用SystemJS+Babel主要是分模塊非同步載入;

3. 用瀏覽器的&

### CSS的模塊化

雖然SASS、LESS、Stylus等預處理器實現了CSS的文件拆分,但沒有解決CSS模塊化的一個重要問題:選擇器的全局污染問題。

按道理,一個模塊化的文件應該要隱藏內部作用域,只暴露少量介面給使用者。而按照目前預處理器的方式,導入一個CSS模塊後,已存在的樣式有被覆蓋的風險。雖然重寫樣式是CSS的一個優勢,但這並不利於多人協作。

為了避免全局選擇器的衝突,各廠都制定了自己的CSS命名風格:

  • BEM風格;
  • Bootstrap風格;
  • Semantic UI風格;
  • 我們公司的NEC風格;
  • ...

但這畢竟是弱約束。選擇器隨著項目的增長變得越多越複雜,然後項目組裡再來個新人帶入自己的風格,就更加混亂了。

所以我很贊同這句話:

與其費盡心思地告訴別人要遵守某種規則,以規避某種痛苦,倒不如從工具層面就消滅這種痛苦。

從工具層面,社區又創造出Shadow DOM、CSS in JS和CSS Modules三種解決方案。

  • Shadow DOM是WebComponents的標準。它能解決全局污染問題,但目前很多瀏覽器不兼容,對我們來說還很久遠;
  • CSS in JS是徹底拋棄CSS,使用JS或JSON來寫樣式。這種方法很激進,不能利用現有的CSS技術,而且處理偽類等問題比較困難;
  • CSS Modules仍然使用CSS,只是讓JS來管理依賴。它能夠最大化地結合CSS生態和JS模塊化能力,目前來看是最好的解決方案。Vue的scoped style也算是一種。

### 資源的模塊化

Webpack的強大之處不僅僅在於它統一了JS的各種模塊系統,取代了Browserify、RequireJS、SeaJS的工作。更重要的是它的萬能模塊載入理念,即所有的資源都可以且也應該模塊化。

資源模塊化後,有三個好處:

  1. 依賴關係單一化。所有CSS和圖片等資源的依賴關係統一走JS路線,無需額外處理CSS預處理器的依賴關係,也不需處理代碼遷移時的圖片合併、字體圖片等路徑問題;
  2. 資源處理集成化。現在可以用loader對各種資源做各種事情,比如複雜的vue-loader等等。
  3. 項目結構清晰化。使用Webpack後,你的項目結構總可以表示成這樣的函數:
    dest = webpack(src, config)

## 組件化

首先,組件化≠模塊化。好多人對這兩個概念有些混淆。

模塊化只是在文件層面上,對代碼或資源的拆分;而組件化是在設計層面上,對UI(用戶界面)的拆分。

從UI拆分下來的每個包含模板(HTML)+樣式(CSS)+邏輯(JS)功能完備的結構單元,我們稱之為組件。

其實,組件化更重要的是一種分治思想

Keep Simple. Everything can be a component.

這句話就是說頁面上所有的東西都是組件。頁面是個大型組件,可以拆成若干個中型組件,然後中型組件還可以再拆,拆成若干個小型組件,小型組件也可以再拆,直到拆成DOM元素為止。DOM元素可以看成是瀏覽器自身的組件,作為組件的基本單元。

傳統前端框架/類庫的思想是先組織DOM,然後把某些可復用的邏輯封裝成組件來操作DOM,是DOM優先;而組件化框架/類庫的思想是先來構思組件,然後用DOM這種基本單元結合相應邏輯來實現組件,是組件優先。這是兩者本質的區別。

其次,組件化實際上是一種按照模板(HTML)+樣式(CSS)+邏輯(JS)三位一體的形式對面向對象的進一步抽象

所以我們除了封裝組件本身,還要合理處理組件之間的關係,比如(邏輯)繼承(樣式)擴展(模板)嵌套包含等,這些關係都可以歸為依賴

其實組件化不是什麼新鮮的東西,以前的客戶端框架,像WinForm、WPF、Android等,它們從誕生的那天起就是組件化的。而前端領域發展曲折,是從展示頁面為主的WebPage模式走過來的,近兩年才從客戶端框架經驗中引入了組件化思想。其實我們很多前端工程化的問題都可以從客戶端那裡尋求解決方案。

目前市面上的組件化框架很多,主要的有Vue、React、Angular 2、我們公司 @鄭海波 的Regular、Avalon等。你感興趣可以都研究一下,選擇一套中意的。其實Vue文檔中的對比其他框架一文已經講得很詳細了。

## 規範化

模塊化和組件化確定了開發模型,而這些東西的實現就需要規範去落實。

規範化其實是工程化中很重要的一個部分,項目初期規範制定的好壞會直接影響到後期的開發質量。

我能想到的有以下一些內容:

  • 目錄結構的制定
  • 編碼規範
  • 前後端介面規範
  • 文檔規範
  • 組件管理
  • Git分支管理
  • Commit描述規範
  • 定期CodeReview
  • 視覺圖標規範
  • ...

其中編碼規範最好採取ESLint和StyleLint等強制措施,配置git hooks可以實現Lint不過不能提交代碼等機制,因為人是靠不住的。

前後端介面管理可以了解一下我們公司出的NEI - 介面管理平台。

## 自動化

作了這麼多年程序猿的我,一直秉持的一個理念是:

任何簡單機械的重複勞動都應該讓機器去完成。

所以我也認為,前端工程化的很多臟活累活都應該交給自動化工具來完成。

### 圖標合併

  • 不要再用PS拼雪碧圖了,統一走Webpack吧;
  • 不要再用Icomoon了,統一走Webpack吧。

### 持續集成

### 自動化構建

### 自動化部署

### 自動化測試

前端自動化測試能夠提高代碼質量、減少人肉測試等,這些優點是不言而喻的。

市面上前端測試框架有很多,選擇哪個都不會有太大問題,我們用的是:

Karma + Mocha + Chai


自動化工具 Grunt

第一份工作, 在公司推薦了Grunt , 居然沒人鳥我..

心想了一下, 我還是自己一邊玩去吧

哈哈.

Grunt 是 Node.js 包管理浮生出來的一種工具, 主要是針對前端工程的.

寫配置文件自動完成 - 合併文件 - 壓縮文件 - 自動測試 - 打包 - 圖片優化, - CSS優化等等之類的任務, 都可以讓 Grunt 自動完成. 還提供文件監視功能.

本質上Node.js 屬於伺服器端開發, 除了所謂的Module, 擴展是要靠C++來寫的.

只是老外也覺得奇怪, NPM玩著玩著居然玩到前端來了.


就是把一整套前端工作流程中能用工具搞定的部分,用工具搞定。

比如:

以前創建配置初始項目文件結構和基本文件,以前靠複製,現在輸入命令自動生成。

以前校驗 JS 文件是否規範,你可能複製一下放到 jshint 上校驗一下,現在配置 grunt 監聽文件變動自動校驗顯示校驗結果。

以前修改代碼查看效果,要手動刷新瀏覽器,現在有一大堆插件可以監聽文件變動自動刷新。

以前壓縮合併文件用手工複製到壓縮工具然後複製到一個文件裡面,現在配置一下 grunt 等自動監聽文件變動,自動合併壓縮。

以前發布到伺服器上,要手動使用 FTP 軟體上傳,現在也可以用工具自動打包上傳。

把這些玩意規範一下,給一堆通用的命令來調用這些功能,就是前端工程化。

來點乾貨:京東前端工業化實踐之路(1)


我的live里完整的介紹了我個人對工程化,工程師,前端,前端工程化這幾個名詞的解釋。就算是新手也能有個系統的理解。目前來看答案里還沒有和我的觀點一樣的,簡單概括,工程化是解決怎麼做,怎麼升級的學問,實踐工程涉及到的地方很多,live里也做了很多比喻和實際的不同公司的例子。

https://www.zhihu.com/lives/792374545070825472

當然真的不是廣告,只是我想說說自己對這個題目的看法。


知乎專欄:

工具化與工程化


正好借這個問題總結一下前端工程化的工作經驗。

首先,前端工程化的大前提是:前後分離。工程化的第一個問題是把前端封裝成一個可以獨立運行的服務。我們選擇使用 Docker + Node.js。Docker 負責打包。Node.js 負責服務端路由和靜態文件服務(一般是開發環境)。

很多人聽到 前後分離 這個詞,都覺得很簡潔,很美好。寫好自己的頁面就行了, 老子再也不用搞服務端編碼了。其實真正得到解放的更多的時候是後端。而前端要考慮很多問題,最常見的就是 介面鑒權 問題。需要對接 OAuth2.0 服務的 web app 如何前後分離呢?這是一個挺常見的例子,很多的微信 H5 都需要實現微信對接。我們知道 OAuth2.0 的對接流程包含這麼幾個階段:

  • 跳轉到微信認證頁面

  • 用戶授權

  • 跳回 web app 頁面,返回 code

  • web app 在服務端調用微信介面,獲取用戶信息,創建 session

整個過程當中需要前端完成跳轉,也需要後端負責獲取用戶信息,負責創建 session。 其實還有像微信支付之類的類似的場景。前端工程化的第一個問題就是把這些複雜一些的流程梳理清楚,把任務清晰的拆分開。

然後,我覺得是 自動化構建和發布。這恐怕是大家討論得最多的環節了。這塊分兩部分。大家最了解的是前端代碼打包和構建,這塊我們使用的是 webpack,實現代碼打包壓縮,上傳 CDN,更新 html 資源鏈接等等。

另一個大家容易忽視的問題,那就是 web app 本身作為一個 web 服務,它自身的打包和發布。這塊我們用的是 Docker,所有的 web app,我們會打包成 Docker 鏡像發到伺服器上部署。這樣也算是解決了前端小白不會各種伺服器操作和配置的問題。打包成 Docker 鏡像之後,讓後端工程師幫忙或者直接使用 Daocloud 之類的工具,可以很方便地完成發布任務。前端只需要學會基本的 Docker 概念,能看明白 Dockerfile 就夠了。

代碼模塊化管理和 code lint 在這兒就不多提了,得益於 webpack、sass 這類的工具,實行模塊化管理在前端終於不那麼費勁了。

再者,前端工程化的重點應該是自動化測試了。更準確的說是 提高代碼的可測性。一直覺得 React 意義重大。UI 組件化都是其次,pure render 讓我們能夠用一個普通函數就能實現一個組件,你只需要給它一個 Element Tree,一個 DSL 而已,react 幫你 diff,幫你 render。這個 DSL 還是可以換渲染引擎的,所以有了 react native,淘寶最近不是還發了一個 rax 嗎?用了 React, UI 組件自動化測試也變得更簡單了,很多時候你只需要檢查 render 函數返回的數據。

提高代碼可測性,除了在 UI 組件的測試,在介面對接環節也很重要。前端工程化面臨的一個問題就是,和後端的對接任務變得更多,基本都是通過介面對接。如果後端介面還沒準備好,那怎麼辦呢?很多人都推薦部署一個 mock server,個人覺得不是最好的方法。你應該在代碼當中設計一個 api 層,api 層用來封裝所有的數據介面。然後在 api 層 mock 數據,在後端介面沒開發好之前先使用 mock 數據版本的 api 模塊,通過 mock api 模塊來添加更豐富的自動化測試。這要比搭建個 mock server 方便快捷多了。

總結起來,前端工程化主要就是前後分離,複雜流程的拆分,介面健全,前端項目獨立打包發布,代碼模塊化管理,提高代碼可測性,提高代碼測試覆蓋率...

最後忍不住想潑一盆冷水,上面提到的這些個概念,前後分離,自動構建打包發布,代碼模塊化,自動化測試,依賴注入,還有沒提到的 redux,flux 等等,這 TM 在其他搬磚領域都是常識... 常識...


建議看看百度的fis

雖然百度有很多口碑不太好的地方,但是有些東西,的確是實打實的好用。


前端工程化是根據具體的業務特點,將前端的開發流程、技術、工具、經驗等規範化、標準化。它的目的是讓前端開發能夠「自成體系」,最大程度地提高前端工程師的開發效率,降低技術選型、前後端聯調等帶來的協調溝通成本。

這裡是美團點評在酒店旅遊方向上的前端工程化實踐案例:http://tech.meituan.com/tech-salon-13-app-proto.html 。

app-proto 結構設計圖

另外,還有一篇組件化方面的技術文章 http://tech.meituan.com/frontend-component-practice.html ,也可以作為參考。


前端工程化變革的差不多了,剩下的就是修修補補了(這是個flag?),作為一個.net開發者在做好準備的情況下(nodejs nuget vscode .net core sdk, .net 4.6),可以直接使用dotnet new angular,來搭建一個 .net core + angular2 + typescript + webpack + sass來開發,單純的ng2用戶也可以使用ng2-cli工具創建,babel是不需要的了,ts就能夠做到編譯了,這些東西包含了這幾年來前端工程化的各種思想

比如包管理終於有了npm,模塊化終於有了es6的import寫法和最終管他們的webpack,mvvm有了ng2 ,vue 等框架,並且加入了組件化和適配ts,來符合模塊化和es6的寫法,各種編譯工具和配置,項目模板,這些東西每一樣單獨拿出來就能學半天,根本不是一個小前端學兩天搭的起來的。。。。於是終於形成了搭建工具,那後端一起來怎麼辦,於是又有了搭建工具,整套東西一搭,思想全在裡面了,邊學邊寫邊領悟,每一樣東西單獨挑出來都能學半天,他為什麼要模塊化,為什麼要強類型,為什麼要spa,為什麼要測試,為什麼要包管理,甚至目錄為何是這麼設計的,這麼多配置文件都是幹嘛的,webpack剛出來時我看了半天是放棄的,作為一個接受能力沒這麼強的老人了,這所有的一切給了你慢慢懂的時間,工程化是一整套思想,這套思想形成了這一整套工具,而你,可以撿現成的了。

最後,狠狠的扇那些一提ts就跳出來噴一通的傢伙們。


推薦這個系列:https://github.com/fouber/blog/issues/10


誰能教教我前端工程化怎麼實現


推薦閱讀:

前端開發中提到的「腳手架」到底指什麼,CLI?gulp 和 gulp-cli有什麼區別
web前端之路?
CSS的復用代碼,是多添加點類好?還是增加點代碼量好?
Win10 發布後,大公司前端會怎麼發展?

TAG:前端開發 |