最近看了下 Meteor 新出的 Beta.13 版本,最重要的一個(gè)新功能就是動(dòng)態(tài)加載 (dynamic imports)。
什么是動(dòng)態(tài)加載呢?簡(jiǎn)單來(lái)說(shuō)就是在客戶端需要一部分代碼時(shí)才從服務(wù)端加載它們。對(duì)應(yīng)的靜態(tài)加載就是不管客戶端暫時(shí)需不需要,只要是在代碼庫(kù)里的都一股腦加載到前端去。
大家如果用過(guò) Meteor 就知道,在生產(chǎn)環(huán)境 Meteor 把 js 和 css 各自打包成一個(gè)巨大的文件發(fā)布,然后在客戶端做渲染。這樣就造成 Meteor app 的首屏加載很慢。這種模式是很有問(wèn)題的,特別是在移動(dòng)端上。這個(gè)動(dòng)態(tài)加載就是為了解決這個(gè)問(wèn)題,在前端還不需要某些代碼時(shí),就不加載。例如先加載首屏相關(guān)的代碼,在其他路由、頁(yè)面的代碼等用戶需要時(shí)再去加載。其實(shí) Webpack 等工具早就可以實(shí)現(xiàn)這樣的功能了。
例子代碼解釋
核心代碼如下:
Template.hello.events({
'click button'(event, instance) {
instance.counter.set(instance.counter.get() + 1);
import("bcryptjs").then( bcryptjs => {
const saltRounds = 10;
const salt = bcryptjs.genSaltSync(saltRounds);
const plaintextPassword = '123456';
const hash = bcryptjs.hashSync(plaintextPassword, salt);
console.log("hashed password:", hash);
});
import("react").then( React => {
import moment from 'moment'
console.log("Today is ", moment().format('YYYY-MM-DD'));
console.log("React object: ", React);
});
},
});
在上面代碼中,只有在用戶點(diǎn)擊了按鈕之后,bcryptjs 和 react 才被加載到前端頁(yè)面。大家可以自己運(yùn)行一下例子試試。注意,Meteor 是通過(guò) websocket 把后續(xù)代碼傳到前端的,所以要在 Chrome devtools 的 Network 選擇 WS,然后點(diǎn)擊左側(cè)的 websocket,再查看 Frames,就可以看到如下的信息。

上圖就只是一些簡(jiǎn)單的信息加載。然后點(diǎn)擊一下例子頁(yè)面上的 click me 按鈕,可以看到類似下圖

可以看到 Frames 里倒數(shù)第一和第三的數(shù)據(jù)非常大,他們就是動(dòng)態(tài)加載的 bcryptjs 和 react。這樣就完成了模塊的按需加載。它是由 Meteor 的 dynamic-import package 完成這部分功能的。
注意
通過(guò)
meteor add添加的 package 很多還不能進(jìn)行動(dòng)態(tài)加載。因?yàn)榘募虞d方式得使用其他兼容的方式。大部分代碼得修改。要通過(guò)
import().then方式加載的包才是動(dòng)態(tài)的,老的方式都會(huì)和以前一樣在 Meteor 啟動(dòng)時(shí)就會(huì)加載??梢詤⒖嘉业睦永锛虞d的 moment 這個(gè)包,雖然是在一個(gè) ``````import().then``` 里,但是還是被打包在了 modules.js 里,所以是一開(kāi)始就被加載到瀏覽器。所以我的例子里只有 bcryptjs 和 react 是動(dòng)態(tài)加載的。本地 export 的包記得放到 Meteor 應(yīng)用的 imports 目錄下,因?yàn)椴辉?imports 目錄的模塊都是 eager 加載的,就是會(huì)被 Meteor bundle 在一起發(fā)布。
經(jīng)過(guò)網(wǎng)友 Hanz 提醒,目前 Meteor 1.5 beta 版 production 模式的 dynamic imports 是加載到 Application -> Storage -> IndexedDB。大家可以使用
meteor run --production試試看。
更多信息參考 Meteor pr 8327