sea.js的同步魔法
阿新 • • 發佈:2019-08-26
前些時間也是想寫點關於CMD
模組規範的文字,以便幫助自己理解。今天看到一篇知乎回答,算是給了我一點啟發。
同步寫法卻不阻塞?
先上一個sea.js
很經典的模組寫法:
// 定義一個模組
define(function(require, exports, module) {
// 載入jquery模組
var $ = require('jquery');
// 直接使用模組裡的方法
$('#header').hide();
});
按道理載入模組,就是需要等jquery.js
載入完畢才能使用,應該是一個非同步的過程,為什麼可以寫成同步的形式呢?這是用了什麼黑科技?
原來作者玉伯大佬用了一個小魔法來“欺騙”我們。而盧勃大神在知乎給了一個很精彩的解釋,這裡直接分享下:
也就是說,require.js
和sea.js
都是在執行模組前預載入了依賴的模組,並沒有比require.js
顯得更“懶載入”,只是所依賴模組的程式碼執行時機不同。require.js
載入時執行,而sea.js
是使用時執行。
其實從程式碼的寫法也看得出來,require.js
的依賴模組在載入後便有了執行結果,並作為回撥函式的實參傳入。
reuiqre.js
寫法:
// 載入完jquery.js後,得到的執行結果$作為引數傳入了回撥函式
define(['jquery'], function($) {
$('#header').hide();
});
sea.js
寫法:
// 預載入了jquery.js define(function(require, exports, module) { // 執行jquery.js模組,並得到結果賦值給$ var $ = require('jquery'); // 呼叫jquery.js模組提供的方法 $('#header').hide(); });
從這一點上來看,兩者在效能上並沒有太多差異。因為最影響頁面渲染速度的當然是資源的載入速度,既然都是預載入,那麼載入模組資源的耗時是一樣的(網路情況相同時)。
而模組程式碼的執行時機並沒有那麼影響效能(除非你的模組太大),現在的js
引擎如V8
引擎足夠強,沒什麼壓力。
懶載入是否存在?
懶載入是存在的。我剛才說的sea.js
並沒有比require.js
更顯得“懶載入”是指模組載入的時機上兩者是一致的,都是預先載入,而不是說不能懶載入。
比如說,有一個模組,頁面渲染時,我不需要載入使用,但是在做了某種互動時(比如點了按鈕),才需要載入使用,這個時候“懶載入”的作用就體現了。下面以require.js
require.config({
baseUrl: './assets/js/',
paths: {
modulea: 'module-a',
moduleb: 'module-b'
}
})
require(["modulea"], function(modulea) {
var btnNode = document.querySelector('#btn-load');
var node1 = document.createElement('span');
node1.innerText = '模組A已經載入!'
btnNode.insertAdjacentElement('beforebegin', node1)
btnNode.addEventListener('click', function() {
require(["moduleb"], function(moduleb) {
var node2 = document.createElement('span');
node2.innerText = '模組B已經載入!'
btnNode.insertAdjacentElement('afterend', node2)
});
})
});
頁面渲染時只加載模組A
點選按鈕後加載模組B
總結
雖然AMD
和CMD
兩種思想有一些差異,但都不失為一種優秀的模組化方案,為大佬們打call!
首發連結