摘要:框架加冕時代年橫空出世的前端框架的模塊機制的模塊機制相比老王老李的解決方案上增強了模塊的約束性,和幫助開發者劃分模塊外,最重要的是解決了模塊的運行時管理問題模塊的初始化順序問題和依賴的模塊自動初始化問題。
前端框架工程化之路
人類的發展動力源于一個“懶”字,就如現在的大前端正是史前那群“懶”而聰明的“切圖仔”進了軟件工程的施工現場,懷揣著更少代碼、更少溝通、更少錯誤、更少維護的夢想奔襲而來。從框架齊放鬧革命到三大框架三足鼎立,從構建工具爭鳴到Webpack一統江湖,從Javascript 遵循ES5長達7年統治到向ES6的自我進化。前端的發展與它們的成功都離不開一個“術”,工程化。
模塊的進化 在沒有框架的史前我們面臨的問題:
1.全局變量污染:各個文件的變量都是掛載到window對象上,污染全局變量。
2.變量重名:不同文件中的變量如果重名,后面的會覆蓋前面的,造成程序運行錯誤。
3.文件依賴順序:多個文件之間存在依賴關系,需要保證一定加載順序問題嚴重。
于是老王想出使用自執行函數的方法去解決問題
var foo = (function(cNum){ var aStr = "aa"; var aNum = cNum + 1; return { aStr: aStr, aNum: aNum }; })(cNum);
前端最初始的模塊誕生了,這個模塊有問題嗎?有!雖然模塊內部的變量對全局不可見了,但暴露出來的foo是一個全局變量,這樣的模塊多了全局變量也會很多。
老李在老王的辦法基礎上添加命名空間去解決問題:
app.util.modA = xxx; app.common.modA = xxx; app.tools.modA.format = xxx;
除了寫法丑陋外,這樣的模塊約束力極低,很容易遭到不遵守的開發者破壞,需要開發者有一定的劃分不同模塊的能力,更大的問題是需要人為的解決模塊加載、初始化等管理問題。
框架加冕時代2009年橫空出世的前端框架Angularjs的模塊機制
angular.module("ConfigModule").service("TextConfig", function () { this.headerText = { }; }); angular.module("HeaderModule", ["ConfigModule"]).controller("HeaderCtr", ["$scope", "TextConfig", function ($scope, textConfig) { $scope.headerText = textConfig.headerText; }]);
Angularjs的模塊機制相比老王、老李的解決方案上增強了模塊的約束性,和幫助開發者劃分模塊外,最重要的是解決了模塊的運行時管理問題(模塊的初始化順序問題和依賴的模塊自動初始化問題。再被多個模塊依賴的情況,模塊僅且只加載一次的問題,統一的輸入輸出api問題)。看似完美的方案,但仍有問題。
構建工具輔政Angularjs的模塊機制只解決了運行時管理問題,但沒有解決模塊加載管理問題。這讓使用者不得不去鏈式在頁面引用模塊文件。所以在那個時候出現了一些構建工具與相應的插件來幫助我們 比如Gulp、Grunt、插件 Browserify。
實際上Angularjs的模塊機制也只是一定程度的解決了運行時管理問題,了解的同學應該知道在Angularjs里做模塊異步懶加載是件非常困難的事情。在Angular 2及以上版本加入了動態加載模塊的支持。其它框架,例如Vue組件(這里暫且把Vue的組件當作模塊看待,后面會進行區分)也加了相應的支持, 這得益于框架的組件或模塊的factor機制的支持和Webpack code splitting功能的支持。
const foo = resolve => { require.ensure(["./Foo.vue"], () => { resolve(require("./Foo.vue")) }) } const router = new VueRouter({ routes: [ { path: "/foo", component: Foo } ] })一直在接近,但從未實現的組件化
前面談模塊化發展中談到了Vue的組件,組件是一種模塊,但又超越模塊。模塊是邏輯單元的封裝,讓開發及維護成本更低。那么組件則是更高一層的抽象,是一個業務單元的封裝,能夠獨立運行的軟件單元。組件需要解決的問題:隔離、去污染問題(模塊解決的隔離只限于js變量的隔離、而組件還需要解決css的隔離)、狀態管理問題、與其它組件通訊問題,生命周期問題,一個好的組件設計還需要遵循軟件設計的一些原則。
不得不改源碼的Jquery組件我們先來看看Jquery的年代組件長什么樣? 以前的代碼一般是用自執行函數作為一個類,這里為方便理解,我用TS展示一下。
export class component { selector:Element; options:any static defaultOption = { "color": "red", "fontSize": "16px", "textDecoration":"none"} constructor(selector,opt) { this.selector = selector; this.options = $.extend({}, this.defaultOption, opt) } highlight () { return this. selector.css({ "color": this.options.color, "fontSize": this.options.fontSize, "textDecoration": this.options.textDecoration }); } }
組件使用者拿到這個組件并初始化,根據組件上層的一些交互,調用組件方法,改動組件內部。 我們可以看到組件上層依賴這個組件,且依賴的是highlight()的具體實現。根據OCP原則,對擴展開放,對修改關閉。當我們需求變化時,比如我們的highlight需要把背景色改一下,只能對組件內部邏輯做修改。很顯然這樣的組件不是一個好設計。
數據驅動讓組件高可用性進入有前端框架的時代,Angular使用數據驅動改變視圖的狀態,這是很大的一個進步,數據驅動解耦了組件外層對組件的依賴關系,將真正的依賴拋向外層的傳給組件的數據(有點類似依賴倒置的意思),組件內部負責根據數據的變化改變UI狀態。(React Virtual DOM 驅動視圖實際也是一種數據驅動,只是一個是找到數據最小粒度的變化直接改動對應的視圖,一個是數據生成Virtual DOM找到最小粒度的Virtual DOM變化,改動對應的視圖。本質上都是數據驅動視圖)。
數據驅動視圖解耦了組件與組件的依賴問題。但同時引入了一個問題,狀態混亂問題。寫過Angularjs的同學應該知道狀態混亂之痛,當我們在Angularjs的多個組件依賴同一份數據時,當一個組件樹中某一個組件將該數據更改時,整顆組件樹中使用該數據的組件都會跟著共振。但實際情況是,樹當中有一部分組件不需要跟著某一次的數據變化而變化。
React、Angular使用Immutablejs強化單向數據流。這的確減輕了復雜度,但這種方式對于子組件想通過狀態變更驅動父組件、兄弟組件變化的情況,只能通過注冊事件通知的形式。首先這種形式會違背隔離性,有很高的耦合,組件內部必須知道外部想要知道我會有什么變化,預留訂閱的鉤子。其次對于一顆組件樹跨了N層,極端點從葉子節點到根節點這樣一個通知在每層訂閱子組件事件,會顯得非常不合理。
于是衍生的一些Flux Redux庫的狀態集中式托管,讓一個組件的數據驅動視圖的變化,可以來源于任何一個組件樹節點,又不會讓變化成復雜的網狀拓撲結構,而是成星型拓撲結構。
這個發展過程實際也是為了解耦合,讓組件更加獨立,就好似以前一個人的每一個日常活動都推送出去讓全人類知道,由于日常太過苦逼影起社會負面情緒暴增,影響太大了(無單向數據流的情況)。于是乎改為在推送前,大家先訂閱建立關系,建立關系則推送,大家發現這套太麻煩了,需要個體知道別人關心我哪個日常活動,家人想知道我吃的什么我建立一個曬圖發布方式,領導想知道工作情況,我建立一個寫周報發布方式,于是乎我不停的改變自己適應社會(這就是一種耦合,單向數據流方式)。當個體喪失人性后,終于想到了一個更好的辦法,做自己該做的事,把這種拔內褲的事情交給社會,我在辦公室就給我采集認真工作的照片,系統讓領導看還是讓其它同事看作為個體的我不需關心。我在吃大餐的時候你采集照片,系統要給哪些聯系人,這由我此刻處的環境下社會關系決定。這個系統就是狀態管理器,這個社會就是組件所處的環境。
組件進化之殤組件的進化從未停下腳步,例如css隔離問題從依靠項目wiki中制訂css命名規范到css Modules自動化解決css隔離問題。從Angularjs的混亂的網狀狀態管理到React、Angular使用Immutablejs強化單向數據流、和衍生的一些Flux Redux庫的狀態集中式托管。從Vue的簡單生命周期到2.0加入keep-alive、activated、deactivated使生命周期的增強。組件的發展一片欣欣向榮,但為什么我仍認為還沒有實現組件化呢?
框架的出現讓組件擁有了其應該有的特性,讓開發者無需再重復造輪子解決這些問題。但也引入了新的問題,組件的獨立性。
前面提到組件應當是一個獨立運行的軟件單元。而實際的情況是,組件只是在某框架體系下獨立運行的軟件單元。而工程化也是一個去底層服務的趨勢,我們可以看看近年的Docker技術、云服務的Serverless概念,都強調其無需關注底層執行環境,想象一下如果某天我們開發一個頁面無論采用任何技術架構與框架,都只需引入一個個Custom Element,把DOM Attribute作為API(或者拿著各團隊發布的在線運行的一個組件地址),去組裝頁面即可。這就是近幾年前端的一個研究課題微前端技術。目前的微前端技術也有不錯的發展,利用Custom Element的實現方案,解決了一些基本的問題,如前面提到的:隔離性、狀態管理、通訊問題、生命周期問題、不依賴前端架構體系問題。但作為能獨立服務端部署提供使用的一個component還有很多問題待解決,但這是一個組件化發展的方向。
這是一個不錯的微前端實現方案 https://micro-frontends.org/
工程化的烏托邦——規范化規范是工程的施工藍圖,保證產出的產品穩健和易維護。如果沒有規范我們改一行代碼可能出現這樣的情況。
那是不是有了規范文檔,就好了?在趕著上線的高壓、高疲勞下狀態,可能出現這樣的同事。
我們前面已經提到過一些古老“法典”,如Jquery時代模塊定義的規則、css規范的規則,還有前面沒提到的項目結構劃分、代碼書寫規范。 大家有沒有發現它們都在歷史的舞臺中消失或者說們不必在為規范的實現耗費精力。為什么?當一個“法典”的受管控者和執法者都是自身的時候,那法典也就成了空談。所以我們需要一個公正的執法者——機器(自動化)。
終會讓項目wiki消失的自動化代碼規范,我們擁有jslint幫我們校驗,有編輯器插件幫我們根據規范自動格式化。
項目結構,我們有對應的CLI幫我們生成。
模塊的定義,我們有框架幫助劃分解決運行時問題,有Webpack幫助解決加載問題,等等。
自動化并非真正讓規范消失,而是對規范的更加強制化和易實施化,達到“無約”自制的效果。
那些wiki里規范讓開發者要怎么怎么寫代碼的文章我覺得大可不必,話說:“能動手的不BB,能自動化的不文檔”。
而對于項目wiki里那些讓開發者如何與其它人合作寫代碼的文檔我也覺得大可不必。比如:我們與后端如何對接,我們可以使用YAPI這類工具,讓前后端對接口定義及數據結構一目了然和保持實時穩定性。
對于前端與前端之間如何互相調用模塊或組件,我們可以利用Typescript,讓模塊組件接口更加清晰和強類型帶來的穩定性。
對于強類型帶來的其它好處我舉個例子:
這個是我寫無ts的vue項目時一個很低級的bug
export default { props: {}, data() { return { isFullscreen: false; } }, methods: { toggle() { this.isFullScreen = true; } } }
看似是個大小寫問題,但完全是可以避免,如果這個組件是個強類型,IDE(支持ts的)會推斷this類型,該字段是否聲明過給予校驗提示。這個是書寫上的帶來的好處。強類型還給我們帶來很多好處與方便,比如可以很快的了解一個模塊提供的API。可以在多模塊引用同一個數據時,某個時期對該數據結構進行一定調整后,能立刻知道那些陳舊的代碼哪些需要隨著這次改動一起調整等等。
除此之外TS還能在自動化文檔上起到輔助作用。我們可以看一下Angular的文檔自動生成工具有多棒~
https://compodoc.github.io/co...
demo: https://compodoc.github.io/co...
當我們站在巨人的肩膀上時,從未覺得向前走一步是如此輕松...愿,未來的前端走得更輕松。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/53550.html
摘要:框架加冕時代年橫空出世的前端框架的模塊機制的模塊機制相比老王老李的解決方案上增強了模塊的約束性,和幫助開發者劃分模塊外,最重要的是解決了模塊的運行時管理問題模塊的初始化順序問題和依賴的模塊自動初始化問題。 前端框架工程化之路 人類的發展動力源于一個懶字,就如現在的大前端正是史前那群懶而聰明的切圖仔進了軟件工程的施工現場,懷揣著更少代碼、更少溝通、更少錯誤、更少維護的夢想奔襲而來。從框架...
某熊的技術之路指北 ? 當我們站在技術之路的原點,未來可能充滿了迷茫,也存在著很多不同的可能;我們可能成為 Web/(大)前端/終端工程師、服務端架構工程師、測試/運維/安全工程師等質量保障、可用性保障相關的工程師、大數據/云計算/虛擬化工程師、算法工程師、產品經理等等某個或者某幾個角色。某熊的技術之路系列文章/書籍/視頻/代碼即是筆者蹣跚行進于這條路上的點滴印記,包含了筆者作為程序員的技術視野、...
摘要:一步,兩步,三步四步五步,就這樣到達了人生的巔峰傳統前端生態初級不使用打包中間處理工具,手工處理圖片等資源掌握以下知識點基礎結構,基礎樣式,基礎語法框架,系列插件框架,等基礎插件,等其他移動端適配,瀏覽器兼容,瀏覽器調試等恭喜完成新手村修 一步,兩步,三步四步五步,就這樣到達了人生的巔峰~ 傳統前端生態-初級 不使用打包、中間處理工具,手工處理js、css、圖片等資源 掌握以下知識點:...
閱讀 4293·2021-09-24 09:47
閱讀 1184·2021-09-03 10:33
閱讀 2063·2019-08-30 11:13
閱讀 1029·2019-08-30 10:49
閱讀 1753·2019-08-29 16:13
閱讀 2046·2019-08-29 11:28
閱讀 3089·2019-08-26 13:31
閱讀 3631·2019-08-23 17:14