<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                > 原文出處:https://github.com/fouber/blog/issues/4 > 作者:[fouber](https://github.com/fouber) 目錄 [TOC] 本文最先發表在?[DIV.IO](http://div.io/)?- 高質量前端社區,歡迎大家圍觀 > 不要再求驗證碼了,這個blog目前有800+人訂閱,求驗證沒什么的很影響其他訂閱者,可以在div.io上申請,定期會有同學發放的。。。 * * * 一直醞釀著寫一篇關于模塊化框架的文章,因為模塊化框架是前端工程中的?`最為核心的部分`?。本來又想長篇大論的寫一篇完整且嚴肅的paper,但看了?[@糖餅](https://github.com/aui)?在?[DIV.IO](http://div.io/)?的一篇文章 《[再談 SeaJS 與 RequireJS 的差異](http://div.io/topic/430)》覺得可以借著這篇繼續談一下,加上最近spm3發布,在seajs的官網上又引來了一場?[口水戰](https://github.com/seajs/seajs/issues/454)?,我并不想參與到這場論戰中,各有所愛的事情不好評論什么,但我想從工程的角度來闡述一下已知的模塊化框架相關的問題,并給出一些新的思路,~~其實也不新啦,都實踐了2多年了~~。 > 前端模塊化框架肩負著?`模塊管理`、`資源加載`?兩項重要的功能,這兩項功能與工具、性能、業務、部署等工程環節都有著非常緊密的聯系。因此,模塊化框架的設計應該最高優先級考慮工程需要。 基于?[@糖餅](https://github.com/aui)?的文章 《[再談 SeaJS 與 RequireJS 的差異](http://div.io/topic/430)》,我這里還要補充一些模塊化框架在工程方面的缺點: 1. requirejs和seajs二者在加載上都有缺陷,就是模塊的依賴要等到模塊加載完成后,通過靜態分析(seajs)或者deps參數(requirejs)來獲取,這就為?`合并請求`?和?`按需加載`?帶來了實現上的矛盾: * 要么放棄按需加載,把所有js合成一個文件,從而滿足請求合并(兩個框架的官方demo都有這樣的例子); * 要么放棄請求合并,請求獨立的模塊文件,從而滿足按需加載。 2. AMD規范在執行callback的時候,要初始化所有依賴的模塊,而CMD只有執行到require的時候才初始化模塊。所以用AMD實現某種if-else邏輯分支加載不同的模塊的時候,就會比較麻煩了。考慮這種情況: ~~~ //AMD for SPA require(['page/index', 'page/detail'], function(index, detail){ //在執行回調之前,index和detail模塊的factory均執行過了 switch(location.hash){ case '#index': index(); break; case '#detail': detail(); break; } }); ~~~ 在執行回調之前,已經同時執行了index和detail模塊的factory,而CMD只有執行到require才會調用對應模塊的factory。這種差別帶來的不僅僅是性能上的差異,也可能為開發增加一點小麻煩,比如不方便實現換膚功能,factory注意不要直接操作dom等。當然,我們可以多層嵌套require來解決這個問題,但又會引起模塊請求串行的問題。 * * * > 結論:以純前端方式實現模塊化框架?**不能**?同時滿足?`按需加載`,`請求合并`?和?`依賴管理`?三個需求。 導致這個問題的根本原因是?`純前端方式只能在運行時分析依賴關系`。 ## 解決模塊化管理的新思路 由于根本問題出在?`運行時分析依賴`,因此新思路的策略很簡單:不在運行時分析依賴。這就要借助?`構建工具`做線下分析了,其基本原理就是: > 利用構建工具在線下進行?`模塊依賴分析`,然后把依賴關系數據寫入到構建結果中,并調用模塊化框架的?`依賴關系聲明接口`?,實現模塊管理、請求合并以及按需加載等功能。 舉個例子,假設我們有一個這樣的工程: ~~~ project ├ lib │ └ xmd.js #模塊化框架 ├ mods #模塊目錄 │ ├ a.js │ ├ b.js │ ├ c.js │ ├ d.js │ └ e.js └ index.html #入口頁面 ~~~ 工程中,`index.html`?的源碼內容為: ~~~ <!doctype html> ... <script src="lib/xmd.js"></script> <!-- 模塊化框架 --> <script> //等待構建工具生成數據替換 `__FRAMEWORK_CONFIG__' 變量 require.config(__FRAMEWORK_CONFIG__); </script> <script> //用戶代碼,異步加載模塊 require.async(['a', 'e'], function(a, e){ //do something with a and e. }); </script> ... ~~~ 工程中,`mods/a.js`?的源碼內容為(采用類似CMD的書寫規范): ~~~ define('a', function(require, exports, module){ console.log('a.init'); var b = require('b'); var c = require('c'); exports.run = function(){ //do something with b and c. console.log('a.run'); }; }); ~~~ ## 具體實現過程 1. 用工具在下線對工程文件進行掃描,得到依賴關系表: ~~~ { "a" : [ "b", "c" ], "b" : [ "d" ] } ~~~ 2. 工具把依賴表構建到頁面或者腳本中,并調用模塊化框架的配置接口,`index.html`的構建結果為: ~~~ <!doctype html> ... <script src="lib/xmd.js"></script> <!-- 模塊化框架 --> <script> //構建工具生成的依賴數據 require.config({ "deps" : { "a" : [ "b", "c" ], "b" : [ "d" ] } }); </script> <script> //用戶代碼,異步加載模塊 require.async(['a', 'e'], function(a, e){ //do something with a and e. }); </script> ~~~ 3. 模塊化框架根據依賴表加載資源,比如上述例子,入口需要加載a、e兩個模塊,查表得知完整依賴關系,配合combo服務,可以發起一個合并后的請求: [http://www.example.com/??d.js,b.js,c.js,a.js,e.js](http://www.example.com/??d.js,b.js,c.js,a.js,e.js) ## 先來看一下這種方案的優點 1. 采用類似CMD的書寫規范(同步require函數聲明依賴),可以在執行到require語句的時候才調用模塊的factory。 2. 雖然采用CMD書寫規范,但放棄了運行時分析依賴,改成工具輸出依賴表,因此?`依賴分析完成后可以壓縮掉require關鍵字` 3. 框架并沒有嚴格依賴工具,它只是約定了一種數據結構。不使用工具,人工維護`require.config({...})`?相關的數據也是可以的。對于小項目,文件全部合并的情況,更加不需要deps表了,只要在入口的require.async調用之前加載所有模塊化的文件,依賴關系無需額外維護 4. 構建工具設計非常簡單,而且可靠。工作就是掃描模塊文件目錄,得到依賴表,JSON序列化之后插入到構建代碼中 5. 由于框架預先知道所有模塊的依賴關系,因此可以借助combo服務實現`請求合并`,而不用等到一級模塊加載完成才能知道后續的依賴關系。 6. 如果構建工具可以自動包裝define函數,那么整個系統開發起來會感覺跟nodejs非常接近,比較舒服。 ## 再來討論一下這種方案的缺點 由于采用require函數作為依賴標記,因此如果需要變量方式require,需要額外聲明,這個時候可以實現兼容AMD規范寫法,比如 ~~~ define('a', ['b', 'c'], function(require, exports, module){ console.log('a.init'); var name = isIE ? 'b' : 'c'; var mod = require(name); exports.run = function(){ //do something with mod. console.log('a.run'); }; }) ~~~ 只要工具把define函數中的?`deps`?參數,或者factory內的require都作為依賴聲明標記來識別,這樣工程性就比較完備了。 但不管怎樣,?`線下分析始終依靠了字面量信息`,所以開發上可能會有一定的局限性,但總的來說瑕不掩瑜。 > 希望本文能為前端模塊化框架的作者帶來一些新的思路。沒有必要爭論規范,工程問題才是最根本的問題。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看