一、webpack原理+步驟
模塊函數(shù)是webpack能處理的最小單位,對應打包前的一個文件,具體格式是:function(module)
webpack的工作原理:
webpack為每個require的資源生成一個唯一的moduleId,這樣在打包的時候,即使多處引用了某資源,也只會打包一份,而不會重復打包。最后打包生成的chunkId,作用是在加載的時候,防止重復加載的模塊,優(yōu)先取緩存。
1、全局注冊一個啟動函數(shù)window.webpackJsonp(chunkIds,modules,立即執(zhí)行的moduleIds)
2、打包后生成的每個chunk都是 webpackJsonp([1], [,,,,(function(module, exports, __webpack_require__){...}),,], [58]) 這樣的格式:
第一個參數(shù)是當前chunk的id,以及當前chunk依賴的chunkIds,
第二個參數(shù)是打包到當前chunk的模塊函數(shù),所有chunk的第二個參數(shù)長度應該是一樣的,因為為了防止模塊重復加載,所以模塊id都是唯一的,比如:某次打包一共有2個chunk、15個module,模塊0-9打包到chunk0下,則chunk0的第二個參數(shù)的0-9都是模塊函數(shù)對象,而chunk1的第二個參數(shù)的0-9則是空,其10-14又是具體的模塊函數(shù)對象
第三個參數(shù)是當前chunk加載完成后 立即執(zhí)行的模塊id,一般入口chunk都是有第三個參數(shù)的。
3、全局webpackJsonp執(zhí)行的過程中,會記錄下已經(jīng)加載過得chunk和模塊以及所有的模塊函數(shù)對象,分別保存在installedChunk、installedModule和modules對象中,每次訪問某個chunk或者模塊時,優(yōu)先讀取緩存,提高性能。
4、__webpack_require__函數(shù)是用于讀取模塊的。
webpack具體的打包流程是:
1、利用optimist整合webpack.config.js和命令行中的所有參數(shù),生成options對象,傳入webpack webpack啟動,執(zhí)行run函數(shù)
2、生成compiler編譯對象:主要完成模塊的構建,包括依賴模塊的構建(AST依賴抽象樹),中間結合各種loaders\plugins來進行處理不同的資源,統(tǒng)一轉化成js模塊
3、構建完成后,根據(jù)配置進行代碼分割、提取、封裝
4、利用不同的模板:主入口模板mainTemplate、非入口模板chunkTemplate生成編譯打包后的文件(mainTemplate與chunkTemplate的區(qū)別在于帶不帶啟動代碼)
5、最后完成文件的輸出
webpack源碼分析---后續(xù)總結
webpack啟動后,創(chuàng)建compiler對象,開始compile,主要包含下面的幾步:
1、make -> build:(建立模塊,loader處理,分析依賴)分析配置的主入口,生成模塊對象,調用loaders處理成js模塊,構建AST抽象樹,分析模塊的依賴數(shù)組
2、seal:(封裝結果)封裝 根據(jù)模塊依賴關系+配置(如提取公共模塊)等,將所有的modules對象進行封裝,module分配進不同的chunk中;并輸出webpack模塊加載器(一段代碼:注冊webpackJsonp)
3、emit:(輸出文件)輸出 將最終的chunk文件輸出到配置好的輸出路徑下。根據(jù)chunk類型的不同,使用不同的模板生成最終的chunkjs
參考:
細說 webpack 之流程篇---淘寶前端團隊
這篇文章講了webpack的原理 其中manifest講的比較清晰
webpack熱更新原理(websocket貌似過時了):
1、利用html5的websocket協(xié)議,在客戶端和服務器端建立起一個長鏈接,當服務器端檢測到文件變化時,主動向瀏覽器端發(fā)起一個更新的消息,瀏覽器收到消息,判斷是css更新還是js、html更新以進行局部更新或者全局更新,從而減少開發(fā)者手動刷新瀏覽器的繁瑣。
【參考】
2、EventSource 是 HTML5 中 Server-sent Events 規(guī)范的一種技術實現(xiàn)。EventSource 接口用于接收服務器發(fā)送的事件。它通過HTTP連接到一個服務器,以text/event-stream 格式接收事件, 不關閉連接。通過 EventSource 服務端可以主動給客戶端發(fā)現(xiàn)消息,使用的是 HTTP協(xié)議,單項通信,只能服務器向瀏覽器發(fā)送; 與 WebSocket 相比輕量,使用簡單,支持斷線重連。
【參考】
loader的原理:
將各種不同類型的資源最終都整合成js模塊,以便webpack處理。
二、React的背景+原理:
傳統(tǒng)的web開發(fā)是從服務器接收到數(shù)據(jù),然后進行dom的更新,比如之前的jQuery方式,每次數(shù)據(jù)的更新,都需要獲取到dom元素,進行相應的增刪改操作。這種方式在頻繁的數(shù)據(jù)刷新下會導致性能問題,體驗很差。React的產(chǎn)生極大的解決了這個問題,它采用了虛擬dom算法,初次渲染生成一顆虛擬dom樹,每次收到新數(shù)據(jù)render前,將新數(shù)據(jù)下的dom樹和之前的dom樹進行對比,只將發(fā)生變化的部分進行dom更新,而且會將臨近的幾次dom更新進行合并處理,極大的避免了頻繁的dom更新導致的性能問題。
具體的dom diff算法關鍵點有:
- 對dom樹只進行同層的比較,秉承不同類型肯定是不同元素的原則,只要類型不同即替換整棵樹,后續(xù)的子節(jié)點不再進行比較,降低算法復雜度;
- 對于列表節(jié)點,使用key屬性,在每次渲染更新的時候,可以最大限度的進行dom元素復用;
三、redux相關
react等組件里面,都是以state、props等進行數(shù)據(jù)的存儲和傳遞的,要想讓幾個組件共享數(shù)據(jù),就只能在父級組件的state內存儲數(shù)據(jù),一級一級的向子組件傳遞。當項目很大、組件很多時,一級一級的傳遞就顯得很繁瑣。redux解決了這個問題,可以把redux理解成一個狀態(tài)機,是最頂層父級組件里的state,通過一些機制,可以直接通過mapStateToProps、connect將頂級state直接作為props傳遞給需要的組件。其中相關的概念有reducer同步改變數(shù)據(jù)、effect異步改變數(shù)據(jù)、action發(fā)起請求、dispatch等。
四、react router原理
底層利用history模塊實現(xiàn)。具體如何做到url與UI保持一致的:history監(jiān)測到url的變化,發(fā)起ajax獲取對應的component,實現(xiàn)UI的更新,同時進行url的替換,具體的底層是調用history.pushState、popState、replaceState等api實現(xiàn)瀏覽器前進、回退的。
【參考】