(本文章還在持續(xù)更新中。壕翩。。傅寡。)
使用webpack做構(gòu)建也有一段時(shí)間了,記錄一下使用webpack的心得北救。
我們來看看官網(wǎng)對(duì)webpack的描述荐操。
webpack is a module bundler for modern JavaScript applications. When webpack processes your application, it recursively builds a dependency graph that includes every module your application needs, then packages all of those modules into a small number of bundles - often only one - to be loaded by the browser.
It is incredibly configurable, but to get started you only need to understand Four Core Concepts: entry, output, loaders, and plugins.
This document is intended to give a high-level overview of these concepts, while providing links to detailed concept specific use-cases.
簡(jiǎn)單來說,webpack是一個(gè)現(xiàn)代js應(yīng)用的模塊管理器珍策。他能正確處理模塊的依賴方式托启,并且把多個(gè)模塊打包成瀏覽器識(shí)別的小數(shù)量文件(通常來說只有一個(gè)文件,但是如果采用異步加載或者代碼拆包的化就有多個(gè)了)攘宙,webpack是基于配置式的屯耸,最核心的四個(gè)參數(shù)是入口、出口蹭劈、模塊加載器和插件疗绣。
入口、出口都好理解铺韧,我這里要補(bǔ)充一下output的publicPath參數(shù)多矮。默認(rèn)為/,它是主文件加載其他文件時(shí)的路徑前綴。比如你構(gòu)建時(shí)產(chǎn)生了多個(gè)js文件塔逃,主文件是app.js讯壶。app.js加載其他文件時(shí),會(huì)在路徑前面補(bǔ)全publicPath湾盗。
loaders是用于處理不同的文件伏蚊。因?yàn)閣ebpack是基于nodejs的,而nodejs默認(rèn)只能識(shí)別js文件格粪,所以less躏吊、json等文件需要相應(yīng)的loader來將文件轉(zhuǎn)換成js。loaders具有如下特點(diǎn):
- 支持鏈?zhǔn)秸{(diào)用匀借,有先后順序颜阐,前一個(gè)loader的返回作為下一個(gè)loader的輸入
- 最終要生成js
常用的loader總結(jié)如下: - file-loader用于生成md5命名的文件
- url-loader 將文章轉(zhuǎn)換成dataurl的方式
- css-loader加載css文件∠爬撸可以解析里面的import凳怨,css模塊化。soucemap等
- style-loader將js化的css包裹style標(biāo)簽是鬼,并嵌入到html中肤舞,一般配合css-loader使用
-
ts-loader解析typescript
...
plugin
如果說loader是對(duì)具體資源類型上對(duì)資源文件的轉(zhuǎn)換擴(kuò)展。那么plugin則相當(dāng)于在全局上做擴(kuò)展均蜜。官方推薦plugin插件一覽表
如果有多個(gè)chunk共享相同的依賴李剖,我們可以用CommonsChunkPlugin來提取相同的依賴性到當(dāng)獨(dú)的文件
resolve
這個(gè)配置很實(shí)用。在處理模塊依賴關(guān)系的時(shí)候囤耳,涉及到嵌套比較深的文件篙顺,我們很可能會(huì)寫出這樣的代碼
import Utility from '../../utilities/utility';
通過resolve.alias就可以設(shè)置一個(gè)別名,正確的讓webpack從該路徑中查找
alias: {
Utilities: path.resolve(__dirname, 'src/utilities/')
}
通過resolve.modules可以指定node_modules的查找路徑充择,適用于一個(gè)大項(xiàng)目嵌套多個(gè)小項(xiàng)目的情況德玫,可以讓小項(xiàng)目共享相同的node_modules,但是如果是同一個(gè)包的不同版本,則不可用椎麦。
webpack的Code Splitting async
當(dāng)你的代碼打包后仍很大的時(shí)候宰僧,你就要考慮進(jìn)行代碼拆包了。把一些沒有必要立刻加載的代碼拆包观挎,并異步去加載琴儿。在webpack中,你可以通過import()和require.ensure來實(shí)現(xiàn)
import是es6的一個(gè)特性嘁捷,在webpack中造成。webpack會(huì)把import()命令識(shí)別成代碼切割的點(diǎn)(記住,import后面有括號(hào)包裹普气,包裹的為要加載的模塊路徑),而且webpack的import異步加載模塊是基于promise谜疤,這意味著低版本瀏覽器你需要加promise的polyfill。
而且import()需要你正確處理依賴項(xiàng),因?yàn)閣ebpack只是單純的將模塊當(dāng)獨(dú)拆包夷磕。如果需要處理依賴關(guān)系的化履肃,還是使用require.ensure比較合適。
webpck打包項(xiàng)目中包括第三方庫
在webpack打包中坐桩,經(jīng)常會(huì)遇到引用第三方庫的情況尺棋,這時(shí)候你可以將代碼打包成三塊(不包括拆包生成的小chunk)
1.webpack的模塊引入代碼。主要是webpackJsonp的實(shí)現(xiàn)和共同的代碼塊绵跷。
2.第三方庫
3.主要的業(yè)務(wù)代碼
要實(shí)現(xiàn)上述的三種分離膘螟。需要用到CommonsChunkPlugin來分離多次引用的chunk。用DllReferencePlugin和DllPlugin來分離第三方應(yīng)用碾局。
不過不建議通過這種方式打包第三方依賴庫荆残,還是直接使用第三方庫提供的dist版本吧,直接打包生成的可能是開發(fā)中版本而不是release版本净当。
externals的使用場(chǎng)景
如果在wepack中定義了externals内斯,webpack會(huì)在import、require的時(shí)候忽略對(duì)應(yīng)模塊像啼,并externals中對(duì)應(yīng)模塊的值賦給模塊俘闯。也就是說,該模塊不會(huì)被打包進(jìn)去最終的代碼忽冻。比如你externals設(shè)置了
并在代碼中對(duì)jquery進(jìn)行了引用
import jquery from "jquery"
webpack在打包的時(shí)候會(huì)在externals中匹配到j(luò)query真朗,從而只是簡(jiǎn)單的進(jìn)行變量替換
要注意的
webpack使用場(chǎng)景
1.處理代碼依賴。當(dāng)你項(xiàng)目復(fù)雜僧诚,需要引入許多靜態(tài)資源遮婶,而且靜態(tài)資源有依賴關(guān)系,優(yōu)先關(guān)系時(shí)
2.代碼的并包(多個(gè)靜態(tài)資源合并湖笨,在進(jìn)行模塊化開發(fā)一定會(huì)用到)
3.代碼的拆包(當(dāng)你的資源需要多個(gè)頁面復(fù)用而需要把共同的代碼分離蹭睡,以便用于瀏覽器緩存時(shí)。)
4.代碼構(gòu)建赶么,需要區(qū)分不同的生成環(huán)境時(shí)。(比如最常見的三層環(huán)境脊串。開發(fā)環(huán)境辫呻、測(cè)試環(huán)境、線上環(huán)境琼锋。你可以在開發(fā)環(huán)境搭建hmr來提高編譯效率放闺,在測(cè)試環(huán)境使用soucemap來方便測(cè)試debug,在線上環(huán)境壓縮混淆版本管理來減小帶寬消耗和利用緩存)
webpack調(diào)用方式
1.通過cli的方式(在終端中使用webpack命令缕坎,適合單獨(dú)文件需要簡(jiǎn)單處理的時(shí)候使用)
2.通過nodejs 的api方式 (適合多環(huán)境搭建的時(shí)候使用怖侦,比如區(qū)分開發(fā)環(huán)境、測(cè)試環(huán)境、線上環(huán)境等匾寝,如何區(qū)別搬葬?在cli中不同的命令指向不同的配置文件,不同的配置文件用define-plugin定義環(huán)境變量艳悔,在代碼中就可以直接使用這個(gè)變量了)