1. 什么是webpack祈噪?
webpack是一個(gè)現(xiàn)代Javascript應(yīng)用程序的模塊打包器始藕,當(dāng)webpack處理應(yīng)用程序時(shí)扶叉,他會(huì)遞歸地構(gòu)建一個(gè)依賴關(guān)系圖臼节,其中包含應(yīng)用程序需要的每個(gè)模塊接剩,然后將所有這些模塊打包成一個(gè)或多個(gè)bundle切厘。
上邊是webpack給出的官方定義;我們可以很直觀的看出webpack作為一個(gè)打包工具懊缺,最大的優(yōu)點(diǎn)即是主動(dòng)疫稿,能夠根據(jù)入口文件分析你當(dāng)前的目錄結(jié)構(gòu),并且根據(jù)運(yùn)行按需加載依賴鹃两,也就是其解決前端開(kāi)發(fā)中最關(guān)鍵的問(wèn)題——按需加載遗座;下面詳細(xì)說(shuō)一下對(duì)webpack學(xué)習(xí)和查找資料后的理解認(rèn)識(shí)和總結(jié)。
2.為什么要有webpack俊扳?相比gulp 和 grunt 有什么不同點(diǎn)以及優(yōu)勢(shì)途蒋?
相對(duì)于前端打包工具,從grunt馋记、gulp 到 webpack号坡,期間有很多變動(dòng),但為什么webpack最終成了主流梯醒?這不得不從其核心說(shuō)起宽堆;那就是 按需加載,眾所周知茸习,我們使用打包工具的目的就是為了實(shí)現(xiàn)開(kāi)發(fā)模塊化畜隶,并且實(shí)現(xiàn)按需加載,以及支持后續(xù)所出現(xiàn)的coffeescript 、typeScript 和 ES6 等等籽慢,以上種種類目繁雜浸遗,如果使用gulp 或 grunt,那會(huì)是什么樣子呢嗡综?看下下面兩張圖:
這是gulp的工作原理
[圖片上傳失敗...(image-c0592b-1512395774697)]
這是webpack的工作原理
[圖片上傳失敗...(image-d947ff-1512395774697)]
從上面可以看出乙帮,gulp只是一個(gè)可以根據(jù)要求操作文件的工具,無(wú)論是壓縮极景、轉(zhuǎn)譯輸出等等察净,并沒(méi)有靈活的實(shí)現(xiàn)真正的按需加載和模塊化,它也不是基于你的代碼進(jìn)行進(jìn)行文件操作盼樟,而是基于task任務(wù)配置進(jìn)行工作氢卡;雖然 webpack 也做的是同樣的事情,但是webpack可以針對(duì)代碼中的require 和 import 的不同類型的文件使用不同的 loader 做處理晨缴,由于 webpack 有依賴樹(shù)和 loader 技術(shù)译秦,除了js,所有的assets資源都是采用了動(dòng)態(tài)綁定的處理方式击碗,也就是對(duì)應(yīng)的loader筑悴,這樣每個(gè)模塊model都聲明了自己的依賴,因此稍途,webpack就可以僅僅打包那些用到的模塊阁吝。
3.webpack基礎(chǔ)配置項(xiàng)參數(shù)
這里是提醒自己一點(diǎn):
webpack是開(kāi)發(fā)階段的一個(gè)依賴項(xiàng),不是運(yùn)行時(shí)候的依賴項(xiàng)械拍,開(kāi)發(fā)完成之后突勇,你的前端庫(kù)是被別人依賴的,而別人用的時(shí)候是不需要webpack存在的坷虑,所以對(duì)于局部項(xiàng)目的安裝應(yīng)該這樣:
npm install webpack --save-dev
webpack的配置也是提供一個(gè)配置文件的甲馋,那就是 webpack.config.js,對(duì)于項(xiàng)目的操作需要webpack的支持的配置參數(shù)都可以寫(xiě)入迄损,啟動(dòng)webpack后定躏,webpack會(huì)讀取配置文件中相應(yīng)的參數(shù),并執(zhí)行后續(xù)相應(yīng)的操作芹敌。
最基礎(chǔ)版 webpack.config.js
module.exports = {
entry: __dirname + '/src/index.js',
output: {
path: __dirname + '/public/js',
filname: 'app.js'
},
devtool: 'source-map' // 后續(xù)說(shuō)明
}
4.webpack核心概念
關(guān)于webpack的核心共屈,其實(shí)也就是如何解決依賴打包、模塊化的問(wèn)題党窜,相對(duì)于gulp和grunt的手動(dòng)添加依賴拗引,webpack實(shí)現(xiàn)了自動(dòng)分析,它可以直接自動(dòng)分析入口文件中的依賴幌衣,判斷當(dāng)前文件中是否需要加載某個(gè)依賴文件矾削,然后將當(dāng)前需要加載的依賴打包壤玫,無(wú)需對(duì)無(wú)關(guān)依賴進(jìn)行手動(dòng)更改,從而保證依賴打包的模塊化加載哼凯。
- entry配置
entry作為依賴關(guān)系的入口位置欲间,有著關(guān)鍵作用;在webpack中断部,這個(gè) entry 可不止一個(gè)猎贴,它的類型可以是對(duì)象、字符串蝴光、數(shù)組她渴;
entry: ['entry', './entry_']
如果它是一個(gè)路徑字符串,則它最終會(huì)與context 配置一起 resolve 一個(gè)絕對(duì)的 url蔑祟;
/*
* 這是之前一個(gè)vue項(xiàng)目中剛使用webpack的時(shí)候
* 使用的一個(gè)模板配置趁耗,可以說(shuō)是很無(wú)腦了
* 根據(jù)絕對(duì)路徑,在當(dāng)前項(xiàng)目默認(rèn)的src下訪問(wèn)main.js
* 然后根據(jù)main中的import 和 require 進(jìn)行相應(yīng)加載和導(dǎo)入
*/
entry: {
app: './src/main.js'
}
如果字符串是相對(duì)路徑疆虚,則會(huì)根據(jù)context配置的路徑查找一個(gè)相對(duì)路徑苛败。(所以這里一般使用path來(lái)解決路徑問(wèn)題)。
entry: {
app: path.resolve(__dirname, './src/index.js'),
page: ['./entry','./entry_'] // 這里webpack會(huì)按序打包径簿,但是只導(dǎo)出最后一個(gè)文件
}
對(duì)于編譯后的輸出罢屈,除了基本的output路徑配置,還要配置輸出的文件名篇亭。
output: {
path: path.resolve(__dirname,'dist'), //這里的dist相信都比較眼熟了
filename: '[name]-[chunkhash].js'
/*
* 這里使用的 name 是使用的占位符缠捌,輸出文件名即 entry 入口進(jìn)入的文件名
* chunkhash 是為了輸出后的文件名的hash值相同
**/
}
對(duì)于多頁(yè)面復(fù)雜應(yīng)用的入口配置,可以使用 commonChunkPlugin 插件進(jìn)行暗赶,保證入口對(duì)公共模塊的抽離。
- module 配置
module 是webpack中進(jìn)行模塊加載時(shí)所需要的配置肃叶;在進(jìn)行模塊加載的時(shí)候需要使用不同的loader對(duì)不同的模塊進(jìn)行處理蹂随,這里的核心就是根據(jù)所需加載模塊的不同,要配置相關(guān)的loader因惭;比如:
// 這是之前一個(gè)項(xiàng)目模板的配置之一
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig,
include: [
path.resolve(...)
] // 每一個(gè) resolve 表示一個(gè)需要被loader處理的路徑
},
...
]
}
test 屬性: 也就是應(yīng)該被 loader 識(shí)別岳锁,然后進(jìn)行轉(zhuǎn)換操作的文件 。
loader 屬性:對(duì)對(duì)應(yīng) test 進(jìn)行處理操作的模塊蹦魔。
use 屬性:轉(zhuǎn)換相應(yīng)的文件激率,使其支持瀏覽器,并且能夠被添加到依賴樹(shù)中勿决。
- resolve 配置
先貼一個(gè)項(xiàng)目模板的配置(現(xiàn)在看都不知道當(dāng)時(shí)怎么寫(xiě)的乒躺,逃)
resolve: {
extensions: ['.js','.vue','.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src')
}
}
alias 屬性:有些文件名很長(zhǎng),或者路徑比較長(zhǎng)低缩,如果單純的每個(gè)依賴都去完全寫(xiě)入嘉冒,會(huì)增加多余的代碼量曹货;這里配置alias后,可以通過(guò)別名去代替對(duì)應(yīng)的路徑讳推。
這里舉個(gè)例子: 如果說(shuō)代碼中有 require('@/index')顶籽,webpack會(huì)首先發(fā)現(xiàn)這個(gè)別名,然后根據(jù)你的 alias 中的配置银觅,搜索相應(yīng)的別名對(duì)應(yīng)的路徑礼饱,然后根據(jù) extensions 中的設(shè)定的依賴的擴(kuò)展名,依次在對(duì)應(yīng)目錄進(jìn)行查找究驴,比如找到了 index.vue镊绪,那么就根據(jù)配置文件中 module 的設(shè)置,調(diào)用vue-loader 來(lái)處理這個(gè) index.vue 模塊纳胧,這是一個(gè)局部的基本流程镰吆。