欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

深入探尋seajs的模塊化與加載方式

 更新時(shí)間:2015年04月14日 09:38:59   投稿:hebedich  
本文是對(duì)Sea.js 提供seajs的模塊化與加載方式的講解,對(duì)學(xué)習(xí)JavaScript編程技術(shù)有所幫助,與大家分享。有需要的小伙伴可以參考下。

由于一直在使用,所以了解了下seajs的源代碼。這里是我對(duì)下面幾個(gè)問(wèn)題的理解:

1、seajs的require(XXX)的方法是怎樣實(shí)現(xiàn)模塊加載的?

2、為什么需要預(yù)加載?

3、為什么需要構(gòu)建工具?

4、構(gòu)建前后的代碼究竟有些什么區(qū)別,為什么要這么做?

問(wèn)題1: seajs的require(XXX)的方法是怎樣實(shí)現(xiàn)模塊加載的?

代碼邏輯比較繞,對(duì)源代碼的理解放在文章的末尾,這里先簡(jiǎn)單梳理下模塊加載的邏輯:

1、從seajs.use方法入口,開(kāi)始加載use到的模塊。

2、use到的模塊這時(shí)mod緩存當(dāng)中一定是不存在的。seajs創(chuàng)建一個(gè)新的mod,賦予一些初始的狀態(tài)。

3、執(zhí)行mod.load方法

4、一堆邏輯之后走到seajs.request方法,請(qǐng)求模塊文件。模塊加載完成之后,執(zhí)行define方法。

5、define方法分析提取模塊的依賴模塊,保存起來(lái)。緩存factory但不執(zhí)行。

6、模塊的依賴模塊再被加載,如果繼續(xù)有依賴模塊,則繼續(xù)加載。直至所有被依賴的模塊都加載完畢。

7、所有的模塊加載完畢之后,執(zhí)行use方法的callback.

8、模塊內(nèi)部邏輯從callback開(kāi)始執(zhí)行。require方法在這個(gè)過(guò)程當(dāng)中才被執(zhí)行。

問(wèn)題2:為什么需要預(yù)加載?

我們看到seajs.use方法實(shí)際上是在所有依賴模塊都加載完了之后才執(zhí)行callback。可以理解成在業(yè)務(wù)邏輯代碼在執(zhí)行之前,必須先預(yù)加載所有被依賴的模塊代碼。那么為什么是一個(gè)這樣必須先做預(yù)加載的邏輯?

答案在于邏輯代碼里面引用其他模塊方法的這個(gè)require方法的執(zhí)行方法:

var mod = require(id);

這個(gè)語(yǔ)法決定了mod的取得是個(gè)同步執(zhí)行的過(guò)程,如果模塊代碼在此之前沒(méi)有被預(yù)加載的話,就只能采用異步加載回調(diào)的方法來(lái)實(shí)現(xiàn)了,那么整個(gè)seajs的執(zhí)行邏輯將完全會(huì)是另一個(gè)樣子。因?yàn)楫惒侥銜?huì)搞不懂模塊的執(zhí)行順序,邏輯會(huì)變的難以掌控。

問(wèn)題3:為什么需要構(gòu)建工具?

可以看到?jīng)]有構(gòu)建前各個(gè)依賴模塊都是單獨(dú)加載的。這會(huì)產(chǎn)生過(guò)多的模塊請(qǐng)求,對(duì)于頁(yè)面的加載性能是不利的。構(gòu)建工具本質(zhì)上就是為了解決模塊合并加載的問(wèn)題。

問(wèn)題4:構(gòu)建前后的代碼究竟有些什么區(qū)別,為什么要這么做?

構(gòu)建工具究竟做了些什么。我們說(shuō)它本質(zhì)上是為了解決代碼合并加載的問(wèn)題,那么它所做的只是簡(jiǎn)單的將各個(gè)模塊文件合并成一個(gè)文件?

當(dāng)然不是。測(cè)試一下,你如果只是簡(jiǎn)單把幾個(gè)模塊文件合并到一個(gè)文件以后,會(huì)發(fā)現(xiàn)這個(gè)文件根本沒(méi)有辦法正常執(zhí)行。

原因在于define方法的實(shí)現(xiàn)。

seajs是推崇定義模塊的時(shí)候只在define方法傳入factory參數(shù)的。回顧define方法內(nèi)部,當(dāng)沒(méi)有傳入id(姑且等同于模塊的url)時(shí),會(huì)通過(guò)getCurrentScript()方法去取得當(dāng)前正在執(zhí)行的這個(gè)模塊文件的url路徑,然后把這個(gè)路徑作為鍵值與模塊本身一起緩存到cachedMods。這里很關(guān)鍵的一點(diǎn)是,整個(gè)seajs內(nèi)部的這個(gè)模塊緩存機(jī)制其實(shí)是依賴每個(gè)模塊的url來(lái)做緩存的鍵值。require(id)方法,歸根結(jié)底也是通過(guò)url鍵值到。require(id)方法,歸根結(jié)底也是通過(guò)url鍵值到cachedMods里面去找相應(yīng)的模塊。這個(gè)鍵值不能重復(fù)不能出錯(cuò),不然模塊的對(duì)應(yīng)關(guān)系就混亂了。如果把a(bǔ)、b、c幾個(gè)模塊文件簡(jiǎn)單合并到一個(gè)目標(biāo)文件x之后,getCurrentScript()只能獲取到x的路徑,三個(gè)模塊的鍵值就沒(méi)法做出區(qū)別了,執(zhí)行肯定出錯(cuò)。

所以如果要把幾個(gè)模塊文件合并在一起,就必須為每個(gè)模塊明確uri。也就是define方法必須都傳入id參數(shù)。當(dāng)id傳入的時(shí)候,seajs會(huì)將這個(gè)id轉(zhuǎn)換為url用作緩存的鍵值。

如果只傳id和factory,也就是 define(id, factory),那么deps = undefined,define方法就會(huì)去執(zhí)行parseDependencies(factory.toString())方法提取factory里面的依賴模塊,后續(xù)會(huì)走到解析模塊路徑,線上單獨(dú)加載各個(gè)模塊的邏輯里面去,這個(gè)時(shí)候就失去了合并加載的意義了。

所以合并加載,define方法必須正確的傳入id,deps,factory三個(gè)參數(shù)才能正確執(zhí)行。

seajs 所謂CMD的模塊定義方法,是提倡大家寫(xiě)模塊的階段都只傳factory一個(gè)參數(shù)的,其他兩個(gè)參數(shù)在后期代碼構(gòu)建的階段來(lái)生成。上面解釋了為什么這兩參數(shù)在構(gòu)建后是必須的。

至于為什么提倡定義模塊的時(shí)候只傳factory,我看主要是因?yàn)槭止魅氲膇d和deps參數(shù),極易出錯(cuò),不便維護(hù)。工具可以提高效率并保證參數(shù)的正確。

附: 對(duì)seajs 主要代碼邏輯的理解。

說(shuō)明:源代碼版本是Sea.js 2.3.0

1、先看看define方法做了些什么

Module.define = function (id, deps, factory)

define方法的時(shí)候,支持三個(gè)參數(shù)。其中id,deps是選填的。factory必須。代碼里面通過(guò)以下邏輯來(lái)控制:

但其實(shí)deps是必須的,因?yàn)閟eajs必須知道每個(gè)模塊依賴了哪些模塊,不然無(wú)法執(zhí)行加載。

所以,當(dāng)factory是函數(shù),并且deps沒(méi)有被主動(dòng)傳入的時(shí)候,就需要使用parseDependencies方法來(lái)分析出factory當(dāng)中的依賴模塊了。

parseDependencies方法做的事情主要就是用一個(gè)正則表達(dá)式把函數(shù)體里面所有require(XXX)里面的XXX提取出來(lái),這也就是這個(gè)函數(shù)依賴到的所有模塊了。

方法本身不復(fù)雜,但是這個(gè)正則表達(dá)式不簡(jiǎn)單:

分析完deps之后,將模塊定義存入緩存:

注意,我們會(huì)發(fā)現(xiàn)define方法純粹只是分析模塊、存儲(chǔ)模塊,并沒(méi)有執(zhí)行模塊。

2、真正執(zhí)行模塊,是在require方法里面。我們接下來(lái)看require。

簡(jiǎn)而言之require方法就是根據(jù)id在define定義存儲(chǔ)的模塊緩存中找到相應(yīng)的模塊,并執(zhí)行它,獲得模塊定義返回的方法:

整個(gè)這個(gè)大步驟中,有一個(gè)很關(guān)鍵的步驟,有必要細(xì)說(shuō):

Module.get(require.resolve(id))。

require一個(gè)模塊的時(shí)候,首先要找到這個(gè)模塊。 Module.get方法就起這個(gè)作用。

cachedMods里面沒(méi)有的話,就創(chuàng)建一個(gè)新的Module并緩存到cachedMods里面:

define和rquire方法這樣看來(lái)不算復(fù)雜。seajs主要還是模塊加載的邏輯有點(diǎn)復(fù)雜。

3、seajs真正執(zhí)行的入口,是use方法:

通過(guò)use方法,從這里的ids開(kāi)始觸發(fā)模塊的加載和執(zhí)行。

可以看到加載的關(guān)鍵點(diǎn)在mod.load方法。

load方法代碼有點(diǎn)長(zhǎng),其中的主要邏輯是:判斷mod的當(dāng)前狀態(tài)是否為已加載或者加載中。

在Module的舒適化函數(shù)中,我們可以看到status默認(rèn)值是0.

所以沒(méi)有加載過(guò)的新模塊,到這里都是: mod.status = STATUS.LOADING 狀態(tài)設(shè)置為加載中,并執(zhí)行后續(xù)加載邏輯。

接來(lái)下是獲取模塊的依賴urls

mod.resolve方法:

Module.resolve方法本質(zhì)上就是把相對(duì)路徑、配置的path、別名等轉(zhuǎn)換成一個(gè)絕對(duì)路徑。不貼代碼了。

更新模塊加載狀態(tài)。

加載模塊的邏輯:

主要是m.fetch方法,里面其他邏輯這里略過(guò)。

可以看到 seajs.request最終會(huì)去執(zhí)行模塊文件的加載:

當(dāng)所有依賴模塊加載完了之后,執(zhí)行mod的onload方法

這里是 mod.onload()方法

到此,seajs的核心邏輯就差不多都看到了。供參考,有理解不到位或者表達(dá)不準(zhǔn)確的地方,歡迎一起探討。

以上所述就是本文的全部?jī)?nèi)容了,希望大家能夠喜歡。

相關(guān)文章

  • Vue實(shí)現(xiàn)圖片懶加載的多種方法詳解

    Vue實(shí)現(xiàn)圖片懶加載的多種方法詳解

    圖片懶加載是前端開(kāi)發(fā)中一項(xiàng)重要的性能優(yōu)化策略,它能夠明顯縮短頁(yè)面加載時(shí)間,提升用戶的瀏覽體驗(yàn),在本文中,我們將深入探討在Vue開(kāi)發(fā)時(shí)候如何實(shí)現(xiàn)圖片懶加載,同時(shí)探討多種實(shí)現(xiàn)途徑,需要的朋友可以參考下
    2023-08-08
  • SeaJS中use函數(shù)用法實(shí)例分析

    SeaJS中use函數(shù)用法實(shí)例分析

    這篇文章主要介紹了SeaJS中use函數(shù)用法,結(jié)合實(shí)例形式分析了use函數(shù)加載模塊的使用方法與相關(guān)操作技巧,需要的朋友可以參考下
    2017-10-10
  • Seajs源碼詳解分析

    Seajs源碼詳解分析

    近幾年前端工程化越來(lái)越完善,打包工具也已經(jīng)是前端標(biāo)配了,像seajs這種老古董早已停止維護(hù),這是一篇細(xì)細(xì)品味Seajs源碼的文章,看完一定受益匪淺
    2019-04-04
  • Seajs的學(xué)習(xí)筆記

    Seajs的學(xué)習(xí)筆記

    這篇文章主要介紹了Seajs的相關(guān)知識(shí)和和學(xué)習(xí)心得,適合剛接觸SeaJS的同學(xué),需要的朋友可以參考下
    2014-03-03
  • seajs中模塊的解析規(guī)則詳解和模塊使用總結(jié)

    seajs中模塊的解析規(guī)則詳解和模塊使用總結(jié)

    這篇文章主要介紹了seajs中模塊的解析規(guī)則詳解和模塊使用總結(jié),需要的朋友可以參考下
    2014-03-03
  • seajs學(xué)習(xí)之模塊的依賴加載及模塊API的導(dǎo)出

    seajs學(xué)習(xí)之模塊的依賴加載及模塊API的導(dǎo)出

    SeaJS是一個(gè)遵循 CommonJS 規(guī)范的模塊加載框架,可用來(lái)輕松愉悅地加載任意JavaScript模塊和css模塊樣式。SeaJS接口和方法也非常少,SeaJS 就兩個(gè)核心:模塊定義和模塊的加載及依賴關(guān)系。本文將詳細(xì)介紹模塊的依賴加載及模塊API的導(dǎo)出,有需要的朋友們可以參考借鑒。
    2016-10-10
  • seaJs的模塊定義和模塊加載淺析

    seaJs的模塊定義和模塊加載淺析

    這篇文章主要介紹了seaJs的模塊定義和模塊加載淺析,以及模塊間的依賴關(guān)系等問(wèn)題,需要的朋友可以參考下
    2014-06-06
  • seajs模塊壓縮問(wèn)題與解決方法實(shí)例分析

    seajs模塊壓縮問(wèn)題與解決方法實(shí)例分析

    這篇文章主要介紹了seajs模塊壓縮問(wèn)題與解決方法,結(jié)合實(shí)例形式分析了seajs模塊壓縮過(guò)程中出現(xiàn)的問(wèn)題及相應(yīng)的解決方法,需要的朋友可以參考下
    2017-10-10
  • SeaJS入門(mén)教程系列之使用SeaJS(二)

    SeaJS入門(mén)教程系列之使用SeaJS(二)

    這篇文章主要介紹了SeaJS入門(mén)教程系列之使用SeaJS,著重介紹了SeaJS的使用方法、關(guān)鍵方法的使用等,需要的朋友可以參考下
    2014-03-03
  • 把jQuery的類、插件封裝成seajs的模塊的方法

    把jQuery的類、插件封裝成seajs的模塊的方法

    這篇文章主要介紹了把jQuery的類、插件封裝成seajs的模塊的方法,需要的朋友可以參考下
    2014-03-03

最新評(píng)論