我理解的前端工程化

前言

現在越來越多的前端人員都在聊前端工程化。可能很多初學者認為前端工程化就是我會使用webpack,我能夠使用某些cli工具來搭建我們公司的項目等等;也有一部分的人認為前端工程化就是涵蓋了前端從立項到上線過程中的每一步,前端的每個項目即是前端的一個工程在前端工程中包含有項目的創建過程,開發過程,測試過程,上線過程等一系列的工作流程的內容等。

那麼什麼是前端工程化?對於這個問題,我這裡就從我個人的角度來聊一下,這個前端工程化的內容。

前端工程化的由來

對於前端開發來說從最初的切圖仔到現在的可以稱為前端工程師的稱呼上面,可以看出,前端在整個web端的的地位在逐漸的提升。當然提升的也不僅僅是稱呼,更重要的是前端的開發理念加開發流程的整體的發展。

刀耕火種時代

很久以前其實前端的工作其實還是很簡單的,就是講UI的設計圖轉換成網頁,並且寫一部分的JS來控制頁面中的交互內容,不用去管後期的數據渲染什麼的。而且以前的前端開發流程也很簡單,就是自己切好圖,丟給後端的同學就好了,至於套頁面等的工作就不用管了,畢竟哪些工作都只是後端同學的事情了。當然也有一些企業單位會讓前端去寫渲染層的東西,讓前端使用php,jsp,asp等技術,來完成前端的工作(這樣前端同學在換工作的時候,由於後端使用語言的不同,可能就需要學習各種的後端框架以及各種的模板引擎)。

其實不管是哪種實現的思路,前端這邊的仍然是一個比較簡單而且重複的工作。「簡單」,其實就是說白了就是切圖,排版的內容,哪怕是後續套頁面的工作(當然這些都是一些中小型項目);「重複」,就是說前端中有很多通用的東西,前端要做的就是各種拷貝,每一次的拷貝生怕有任何一點的遺漏。隨著項目的發展,前端的項目是越來越大,後期的維護成本也越來越大,前端這邊的改動成本也會越來越大, 就可能需要前端去處理後端數據的問題,或者是需要後端來解決前端的問題,這樣的這樣不僅僅操作的難度大,而且,對於雙方都不友好。

發展階段

後來有人想到了前端中存在一個被叫做ajax(Asynchronous JavaScript and XML)的東西,這個東西可以實現前端跟後端的通訊,這樣,就能夠將前端的項目進行單獨部署,然後後端單獨部署,這樣就實現了完美的前後端分離的工作。瞬間,就像發現新大陸一樣,很多企業都開始實行這樣的模式了,只是部署的方式可能有些不同,有的是直接將前端的頁面和資源直接扔到nginx中,作為一個靜態資源伺服器,將網站指向到html文件中;有的是將前端的項目直接放進項目裡面,不管是作為靜態資源還是作為view資源,然後通過建個Controller的方式再進行訪問到頁面的文件等。都是為了將前後端的工作進行分離開來,早點脫離修改其他人程式碼的煩惱。

鳥槍換炮時代

前後端工作分離開始之後(這個不是很準確),接著就是前端重複內容的問題。對於重複內容,不管是html中的內容還是JavaScript中的內容,等等這些東西,還是需要拷貝。但是對於使用了模板引擎的項目來說可能稍微會好一些,可以使用includes來引入公共的部分,但是對於js來說不行。如果將每個細分的功能模組都寫入到一個js文件中的話,就會造成整個js比較大,另外還有可能造成全局污染問題。於是一些優秀的前端工程師們決定向後端取經,提出了模組機制。早期,這種模組機制在Dojo、EXT這些框架中都是內置的,但是顯然說服不了另一個框架的用戶用對方的模組機制,於是有人立志要統一這種模組定義方式,成立了CommonJS。但是CommonJS內部也有派系,誰也說不服對方。終於有一個人忍不住自己獨立開發出RequireJS,其模組規範即為AMD。AMD最大的優勢是它支援各種插件,且簡單明了,並且提供shim機制載入以非AMD規範編寫的JavaScript程式碼。接著就是NodeJs的誕生,伴隨著NodeJs的誕生,同時也推出了不少的前端打包工具,grunt,然後就是gulp。

質的飛躍

對於前端開發,僅僅將分模組開發的程式碼打包到一起能夠解決一部分的問題,但是整個過程的運行什麼的還是基於文件系統的,並不能夠完全模擬一個網路環境。如果要模擬一個網路環境,就需要一個伺服器的載體,或者是nginx,jsp,亦或是php等等,但是這些對於前端來說又比較的陌生,同時由於nodejs的發展,進化出了基於node的前端伺服器框架express。因此就有人想,能否基於node服務來提供伺服器載體,並且,將打包功能集成進去。這個時候,webpack就應運而生了。同時webpackt提供熱更新功能,webpack是一個比較開放的東西,大家都可以為其添加不同文件的編譯工具(loader),並且用戶可以根據自己的需求,將其進行改造,形成自己的一套完整的開發體系。因此webpack迅速的佔領了整個前端的工具鏈的市場。

完整體系的建立

漸漸地像vue,react和angular框架的逐漸推出和完善,都各自提供了模組發的開發,組件的共用,大大的提高了前端開發人員的開發效率。另外各個框架都有推出自己基於webpack的cli工具,統一了他們的工程化開發流程,從dev到build等。這樣一來,導致很多的前端同學都覺得,前端工程化就是webpack。後續有推出了很多的打包工具,比如說rollup,vite等,都是為了幫助前端同學提高工作效率。另外很多前端根據自己的工作需求,開發了不同性質的前工程化工具,並將前端工程化推向了一個高潮。近兩年,各種低程式碼平台的呼聲越來越高,其實低程式碼也算是前端工程化的一個範疇。

低程式碼時代

近兩年,各種低程式碼平台的呼聲越來越高,其實低程式碼也算是前端工程化的一個範疇。前端工程化的目的就是為了提高前端的開發效率的問題,而低程式碼平台的目的也是提高前端的開發效率,並且低程式碼的實現方案是基於之前的模組化打包方案,以及打包工具,和各自的框架,只是能夠使開發者能夠所見即所得,而且就算不懂前端,也能夠簡單的配置一下,來實現自己的想要的功能。這樣的前端開發者只需要按照需求,來訂製化的開發一些組件,以及將大多數的精力放在工具的優化和開發使用上面。這樣開發的工作量低了,溝通以及資訊的傳遞的損失以及時效性所帶來的的成本,也會隨著低程式碼平台的完善,逐漸的降低。

什麼是前端工程化

「工程」一詞源於十八世紀的歐洲,最早是使用在兵器製造、具有軍事目的的各項勞作,後拓展到多個領域,比如建築屋宇、機械製造、架橋修路以及軟體開發。在在現代社會中,「工程」一詞有廣義和狹義之分。就狹義而言,「工程」定義為:以某組設想的目標為依據,應用有關的科學知識和技術手段,通過有組織的一群人將某個現有實體轉化為具有預期使用價值的人造產品的過程。說白了「工程」就是指從有想法,到將想法轉化為實際的東西的過程。那麼「工程化」也就是應用於實體產生的整個過程。

有關前端工程化的概念,就是將前端項目(或者想法)轉化成實際能夠使用的應用的整個過程。換句簡單點的話說就是從立項到開發再到最後的上線的整個過程,就是前端工程化。

那麼在這個過程中,前端開發者都做了哪些事情呢?

  • 設計方案和技術選型
  • 開發規範設計
  • 介面通用規範的約定
  • 項目的搭建,創建git託管
  • 功能拆分,組件拆分
  • 基礎組件的開發
  • 業務功能的開發
  • 後端介面對接聯調自測
  • 提測
  • bugfix
  • 打包上線
  • 後期維護

我理解的前端工程化,至少應該包含有上述過程的,才能算是整個工程化。就好像我們剛初出茅廬的時候,拿到一個需求(可能是一堆的設計圖),就開始切圖鋪頁面,當頁面鋪好了,就完了,就萬事大吉了,中間缺少某種狀態的情況展示效果,我們最後直接甩鍋給UI小姐姐。經過這麼多年的工作,以及對前端的理解,以及對前端的思考,最終確定了,我們前端要做的事情包含有上述的每一個過程。而且在整個過程中,前端需要跟不同的角色,不同的人進行溝通,以能夠更好的將用戶的需求實現。

如何推進前端工程化建設

在了解了前端工程化都應該包含哪些東西的時候,就需要考慮前端工程化的建設工作。其實整個工程化建設就是整個前端工作流程的規範化的一個建設。當然中間還夾雜著一些技術層面的優化的內容。但是有一點我可以很肯定的說,前端工程化建設絕對不是僅對webpack的學習和使用,只能說,webpack在前端工程化的過程中起著舉足輕重的作用。

接下來我們分步來來聊一下前端工程化的每一步都要做哪些工作:

技術選型

在項目的架構中,我們需要選擇各種技術棧所對應的技術;在項目的開發中,我們需要選擇各種工具庫。技術選型是我們必然會碰到的,我們常常面臨的不是單個技術的選型,而是對於一個項目所涉及的一整套技術、方案、規範或者產品的選型。我們需要仔細的去權衡各種技術、各種組合的利弊,做出取捨。

技術選型其實在整個項目的發展過程中,有這舉足輕重的地位。繼續選型的選型直接影響到項目的後期的發展走向,比如說項目的後續的維護成本;後續相關生態鏈的建設;未來技術人員的數量等等。因此在做技術選型的時候需要謹慎再謹慎。因此我們要從多方面因素進行考慮技術選型:

  • 項目因素: 明確現在項目的規模、重要程度。 項目的需求(特別是非功能性需求)也會限制技術的選型
  • 團隊因素: 考慮團隊的因素,也就是人的因素,考慮團隊人員的技術組成。 考慮招聘的因素,對於特別小眾的技術,可能會因為招不到人而影響到對公司的業務支援。
  • 技術因素: 技術特性考慮(易用性、可維護性、可擴展性、性能等)、技術成熟度、社區活躍度、架構匹配和演化等。 github上的star數,可以作為一個重要的參考。

上面列了在選型過程中我們要考慮的因素,那麼實際中我們應該怎麼去進行技術選型呢?

  1. 首先明確選型的需求和目的,最好能列出必須要考慮的各種因素以及評判標準。
  2. 找候選技術和產品。這時範圍可以盡量的廣一些,搜集儘可能多的候選技術和產品。
  3. 初步篩選。把一些由於各種限制無法選擇或者明顯不可能的技術或產品排除,篩選3個左右備選方案。
  4. 做一些詳細的調查和分析。可以列個技術選型分析表(小的不太重要的技術選型不一定要這麼麻煩,而重要的技術選型則可能要反覆各個步驟多次)

考慮因素

選型A

選型B

選型C

項目因素

     

團隊因素

     

技術因素

     

那麼在選型過程中需要注意些什麼的?

  • 一定要進行可行性分析,如果不太確定,做個Demo驗證一下,如果項目進行到一半,發現原來設想的方案不可選,那會是非常痛苦和浪費時間的事情。
  • 不要有思維定式,也不要趕時髦。舉個例子,我就想要一個很簡單的活動頁面,就純粹的展示頁面,你這邊告訴我,需要搭建一個構建平台,在引入一堆的庫,什麼vue,axios等等……結果功能用一天就不用了。看起來很時髦,很不錯,但是完全沒有必要。
  • 隨著業務發展,很多架構需要不斷升級,所以一定要考慮未來如果替換某項技術,是否會很麻煩。可以選擇一些標準技術或產品,或者在應用中部署一個適配層,方便未來適配其他技術,自由插拔。
  • 架構應該儘可能統一,一個領域避免引入太多相同功能的技術產品。

對於前端這邊的技術選型來說,我們需要做以下的方面的操作:

  1. 確定我們的項目的架構方案,是走純粹的靜態頁面部署呢還是走服務端渲染(SSR);
  2. 在確定好大體的架構方案的的前提下,我們需要做基礎框架的選擇,是選擇vue、還是react、還是angular呢,這樣的選擇直接影響到了我們整個團隊的未來的技術棧的構建;
  3. 選擇完基礎框架後,前端就是選擇UI框架,是使用現有的UI框架呢還是,需要我們自己開發一套屬於自己的UI框架;
  4. 接著我們要考慮使用模組化載入處理方,這個包括CSS的載入處理方案和JS的載入處理方案。對於CSS的預處理方案有SCSS,Less等可以進行選擇);對於JS的預處理方案我們可以使用ES6+babel的方案還是使用TS的處理方案等等。
  5. 接著就是一些基礎庫的選擇,比如說工具類庫的lodash,ajax請求庫axios,時間處理庫dayjs,圖表組件echarts等等。

做完技術選擇之後,說明我們的前端的工程化建設的腳步的第一步已經邁出去了。接下來就是在此基礎上進行的我們後續的建設了。

開發規範設計

談起開發規範,我想想這個是每個程式設計師頭疼的事兒。當我們接手一個人的項目看到亂遭的程式碼是不是就會瞬間沒有看下去的慾望。古人云「無規矩不成方圓」,開發過程中如果沒有規範,只能讓我們的屎山越堆越高,後期越來越難維護。可見規範的重要性。始皇帝初統六國即「書同文車同軌」,規範意味著標準,是團隊的共識,是溝通協作的基礎。對於規範的最基本的載體就是文檔,我們要根據不同的內容,制定不同的規範文檔:

 

 

 

 

 

 

 

 

 

 

 

當然對於規範的制定是需要跟團隊成員一起進行討論約定的,以達到組內大家的共識,這樣大家才會願意去執行。既然規範出來了,那就應該大家去遵守,如果規範制定出來之後,大家都不去執行,那麼規範也就成了擺設,那制定規範的意義就完全沒有了。當然也有些時候我們制定了規範可能由於疏忽等其他方面的原因,而沒有遵循規範,那總得有個檢查的辦法是吧,這個時候,就需要我們要應對規範實現一定的校驗規則:

比如說git規範,我們可以通過githook來在提交之前對提交的內容進行校驗,以及分支的創建進行校驗什麼的;再比如我們都知道ESLint吧,其實就是對程式碼個是的規範的一個校驗等等。在規範實施的過程中,我們可以使用一定的技術手段,來對部分的規範進行約束。當然可能也會有人覺得搞那麼多的規範,就很影響工作效率,其實不然,所謂的影響開發效率,只是在剛開始接觸的時候會有這種感覺,因為不適應,總得需要有一個適應的過程。一旦當你完全適應了這些規範的話,就會覺得真香。只要規範統一了,標準統一了,對後期的程式碼維護,以及功能開發是有很大的幫助的。

在各種規範中,這裡單獨將數據規範單獨拎出來強調一下,因為數據的規範可能會直接影響我們前端通用組件,以及通用的工具類的封裝。舉個例子:當我們在封裝介面請求工具的時候,對於登錄失敗的這種數據的通用處理邏輯應該設計,如果後端關於登錄失敗,返回的錯誤碼沒有一個統一的標準,那前端在處理用戶非登錄的介面請求就沒有辦法進行一個統一的封裝,就沒有辦法做到統一封裝;再比如說,某些組件外觀一樣,交互邏輯一樣,但是後端返回的數據欄位名稱不一樣(曾經我呆過的一家做酒店相關係統的公司,關於酒店有些人用的chain,有些人用的是hotel,就導致很多通用的組件沒辦法進行統一的封裝,或者是封裝好了之後,要根據後端的返回的介面數據欄位,再重新處理一下數據格式)。

項目的搭建和開發

對於項目的搭建和開發了流程這一步,可以說是整個前端工程化的一個非常關鍵的內容,畢竟這個跟我們的前端開發是息息相關的。這一個過程的建設也是整個團隊開發工作流的重中之重。這一步我們需要做的的內容其實包含很多的:

  • 模組化處理方案:模組化處理方案主要包括有css的預處理和js的預處理,以及載入方案。對於css的預處理不管是scss還是less都是能夠提高我們前端的開發效率的;而JS的處理方案,可以使用ES6 + babel,還有Flow,或者是TypeScript等方案處理。對於其載入,JS我們常見的有CMD,AMD,CommonJS以及ESModule的載入方案,要根據不同的的瀏覽器的兼容性,來進行選擇。目前大多數的前端項目是基於webpack來進行開發的,雖說還有別的項目,比如說基於ESModule的vite等等。
  • 組件化開發:主要就是我們平時項目中的基礎組件,包括基礎的UI組件(目前我們基本上使用的都是現有的UI框架):如搜索框,對話框,list,樹形結構等,這些元素可以說是構成頁面的基礎,也就是最原子的東西。我門所有的頁面就是通過使用這些最原子的內容,來進行一步的拼裝而成的。
  • 模組化開發:對於很多的前端來說對於模組和組件的概念很容弄。我理解的,其實模組也屬於組件的一種,但是模組是具有獨立功能的組件。就比如說一個頁面的登錄模組、用戶的基本資訊模組等等。
  • 通用組件倉庫:對於前端也有相對應的包管理工具npm(當然,現在還有別的一些包管理工具,比如說yarn,pnpm等等)。對於一寫我們自己開發的,適用於自己公司內部的一些組件或者是一些通用的工具類庫,我們也希望有一個自己的託管平台,因此,需要自己搭建自己的npm私服。並且將內部的一些通用組件進行託管。
  • 開發工具:這裡所說的開發工具不一定指前端的編輯器。因為我么在開發過程中需要創建項目,創建組件,創業介面扥等一系列的東西,因此在三大框架中就應運而生了各自的cli工具,比如說,react使用的是react-create-app,vue的vue-cli,以及angular的angular-cli工具。這些工具為我們的項目創建,構建,格式校驗等提供了不小的便利。
  • 項目的構建和部署流程:目前我們使用的前端工具cli工具基本上都是支援我們將我們的項目進行打包,當然,這些也僅僅是打包出來的是官方提供的解決方案的內容。都是能夠將我們的項目進行打包,但是遠遠還不滿足我們的CI/CD的需求,因此要建立的完整的CI/CD流程就首先需要我們規範我的構建和部署流程,然後在此基礎上去進行開發的我們的CI/CD的流程化工具(目前的Jenkins雖說能夠做到一部分的CI/CD的工作,但是要想實現符合自己的企業內部的CI/CD的,還是需要自己做一部分的內容的開發)。
  • 性能優化方案:前端性能優化的問題是一個經久不衰的問題,在不同的應用場景以及不同的項目中,所出現的應用瓶頸時不一樣的。比如說2C的前端項目中,我們可能更加的看重的是用戶的首屏載入,用戶的擺平時間,以及用戶的交互響應時間等等;在2B的項目中坑出現性能的瓶頸問題的場景就更多了,比如說大數據的載入與渲染等等。但是針對於不同的項目來說,這個性能優化方案應該是在項目開發之初就有所預知,然後進行設計方案,這些也將直接影響到整個前端工程化的建設。
  • 自動化測試方案:測試是在開發過程中必不可少的。而自動化測試則能夠減少人肉測試,提高程式碼品質等等。前端常見的自動化測試工具有很多,不管選擇哪個都不會有太大的問題。
  • Code Review:對於開發者而言,每一行程式碼其實都應該具備起存在的意義。況且人不是機器,是很容犯錯的,有些時候我們開發的問題, 是在測試過程中復現不了的,以及我們的程式碼規範約定的內容,在有些同學開發過程中有些時候沒有注意等等。而Code Review恰恰對這些問題提供一個很好的解決方案。面向小黃鴨的變成,其實就是Code Revew的一種變種。

介面數據的mock

在實際的項目開發過程總,我們會經常遇到如下的尷尬場景:

  • 前端開發依賴於後端的介面數據,但是後端人員不足,或者是無法到位,或者是介面正在開發中,就會造成應該提供數據的介面未開發完成,前端這邊很多的操作又依賴於介面的數據,導致前端這邊的開發工作受阻,造成前端處於一個放空的階段。
  • 我們要寫前端的項目文檔,但是文檔中的某些組件的示例是依賴於後端數據的,但是後端的服務未啟動或者是其他的原因,介面不能夠進行正常的訪問;還有部分的功能是一個完整的流程,流程走過了前端數據的的狀態就改變了,如果我們還希望走這樣流程,就需要從頭開始進行構建數據造成不必要的時間的浪費。
  • 對於前端開發,如果需要做前端自動化測試,依賴於數據的部分應該怎麼去做,自動化測試返回結果不能夠判斷是後端數據的問題還驗證前端的問題的(因為結果是不確定的),而自動化測試的結果一定是確定字後才能夠進行的。這樣就需要數據的可靠性,可預知性。

基於上述的場景,就需要我們有一套前端的數據的mock環境,用來mock我們的介面數據(當然這些是基於介面的數據格式跟後端夥伴約定好的前提下進行的)。這就有一個要求就是我們能否通過介面的文檔直接生成mock的數據的工具。這裡推薦一個不錯的介面文檔工具「YAPI」(//hellosean1025.github.io/yapi/),這個工具不僅支援介面文檔的輸出,還能夠在在介面文檔上面直接進行mock數據,非常方便。如果說這樣的工具和自家的工程化工具的結合的不甚好的話,也可以自己進行開發,這裡推薦一個叫做的mockjs的工具,用來進行生成mock數據。

項目的打包發布

前端的項目開發完成了,如果不進行打包發布,就是在耍流氓。對於前端的項目的打包發布這件事情其實貫穿在我們項目開發的整個過程中,從最初的開發、聯調、再到測試以及最後的上線交付,都包含有打包和發布的過程。打包發布其實是一件重複,枯燥沒有技術含量,並且很容易出錯的事情。針對於這種情況,程式設計師就創造了自動化的大包發布工具。當然對於對於前端來說,也同樣的存在這樣的一個過程。

我們前端項目的打包發布是基於我們整體的前端項目的架構方案進行的,比如說前後端分離架構方案、性能優化方案、靜態資源的存放位置、載入方案、以及部署方案都是我們這個階段要考慮的問題。然後就是我們前端的CI/CD的方案設計,流程規劃以及CI/CD的載體選擇和功能開發。

後期的項目維護

項目上線了,不代表就萬事大吉了。項目存不存在在測試階段沒有測試到的bug或者是場景;項目的是否能夠穩定運行,項目在用戶端的使用是否流暢等等一系列的問題。面對這樣的問題我們應該如何能夠發現,以及在用戶遇到這樣的問題,能不能有一個回饋等等。相對於後端項目來說,前端的監控相對來說是比較困難的,畢竟要將很多的操作放在用戶的設備上進行,然後需要將監控收集的數據進行上報,這個過程中,用戶端上報過程都可能出現問題,因此這個上報的數據是可能不會很準確。即使這些數據不是很準確,但是也能夠客觀地反映出一些問題。因此前端的監控是非常有必要的。而且目前個大平台都在推出自己的前端監控平台,可見前端監控對於前端開發來說是有多麼的重要。

小結

以上就是我個人對於前端工程化的理解,可能理解的比較片面,但是隨著工作時間的不斷的增加,以及科技技術的發展,我相信未來的前端行業會面臨著更大的挑戰,而前端工程化的內容,也將會不斷的跟著時代的發展而快速的發展。