對(duì)于一個(gè)高質(zhì)量的web應(yīng)用程序來(lái)說(shuō)慢宗,選擇一個(gè)重要的模塊加載器是非常重要的犁享。你可能不想在html頁(yè)面中手動(dòng)的添加script標(biāo)簽余素,因?yàn)檫@樣很不靈活(你必須手動(dòng)的對(duì)script標(biāo)簽排序、不能在部署的時(shí)候壓縮代碼...)饼疙。
最終的解決方案是Webpack溺森,并遵循它的基本原理的文檔。
模塊加載器最主要的需求就是允許你寫不同環(huán)境下的代碼窑眯。這就意味著同樣的一份代碼能運(yùn)行在node.js環(huán)境屏积,也能運(yùn)行在瀏覽器環(huán)境。每一個(gè)模塊加載器對(duì)服務(wù)器端的支持不同:
- Require.js和WebPack:可以在服務(wù)器端使用
- Browserify:沒(méi)有開(kāi)箱即用的方法
模塊代碼風(fēng)格
Require.js的模塊看起來(lái)像這樣:
define(['a', 'b'], function(a, b){return {myModule: 1}})
或者你需要很多的依賴磅甩,你可能會(huì)感到混亂炊林,你將這么做:
define(function(require, exports, module){
var a = require('a');
var b = require('b');
module.exports = {myModule: 1};
})
這兩種方式都不是最優(yōu)的,因?yàn)闀?huì)增加額外的代碼卷要。
使用WebPack和Browserify看起來(lái)像這樣:
var a = require('a');
var b = require('b');
module.exports = {myModule: 1};
這看起來(lái)非常像原生的node.js模塊渣聚。
投票結(jié)果:
- WebPack: +1;
- Require.js: -1;
- Browserify: +1;
遷移
你可以從任何風(fēng)格遷移到Webpack独榴。舉個(gè)例子,我以前用Require.js風(fēng)格的模塊奕枝,然后無(wú)縫遷移到了Webpack棺榔。這非常的快,我不需要對(duì)我的源代碼做任何的改變(構(gòu)建過(guò)程的配置例外)隘道,后來(lái)慢慢的我升級(jí)到Webpack的方式症歇。這一個(gè)點(diǎn)我們不進(jìn)行投票,但是Webpack再一次閃耀谭梗,如果你有一個(gè)大項(xiàng)目要處理的話(超過(guò)1000個(gè)文件)忘晤。
別名
別名是非常重要的,因?yàn)樽屇愕拇a組織良好激捏、整潔设塔、健壯且便于維護(hù)。
Webpack和Require.js在服務(wù)器端和客戶端都有別名远舅,而B(niǎo)rowserify沒(méi)有因?yàn)樗恢С謓ode.js闰蛔。
為什么別名非常重要,我們看下面的代碼結(jié)構(gòu):
src
client/someFolderA/a.js
shared/logic/complexLogic.js
server/someFolderB/b.js
現(xiàn)在你在服務(wù)器上的server/someFolderB/b.js
文件中寫了一些代碼表谊,你將怎么樣去加載complexLogic.js
這個(gè)文件呢钞护?沒(méi)有別名的話會(huì)很混亂:
// From file "server/someFolderB/b.js"
require('../../shared/complexLogic');
這不是理想的情況盖喷,有很多真實(shí)的例子: ghost1, ghost2, ghost3 with 3 levels, material-ui, strider1, strider2爆办。
現(xiàn)在假設(shè)你要把server/someFolderB/b.js
這個(gè)文件移動(dòng)到其他的目錄,你將不得不更新所有的相對(duì)路徑(有時(shí)候相對(duì)路徑是好的课梳,但你需要知道什么時(shí)候使用它們)距辆。
如果有別名的話,你可能這么做:
// From file "server/someFolderB/b.js"
require('shared/complexLogic');
你需要添加一個(gè)名為shared
的別名指向src/shared
暮刃,這讓代碼非常的整潔且更加健壯跨算。
Browserify的用戶也能做類似的事情,但不是最優(yōu)的做法椭懊。他們能添加一個(gè)命名為node_modules
的root
項(xiàng)目文件夾诸蚕。
app
node_modules
client
shared
server
如果你只需要3個(gè)root別名且你不介意你的app中多一個(gè)node_modules
文件的話,這也是不錯(cuò)的氧猬。但是這對(duì)新加入的開(kāi)發(fā)者來(lái)說(shuō)是不直觀的背犯,他們可能會(huì)把node模塊放到node_modules
文件夾中。
投票結(jié)果:
- WebPack: +1;
- Require.js: +1;
- Browserify: -1;
速度
在開(kāi)發(fā)的模式中盅抚,這是沒(méi)有統(tǒng)一標(biāo)準(zhǔn)的漠魏。但是從個(gè)人經(jīng)驗(yàn)而言這3者中Require.js是最快的,因?yàn)樗谶\(yùn)行前不需要任何預(yù)處理的任務(wù)妄均。
構(gòu)建過(guò)程的速度取決于2個(gè)變量:
- 運(yùn)行任務(wù)的工具(gulp或者grunt);
- 運(yùn)行的任務(wù)(Webpack柱锹、Require.js哪自、Browserify)
Gulp遠(yuǎn)遠(yuǎn)比grunt要快,沒(méi)有做統(tǒng)計(jì)比較所有的選項(xiàng)禁熏。
投票結(jié)果:
- WebPack: 0;
- Require.js: +1;
- Browserify: 0;
內(nèi)存使用
WebPack和Browserify都需要使用大量的內(nèi)存壤巷,因?yàn)樗鼈儽仨毎阉械拇a都保存在內(nèi)存中。Require.js是最輕的瞧毙,因?yàn)闆](méi)有代碼必須保存在內(nèi)存中隙笆。
投票結(jié)果:
- WebPack: 0;
- Require.js: +1;
- Browserify: 0;
集成其他模塊
在Require.js中加載其他模塊需要在配置中去填充,而WebPack做這些幾乎都是自動(dòng)的升筏。
投票結(jié)果:
- WebPack: +1;
- Require.js: -1;
- Browserify: 0;
Webpack警告
使用增強(qiáng)的require(讓W(xué)ebpack工作在node.js中)撑柔,你可能會(huì)遇到一些問(wèn)題,比如:加載java的模塊因?yàn)樗嵌M(jìn)制的(很容易修復(fù)您访,通過(guò)原生的node.js的require方法)铅忿。
投票結(jié)果:
- WebPack: -1;
- Require.js: 0;
- Browserify: 0;
結(jié)論
通過(guò)回顧Webpack、Require.js和Browserify灵汪,你能夠很好的理解每一個(gè)工具有什么優(yōu)點(diǎn)和缺點(diǎn)檀训。
最后的投票結(jié)果:
- WebPack: 2;
- Require.js: 1;
- Browserify: 0;
在所有的選擇中,強(qiáng)烈建議WebPack結(jié)合gulp一起使用享言。