您好,登錄后才能下訂單哦!
這期內(nèi)容當中小編將會給大家?guī)碛嘘P(guān)web網(wǎng)頁模塊化的原因,以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
單個頁面中越來越多的Javascript。
在現(xiàn)代瀏覽器中你可以做越來越多的功能。
少量的全頁面刷新,以至于單個頁面中有更多的代碼。
正因為這些原因造成越來越多的代碼鑲嵌在瀏覽器端中。
這樣一個大的代碼倉庫(code base)急需做出相應的管理。正好,模塊化系統(tǒng)提供了這些功能分割你的代碼倉庫,把它們分割為一個個的模塊。
問題
網(wǎng)站逐漸轉(zhuǎn)化為Web apps
代碼復雜度逐漸提高
組裝變的困難
開發(fā)者想要分離的JS文件/模塊
部署時可以把代碼優(yōu)化成幾個HTTP請求
解決方案
前端開發(fā)者需要這樣的解決方案:一些這類的API #include/import/require有能力加載嵌套的依賴,對開發(fā)者來說易于使用,并且有優(yōu)化工具在后面支持,有助于部署。
腳本載入API
首先梳理出腳本載入API。這里有幾個選擇:
Dojo: dojo.require("some.module") LABjs: $LAB.script("some/module.js") CommonJS: require("some/module")
所有的都映射到載入 some/path/some/module.js。理想情況下,我們可以選擇CommonJS的語法,因為它很可能會變得更加常見,而且我們想要重用代碼。
當前我們也希望一些語法能夠載入已存在的純文本JavaScript文件,因此開發(fā)者不用重寫所有的JavaScript來從腳本載入中獲益。
但是,我們需要一些能在瀏覽器中更好的工作的事物。CommonJS 的require()是一個同步調(diào)用,它期望能夠立即返回那個模塊。不過這在瀏覽器中工作的不是很好。
異步與同步
下面這個例子說明了瀏覽器的基本問題。假設我們有一個Employee對象,我們想要一個派生自Employee對象的Manager對象。獲取該例子,我們可能會用我們的腳步載入API來這樣編碼:
var Employee = require("types/Employee");function Manager () { this.reports = []; }//Error if require call is asyncManager.prototype = new Employee();
如上面注釋中所示,如果require()是異步的,這段代碼不會工作。但是,在瀏覽器中同步載入腳步將會抹殺性能。那么,怎么辦?
腳本載入:XHR
使用XMLHttpRequest(XHR)載入腳本是很有吸引力的。如果使用XHR,我們就可以觸摸上面的文本,也就是可以通過正則表達式來查找require()調(diào)用,以確保我們載入了這些腳本,然后再用eval()或script元素將文本內(nèi)容傳給使用XHR載入的腳本。
使用eval()來評估模塊不太好:
開發(fā)者已經(jīng)被告知eval()不好用。
有些環(huán)境不支持eval()。
難以調(diào)試。Firebug和WebKit的檢查器有一個//@ sourceURL= 約定,用來給被評估的文本命名,不過這個特性不是所有的瀏覽器都支持。
不同的瀏覽器評估上下文環(huán)境是不同的。IE中的execScript或許可以做到,但是同時也意味著更多的移動部件。
使用帶文本內(nèi)容的script標簽來設置為文件文本也不太好:調(diào)試的時候,你得到的錯誤行號和源文件對不上號。
XHR 在跨域請求的時候還有問題。一些瀏覽器現(xiàn)在有跨域XHR的支持,但并不是全部。并且 IE 決定創(chuàng)建一個不同的API對象:XDomainRequest來實現(xiàn)跨域請求。出現(xiàn)了更多的需要改動的地方,更容易出錯。特別是,你需要確定不發(fā)送任何不標準的HTTPheader或者還需要另外一個"預檢"的請求來保證這次跨域的請求是被允許的。
Dojo 通過eval()使用基于XHR的loader,但是,雖然它能用,但是一直是困擾開發(fā)者的源頭。Dojo 有一個 xdomain loader但是它需要通過使用一個函數(shù)wrapper來修改require的模塊,所以script src=""標簽可以用來加載模塊了。還有很多邊界情況和變化的地方來給程序員增加困難。如果我們創(chuàng)建一個新的腳本加載器,我們可以做的更好。
腳本載入:Web Workers
web worker可能是另一個加載腳本的方法,但是:它的跨平臺性不好
它是一個消息傳遞API,并且該腳本可能要與DOM交互,它只是使用worker獲取腳本的文本,然后將文本回傳給主窗口,再用eval/script來執(zhí)行腳本。這種方法帶有上面提到的XHR的全部問題。
腳本載入:document.write()
document.write()可以用來載入腳本,它可以從其他的域載入腳本并且映射了瀏覽器通常是如何使用腳本的,因此它可以用來進行簡單的調(diào)試。但是,在異步VS同步的例子中,我們不能直接執(zhí)行腳本。理想情況下,在執(zhí)行腳本前我們能夠通過require()知道相關(guān)依賴項,并且確保這些依賴項被首先載入。但是我們不能在腳本執(zhí)行前訪問它。而且,document.write()在頁面載入后就不工作了。對于你的網(wǎng)站,一個好的方法是在用戶需要進行下一步操作時來載入腳本。最后,通過document.write()載入腳本或阻塞頁面的渲染。要讓你的網(wǎng)站有最佳表現(xiàn),這個方法是不可取的。
腳本載入:head.appendChild(script)§
我們可以在需要時創(chuàng)建腳本并將它們添加到頭部:
var head = document.getElementsByTagName('head')[0], script = document.createElement('script'); script.src = url; head.appendChild(script);
上面的腳本片段多了一點東西,不過那正是基本的思想。這種方法比document.write要好,因為它不會阻塞頁面的渲染并且在頁面載入后仍能工作。但是,它仍然有同步VS異步例子的問題:理想情況下,在執(zhí)行腳本前我們能夠通過require()知道相關(guān)依賴項,并且確保這些依賴項被首先載入。
函數(shù)封裝
在執(zhí)行我們的腳本前,我們需要知道相關(guān)依賴項并確保已經(jīng)將其載入。做這件事的最好方法是通過函數(shù)封裝來構(gòu)造我們的模塊載入API。像這樣:
define( //The name of this module "types/Manager", //The array of dependencies ["types/Employee"], //The function to execute when all dependencies have loaded. The //arguments to this function are the array of dependencies mentioned //above. function (Employee) { function Manager () { this.reports = []; } //This will now work Manager.prototype = new Employee(); //return the Manager constructor function so it can be used by //other modules. return Manager; } );
這是ReguireJS的句法。如果你想載入沒有定義成模塊的純文本的JavaScript的話,有一種簡單的句法:
require(["some/script.js"], function() { //This function is called after some/script.js has loaded. });
選擇這種句法是因為,它足夠簡潔并且允許載入者使用head.appendChild(script)載入類型。出于在瀏覽器中良好工作的需要,它有不同于普通的CommonJS句法。有建議說普通的CommonJS句法可以使用head.appendChild(script)的載入類型,如果服務器進程有封裝的函數(shù)可以將模塊轉(zhuǎn)換成傳輸格式的話。
我相信不強制使用一個運行時服務器進程來轉(zhuǎn)換代碼是很重要的事:
一是調(diào)試變的很怪異,因為服務器在注入封裝函數(shù)時會導致源文件的行號關(guān)閉。
二是需要做更多的工作。前端開發(fā)應該盡可能的使用靜態(tài)文件。
上述就是小編為大家分享的web網(wǎng)頁模塊化的原因,如果您也有類似的疑惑,不妨參照上述分析內(nèi)容進行理解。如果想了解更多相關(guān)內(nèi)容,請關(guān)注億速云行業(yè)資訊。
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。