我之前在 《前端搭環境之從入門到放棄》這篇文章中吐槽過,webpack中可以寫commonjs格式的require同步語法,可以寫amd格式的require**語法,還有乙個require.ensure,以及webpack自己定義的require.include,再加上es6的import語法,這麼多豈不是會把人給搞亂。本篇就來梳理一下這些require各自的特點,以及都在什麼場景下使用。
經典的commonjs同步語法如下:
var a = require('./a');a.show();
此時webpack會將a.js打包進引用它的檔案中。這是最普遍的情形,不必贅述。
在commonjs中有乙個modules/async/a規範,裡面定義了require.ensure語法。webpack實現了它,作用是可以在打包的時候進行**分片,並非同步載入分片後的**。用法如下:
require.ensure(, function(require));
此時list.js會被打包成乙個單獨的chunk檔案,大概長這樣:
1.fb874860b35831bc96a8.js
require.ensure(, function(require), 'list');
這樣就能得到你想要的檔名稱:
list.fb874860b35831bc96a8.js
你也可以傳入像"question/list"這樣帶層級的名字,這樣webpack會按照層級給你建立資料夾。
需要注意的是,如果你在require.ensure的函式中引用了兩個以上的模組,webpack會把它們打包在一起,比如:
require.ensure(, function(require), 'list_and_edit');
list.js和edit.js將會被打包成乙個檔案,並命名為list_and_edit.js。這就需要根據你的實際情況來衡量了,如果你不希望打包在一起,只能寫兩個require.ensure分別引用這兩個檔案。
多說一句,這種思維其實我是很不喜歡的,在編碼階段卻要對打包的事情做出決策,明顯違背了職責分離原則。
在上面的用法中,我們給require.ensure的第乙個引數傳了空陣列,實際上這裡是可以接收模組名稱的,作用就是實現預載入懶執行。用法如下:
require.ensure(['./list'], function(require));
寫在函式中的多個模組會被打包在一起,這一點和上面沒有區別。另外,寫在陣列中的模組也會跟他們打包在一起,不管你有沒有手動執行。
這種寫法也是有點彆扭的,像是commonjs和amd的結合體,而且乙個模組名稱還要寫兩次,真是不夠優雅。所以webpack自己定義了乙個方法,能夠實現預載入。
require.include是webpack自己提供的,並沒有什麼規範做後台,所以是個小角色。它可以實現上面是預載入功能,而不用把模組寫在陣列中,用法如下:
require.ensure(, function(require));
據webpack官網文件介紹,require.include還有乙個作用是能把子模組中的公共部分,提取到父模組中,比如child1和child2都引用了list.js這個模組,那麼如果在parent中include了list.js,那麼子模組中的就會被刪掉,相當於提公升到了父模組中。(這裡所謂的父子關係是指引用關係)
這個方法官方也是一筆帶過,看來也是乙個雞肋的東西,用處不大。因為我發現require.include的返回值是undefined,也就是說,如果你想使用模組,姿勢是這樣的:
require.ensure(, function(require), 'pre');
webpack既支援commonjs規範也支援amd規範,這就意味著amd的經典語法是可以正常使用的,如:
require(['./list'], function(list));
當然,這樣寫的話list.js也是被單獨打包成乙個檔案的。與上面類似,如果你在這裡寫了多個模組,那麼這些模組都會被打包成乙個檔案,如:
require(['./list', './edit'], function(list, edit));
list.js和edit.js會被打包在一起。不同的是,amd的方式無法傳入第三個引數當檔名,所以得不到很好看的檔案。
這年頭不用es6都不好意思跟人打招呼。所以我們的**中,又會多一種模組引入語法,那就是import。import會被轉化為commonjs格式或者是amd格式,所以不要把它認為是一種新的模組引用方式。babel缺省會把es6的模組轉化為commonjs規範的,你也不用費勁再把它轉成amd了。
所以如下寫法是等價的:
import list from './list';//等價於
var list = require('./list');
不過這兩種寫法只需選一種,避免在**中同時使用兩種,否則會造成混淆。
以上把require的用法捋了一遍,明白了各自用法的區別之後,我們就可以在專案中進行選擇了。我覺得最佳選擇是往commonjs方向靠攏,想嘗試es6的話就用import代替commonjs同步語法即可。
因此,**中保持以下兩種風格就好:
//可打包在一起的同步**,使用import語法
import list from './list';
//需要獨立打包、非同步載入的**,使用require.ensure
require.ensure(, function
(require));
很顯然,你在寫**的時候還是需要對打包結果進行決策,這是我不喜歡webpack的原因。gulp那樣多好,編碼就是編碼,編譯就是編譯,分開來。不過這就是webpack以模組為核心的打包方式的特點吧,仁者見仁,只要團隊內做乙個約定,也不會打的一塌糊塗。
如果你是新手,對commonjs以及amd的各自特點還不太清楚,推薦去看一下我之前寫的這篇:js模組化歷程
requir與include的區別
require 語句的效能與include 相類似,都是包括並執行指定檔案。不同之處在於 對include 語句來說,在執行檔案時每次都要進行讀取和評估 而對於require 來說,檔案只處理一次 實際上,檔案內容替換require 語句 這就意味著如果可能執行多次的 則使用require 效率比較...
requir和load的區別
不同點 load 1 每次執行load的時候,它都會無條件的載入指定的ruby的原始檔。2 使用它可以重新來載入乙個在程式開始執行後可能修改的原始檔。require 1 載入指定的檔案,且只載入一次 2 require可以載入二進位制庫 3 require是一條可執行語句 它可能在乙個if語句內,或...
Lua模組引入import 和require的區別
lua 中引入乙個模組,可以採用兩種方式 import和require方式,具體的區別在於 import 與require 功能相同,但具有一定程度的自動化特性。假設我們有如下的目錄結構 myclass 中需要載入 myclassbase 和 myclassdata。如果用 require mycl...