詳解webpack解惑:require的五種用法
webpack中可以寫commonjs格式的require同步語法,可以寫AMD格式的require回調(diào)語法,還有一個(gè)require.ensure,以及webpack自己定義的require.include,再加上ES6的import語法,這么多豈不是會(huì)把人給搞亂。本篇就來梳理一下這些require各自的特點(diǎn),以及都在什么場(chǎng)景下使用。
commonjs同步語法
經(jīng)典的commonjs同步語法如下:
var a = require('./a'); a.show();
此時(shí)webpack會(huì)將a.js打包進(jìn)引用它的文件中。這是最普遍的情形,不必贅述。
commonjs異步加載
在commonjs中有一個(gè)Modules/Async/A規(guī)范,里面定義了require.ensure語法。webpack實(shí)現(xiàn)了它,作用是可以在打包的時(shí)候進(jìn)行代碼分片,并異步加載分片后的代碼。用法如下:
require.ensure([], function(require){ var list = require('./list'); list.show(); });
此時(shí)list.js會(huì)被打包成一個(gè)單獨(dú)的chunk文件,大概長(zhǎng)這樣:
1.fb874860b35831bc96a8.js
可讀性比較差。我在上一篇結(jié)尾也提到了,給它命名的方式,那就是給require.ensure傳遞第三個(gè)參數(shù),如:
require.ensure([], function(require){ var list = require('./list'); list.show(); }, 'list');
這樣就能得到你想要的文件名稱:
list.fb874860b35831bc96a8.js
你也可以傳入像"question/list"這樣帶層級(jí)的名字,這樣webpack會(huì)按照層級(jí)給你創(chuàng)建文件夾。
需要注意的是,如果你在require.ensure的函數(shù)中引用了兩個(gè)以上的模塊,webpack會(huì)把它們打包在一起,比如:
require.ensure([], function(require){ var list = require('./list'); list.show(); var edit = require('./edit'); edit.display(); }, 'list_and_edit');
list.js和edit.js將會(huì)被打包成一個(gè)文件,并命名為list_and_edit.js。這就需要根據(jù)你的實(shí)際情況來衡量了,如果你不希望打包在一起,只能寫兩個(gè)require.ensure分別引用這兩個(gè)文件。
多說一句,這種思維其實(shí)我是很不喜歡的,在編碼階段卻要對(duì)打包的事情做出決策,明顯違背了職責(zé)分離原則。
commonjs預(yù)加載懶執(zhí)行
在上面的用法中,我們給require.ensure的第一個(gè)參數(shù)傳了空數(shù)組,實(shí)際上這里是可以接收模塊名稱的,作用就是實(shí)現(xiàn)預(yù)加載懶執(zhí)行。用法如下:
require.ensure(['./list'], function(require){ var list = require('./list'); list.show(); });
給require.ensure的第一個(gè)參數(shù)傳了['./list'],執(zhí)行到這里的時(shí)候list.js會(huì)被瀏覽器下載下來,但是并不會(huì)執(zhí)行l(wèi)ist.js模塊中的代碼,也就是webpack官網(wǎng)說的,不會(huì)進(jìn)行evaluate。真正進(jìn)行evaluate的時(shí)候是到了后面這句var list = require('./list');這就是所謂的懶執(zhí)行。
寫在函數(shù)中的多個(gè)模塊會(huì)被打包在一起,這一點(diǎn)和上面沒有區(qū)別。另外,寫在數(shù)組中的模塊也會(huì)跟他們打包在一起,不管你有沒有手動(dòng)執(zhí)行。
這種寫法也是有點(diǎn)別扭的,像是commonjs和AMD的結(jié)合體,而且一個(gè)模塊名稱還要寫兩次,真是不夠優(yōu)雅。所以webpack自己定義了一個(gè)方法,能夠?qū)崿F(xiàn)預(yù)加載。
webpack自帶的require.include
require.include是webpack自己提供的,并沒有什么規(guī)范做后臺(tái),所以是個(gè)小角色。它可以實(shí)現(xiàn)上面是預(yù)加載功能,而不用把模塊寫在數(shù)組中,用法如下:
require.ensure([], function(require){ require.include('./list');//此處只加載不執(zhí)行 });
據(jù)webpack官網(wǎng)文檔介紹,require.include還有一個(gè)作用是能把子模塊中的公共部分,提取到父模塊中,比如child1和child2都引用了list.js這個(gè)模塊,那么如果在parent中include了list.js,那么子模塊中的就會(huì)被刪掉,相當(dāng)于提升到了父模塊中。(這里所謂的父子關(guān)系是指引用關(guān)系)
這個(gè)方法官方也是一筆帶過,看來也是一個(gè)雞肋的東西,用處不大。因?yàn)槲野l(fā)現(xiàn)require.include的返回值是undefined,也就是說,如果你想使用模塊,姿勢(shì)是這樣的:
require.ensure([], function(require){ require.include('./preview'); //加載 let p = require('./preview'); //執(zhí)行 p.getUrl(); //使用 }, 'pre');
AMD異步加載
webpack既支持commonjs規(guī)范也支持AMD規(guī)范,這就意味著AMD的經(jīng)典語法是可以正常使用的,如:
require(['./list'], function(list){ list.show(); });
當(dāng)然,這樣寫的話list.js也是被單獨(dú)打包成一個(gè)文件的。與上面類似,如果你在這里寫了多個(gè)模塊,那么這些模塊都會(huì)被打包成一個(gè)文件,如:
require(['./list', './edit'], function(list, edit){ list.show(); edit.display(); });
list.js和edit.js會(huì)被打包在一起。不同的是,AMD的方式無法傳入第三個(gè)參數(shù)當(dāng)文件名,所以得不到很好看的文件。
ES6 import
這年頭不用ES6都不好意思跟人打招呼。所以我們的代碼中,又會(huì)多一種模塊引入語法,那就是import。import會(huì)被轉(zhuǎn)化為commonjs格式或者是AMD格式,所以不要把它認(rèn)為是一種新的模塊引用方式。babel默認(rèn)會(huì)把ES6的模塊轉(zhuǎn)化為commonjs規(guī)范的,你也不用費(fèi)勁再把它轉(zhuǎn)成AMD了。
所以如下寫法是等價(jià)的:
import list from './list'; //等價(jià)于 var list = require('./list');
不過這兩種寫法只需選一種,避免在代碼中同時(shí)使用兩種,否則會(huì)造成混淆。
總結(jié)
以上把require的用法捋了一遍,明白了各自用法的區(qū)別之后,我們就可以在項(xiàng)目中進(jìn)行選擇了。我覺得最佳選擇是往commonjs方向靠攏,想嘗試ES6的話就用import代替commonjs同步語法即可。
因此,代碼中保持以下兩種風(fēng)格就好:
//可打包在一起的同步代碼,使用import語法 import list from './list'; //需要獨(dú)立打包、異步加載的代碼,使用require.ensure require.ensure([], function(require){ var list = require('./list'); });
很顯然,你在寫代碼的時(shí)候還是需要對(duì)打包結(jié)果進(jìn)行決策,這是我不喜歡webpack的原因。gulp那樣多好,編碼就是編碼,編譯就是編譯,分開來。不過這就是webpack以模塊為核心的打包方式的特點(diǎn)吧,仁者見仁,只要團(tuán)隊(duì)內(nèi)做一個(gè)約定,也不會(huì)打的一塌糊涂。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
JS實(shí)現(xiàn)的加減乘除四則運(yùn)算計(jì)算器示例
這篇文章主要介紹了JS實(shí)現(xiàn)的加減乘除四則運(yùn)算計(jì)算器,涉及javascript事件響應(yīng)及數(shù)學(xué)運(yùn)算相關(guān)操作技巧,需要的朋友可以參考下2017-08-08webpack-mvc 傳統(tǒng)多頁面組件化開發(fā)詳解
這篇文章主要介紹了webpack-mvc 傳統(tǒng)多頁面組件化開發(fā)詳解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-05-05基于Bootstrap的UI擴(kuò)展 StyleBootstrap
這篇文章主要為大家詳細(xì)介紹了基于Bootstrap的UI擴(kuò)展: StyleBootstrap,感興趣的小伙伴們可以參考一下2016-06-06JavaSctit 利用FileReader和濾鏡上傳圖片預(yù)覽功能
FileReader 對(duì)象允許Web應(yīng)用程序異步讀取存儲(chǔ)在用戶計(jì)算機(jī)上的文件內(nèi)容,使用 File或 Blob對(duì)象指定要讀取的文件或數(shù)據(jù)。下面通過本文給大家分享JavaSctit 利用FileReader和濾鏡上傳圖片預(yù)覽功能,需要的朋友參考下吧2017-09-09javascript中的循環(huán)語句for語句深入理解
for循環(huán)是多數(shù)語言都有的。在javascript中,for循環(huán)有幾種不同的使用情況,下面為大家一一介紹下2014-04-04JavaScript讓IE瀏覽器event對(duì)象符合W3C DOM標(biāo)準(zhǔn)
IE瀏覽器event對(duì)象跟W3C實(shí)現(xiàn)的不一樣.所以自己封裝一個(gè)EventUtil類來讓IE瀏覽器的event對(duì)象與W3C一樣.2009-11-11