免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
對(duì)CommonJS,AMD,CMD規(guī)范以及script標(biāo)簽異步加載的理解
1.牢騷

CommonJS, AMD, CMD , 其實(shí)很早就接觸過了。
當(dāng)時(shí), 網(wǎng)上的文章看得眼花繚亂, 只依稀記得幾個(gè)模糊的概念。
什么依賴前置 , 什么按需加載。
一頭霧水。

現(xiàn)在再回過頭來看看概念 , 網(wǎng)上部分文章用詞模棱兩可。
給我們這些菜雞, 帶來了理解的偏差和困惑。
記得第一個(gè)項(xiàng)目還用了requireJS 。
時(shí)過境遷,現(xiàn)在入門前端 , 都是直接上webpack了 。
但我覺得還是有必要理一理 。


2. 是什么

CommonJS, AMD, CMD是規(guī)范, 理念 ;

  • 對(duì) CommonJS 的實(shí)現(xiàn) , 有 node 的模塊系統(tǒng) ;

  • 對(duì) AMD 的實(shí)現(xiàn)有require.js ;

  • 而 CMD, 是在sea.js的實(shí)現(xiàn)中提出來的 (但是在Google和Stack Overflow, 這個(gè)概念很少被提到, 一般出現(xiàn)在國(guó)內(nèi))。


  • CommonJS規(guī)范, 模塊加載是同步的
    對(duì)node來說,模塊存放在本地硬盤,同步加載,等待時(shí)間就是硬盤的讀取時(shí)間,這個(gè)時(shí)間非常短;

  • AMD、CMD 規(guī)范,模塊加載是異步的
    目的, 是為了適應(yīng)瀏覽器環(huán)境,加載的時(shí)間取決于網(wǎng)絡(luò)的好壞,可能要等很長(zhǎng)時(shí)間;


3. 先說 async 和 defer

記得看文章的時(shí)候, 看到了下面這段話 ,


我看了半天, 總覺得不是很理解 , 為什么呢 ?
這里說, 腳本標(biāo)簽天生是異步的 , 那為什么會(huì)出現(xiàn) async 和 defer ?
然后, 我發(fā)覺我并沒有把 加載執(zhí)行的概念區(qū)分清楚 , 這里的加載我把它理解為瀏覽器中的下載
這里貼一張圖就很清楚了:

  • <script> 標(biāo)簽, 在下載和執(zhí)行的時(shí)候 , 會(huì)阻塞dom的渲染進(jìn)程 , 所以如果把<script> 標(biāo)簽放在<head>中, 當(dāng) js 文件很大或者網(wǎng)絡(luò)差時(shí), 會(huì)導(dǎo)致頁(yè)面長(zhǎng)時(shí)間空白( 順帶提一下, <script>標(biāo)簽并不會(huì)阻止其他的<script>標(biāo)簽的下載, 現(xiàn)代瀏覽器中多個(gè)<script>下載是并行的, 在chrome中, 默認(rèn)支持6個(gè)資源(http1.x)并行下載 ), 另外 , 腳本是按照<script>標(biāo)簽的書寫順序執(zhí)行的 ;

  • <script defer> 在加上defer以后, 下載的過程就不會(huì)阻塞dom渲染了, 但腳本的執(zhí)行是在dom渲染完畢之后;

  • <script async>在加上async以后, 下載的過程同樣不會(huì)阻塞dom渲染, 但腳本會(huì)在下載完后立刻執(zhí)行, 所以存在多個(gè)<script async>時(shí), 無法保證多個(gè)js文件的執(zhí)行順序, 加載較快的腳本會(huì)執(zhí)行;

所以defer, async主要作用于加載階段, 執(zhí)行階段仍然會(huì)阻塞dom渲染


4. 再看 require.js 的異步體現(xiàn)

再看看使用require.js的模塊寫法
新建 main.js / a.js / b.js , main.js 為入口, 引用了a.js , b.js

	// main.js	// waitSeconds = 0的配置, 是為了防止文件過大或網(wǎng)絡(luò)不佳時(shí), 加載時(shí)間過長(zhǎng)導(dǎo)致require報(bào)`Load timeout for modules`的錯(cuò)誤 	require.config({   		 waitSeconds: 0  	});	require(['a.js', 'b.js'], function(a, b){		// handle / use a, b		console.log(a)		console.log(b)	})		// a.js   ------------------------------	define([], function(){		return {			a: 111111111111		}	})		// b.js   ------------------------------	define([], function(){		return {			b: 222222222222		}	})	
  • 文件 開始下載 的 順序: main, a, b
    為什么文件下載的順序是 main, a, b 呢? main依賴了 a b, 不是 a b 先下載嗎? 那是因?yàn)椋挥?main 加載之后,才知道m(xù)ian依賴了啥啊

  • 執(zhí)行的 順序 : a, b, main 或者 b, a, main
    這里體現(xiàn) require.js 的異步加載。 a 和 b 的加載或者說下載是并行的, 但 a 和 b 的執(zhí)行順序不確定的 , a 和 b 先執(zhí)行哪一個(gè)都無所謂 ,只需要保證回調(diào)函數(shù)在 a 和 b 都執(zhí)行完之后再執(zhí)行就可以了;

在require.js中模塊加載是怎么實(shí)現(xiàn)的呢?
看一下require.js的源碼:

    /**     * Creates the node for the load command. Only used in browser envs.     */    req.createNode = function (config, moduleName, url) {        var node = config.xhtml ?                document.createElementNS('http://www.w3.org/1999/xhtml', 'html:script') :                document.createElement('script');        node.type = config.scriptType || 'text/javascript';        node.charset = 'utf-8';        node.async = true;           return node;    };

這段代碼, 新建了script標(biāo)簽, 并把它的 async設(shè)置為true ,

另外, 前面說 , 依賴的模塊都執(zhí)行完之后, 才會(huì)執(zhí)行回調(diào)函數(shù)。 那怎么判斷是否 所有依賴的模塊 都已經(jīng)執(zhí)行完 ?
多個(gè)模塊的情況 , 還沒看懂(捂臉) , 但是單個(gè)模塊的執(zhí)行狀態(tài)是可以監(jiān)聽的:

	...	...	...        //mentioned above about not doing the 'script execute,        //then fire the script load event listener before execute        //next script' that other browsers do.        //Best hope: IE10 fixes the issues,        //and then destroys all installs of IE 6-9.        //node.attachEvent('onerror', context.onScriptError);    } else {        node.addEventListener('load', context.onScriptLoad, false);        node.addEventListener('error', context.onScriptError, false);    }    node.src = url;    ...    ...

上面的代碼可以看到, 通過 <script>標(biāo)簽的onload事件可以判斷, 該腳本是否執(zhí)行完畢 ;

所以, 個(gè)人理解, require.js的異步
第一, 是指下載的異步,
第二, 還指回調(diào)機(jī)制, 依賴模塊執(zhí)行完之后再執(zhí)行回調(diào)函數(shù)

5. AMD 和 CMD 的理解誤區(qū)

現(xiàn)在 再來看 AMD 和 CMD 的區(qū)別, 網(wǎng)上的說法:

  1. AMD推崇依賴前置,在定義模塊的時(shí)候就要聲明其依賴的模塊

  2. CMD推崇就近依賴,只有在用到某個(gè)模塊的時(shí)候再去require

第二點(diǎn) 只有在用到某個(gè)模塊的時(shí)候再去require, 這種說其實(shí)是帶有誤導(dǎo)性的,
看看sea.js的寫法:

	define(function(require, exports, module) {  		console.log(123) 	    var a = require('a.js')	    console.log(a)	    var b = require('b.js')	    console.log(b)	})

這里, 難道是執(zhí)行到require, 才去加載/下載require的文件嗎 ?
當(dāng)然不是 ! 看一下sea.js的代碼:

	window.define = function(callback) {    	var id = getCurrentJs()    	var depsInit = s.parseDependencies(callback.toString())    	var a = depsInit.map(item => basepath   item)    ....

sea.js把callback回調(diào)函數(shù)用轉(zhuǎn)換成字符串, 再找出有哪些依賴, 這些依賴模塊同樣是預(yù)先加載的 ,
不同在于, require.js會(huì)立刻執(zhí)行依賴模塊, 而sea.js 在遇到 require 語句的時(shí)候 , 再執(zhí)行依賴模塊;

5. 總結(jié)

AMD和CMD最大的區(qū)別是: 對(duì)依賴模塊的執(zhí)行時(shí)機(jī)處理不同(注意不是加載的時(shí)機(jī))
很多人說, requireJS是異步加載模塊,SeaJS是同步加載模塊,這么說實(shí)際上是不準(zhǔn)確的 ;
二者加載模塊都是異步的 ;
只不過AMD依賴前置,可以方便知道依賴了哪些模塊,然后馬上加載 , 在加載完成后, 就會(huì)執(zhí)行該模塊;
而CMD推崇就近依賴,把模塊變?yōu)樽址馕鲆槐? 找到依賴了哪些模塊, 在加載模塊完成后, 不立刻執(zhí)行, 而是等到require后再執(zhí)行;
上面只說了異步相關(guān)的概念, 其實(shí) require.js / sea.js , 最重要的還是模塊化。
模塊化降低耦合,依賴清晰,讓調(diào)試, 加功能, 任務(wù)分配和交接都更方便。

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
web前端教程分享js中的模塊化一
CommonJS,AMD,CMD區(qū)別
工程化實(shí)踐:模塊化和組件化
以代碼愛好者角度來看AMD與CMD
前端模塊化
人們常說的前端工程化到底是什么?
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服