webpack官網(wǎng):https://webpack.js.org/
webpack中文文檔: https://www.webpackjs.com/concepts/

1.什么是webpack
概念:本質(zhì)上,webpack 是一個(gè)現(xiàn)代 JavaScript 應(yīng)用程序的靜態(tài)模塊打包器(module bundler)。當(dāng) webpack 處理應(yīng)用程序時(shí),它會(huì)遞歸地構(gòu)建一個(gè)依賴(lài)關(guān)系圖(dependency graph),其中包含應(yīng)用程序需要的每個(gè)模塊,然后將所有這些模塊打包成一個(gè)或多個(gè) bundle。
簡(jiǎn)單理解:webpack是一個(gè)打包模塊化javascript的工具,在webpack里一切文件皆模塊,通過(guò)loader轉(zhuǎn)換文件,通過(guò)plugin注入鉤子,最后輸出由多個(gè)模塊組合成的文件,webpack專(zhuān)注構(gòu)建模塊化項(xiàng)目。
WebPack可以看做是模塊打包機(jī):它做的事情是,分析你的項(xiàng)目結(jié)構(gòu),找到JavaScript模塊以及其它的一些瀏覽器不能直接運(yùn)行的拓展語(yǔ)言(Scss,TypeScript等),并將其打包為合適的格式以供瀏覽器使用。
2.基本使用
webpack基本使用




配置完訪問(wèn)localhost:8080可以直接訪問(wèn)頁(yè)面(不配置的話訪問(wèn)看到的頁(yè)面是項(xiàng)目目錄,然后再點(diǎn)擊進(jìn)去訪問(wèn))

配置完運(yùn)行npm run dev打包之后可以直接打開(kāi)頁(yè)面,不用再?gòu)?fù)制訪問(wèn)地址。
webapck的加載器loader

沒(méi)有l(wèi)oader加載器打包c(diǎn)ss文件報(bào)錯(cuò):

基本使用:





webpack默認(rèn)不打包樣式表中的圖片,如css文件中的背景圖片的url。所以需要借助url-loader來(lái)進(jìn)行打包,否則會(huì)報(bào)錯(cuò)。

幾個(gè)常見(jiàn)的loader
file-loader:把文件輸出到一個(gè)文件夾中,在代碼中通過(guò)相對(duì) URL 去引用輸出的文件
url-loader:和 file-loader 類(lèi)似,但是能在文件很小的情況下以 base64 的方式把文件內(nèi)容注入到代碼中去
source-map-loader:加載額外的 Source Map 文件,以方便斷點(diǎn)調(diào)試
image-loader:加載并且壓縮圖片文件
babel-loader:把 ES6 轉(zhuǎn)換成 ES5
css-loader:加載 CSS,支持模塊化、壓縮、文件導(dǎo)入等特性
style-loader:把 CSS 代碼注入到 JavaScript 中,通過(guò) DOM 操作去加載 CSS。
eslint-loader:通過(guò) ESLint 檢查 JavaScript 代碼
webpack中的plugin
什么是plugin
plugin是一個(gè)具有 apply方法的 js對(duì)象。 apply方法會(huì)被 webpack的 compiler(編譯器)對(duì)象調(diào)用,并且 compiler 對(duì)象可在整個(gè) compilation(編譯)生命周期內(nèi)訪問(wèn)。
一個(gè)plugin看起來(lái)大概是這個(gè)樣子:
function CustomPlugin(options){
// options是配置文件,你可以在這里進(jìn)行一些與options相關(guān)的工作
}
?
// 每個(gè)plugin都必須定義一個(gè)apply方法,webpack會(huì)自動(dòng)調(diào)用這個(gè)方法
CustomPlugin.prototype.apply = function(compiler){
......
});
}
?
module.exports = CustomPlugin;
plugin有什么用
plugin是webpack核心功能,通過(guò)plugin(插件)webpack可以實(shí)現(xiàn)loader所不能完成的復(fù)雜功能,使用plugin豐富的自定義API,可以控制webpack編譯流程的每個(gè)環(huán)節(jié),實(shí)現(xiàn)對(duì)webpack的自定義功能擴(kuò)展。
舉例 我們實(shí)際項(xiàng)目中就使用了HtmlWebpackPlugin插件,它幫助我們做了下面幾件事兒:
在工程打包成功后會(huì)自動(dòng)生成一個(gè)html模板文件
同時(shí)所依賴(lài)的CSS/JS也都會(huì)被自動(dòng)引入到這個(gè)html模板文件中
設(shè)置生成hash添加在引入文件地址的末尾,類(lèi)似于我們常用的時(shí)間戳,來(lái)解決可能會(huì)遇到的緩存問(wèn)題。
使用plugin
在 webpack 配置文件(webpack.config.js)中,向 plugins 屬性傳入 new 實(shí)例即可。比如:
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
module.exports = {
module: {
loaders: [
{
test: /\.(js|jsx)$/,
loader: 'babel-loader'
}
]
},
plugins: [
new webpack.optimize.UglifyJsPlugin(), //訪問(wèn)內(nèi)置的插件
new HtmlWebpackPlugin({template: './src/index.html'}) //訪問(wèn)第三方插件
]
};
注意
webpack中的插件分為內(nèi)置插件和第三方插件
內(nèi)置插件不需要額外安裝依賴(lài),如上面的例子中:UglifyJsPlugin插件
如果是第三方插件,如上面的例子中HtmlWebpackPlugin插件,則使用之前需要進(jìn)行安裝:
npm install html-webpack-plugin --save-dev</pre>
幾個(gè)常見(jiàn)的plugin
BannerPlugin:對(duì)所有的文件打包后添加一個(gè)版權(quán)聲明
uglifyjs-webpack-plugin: 對(duì)JS進(jìn)行壓縮混淆
HtmlWebpackPlugin:可以根據(jù)模板自動(dòng)生成html代碼,并自動(dòng)引用css和js文件
Hot Module Replacement:在每次修改代碼保存后,瀏覽器會(huì)自動(dòng)刷新,實(shí)時(shí)預(yù)覽修改后的效果
copy-webpack-plugin:通過(guò)Webpack來(lái)拷貝文件
extract-text-webpack-plugin:將js文件和css文件分別單獨(dú)打包,不混在一個(gè)文件中
DefinePlugin 編譯時(shí)配置全局變量,這對(duì)開(kāi)發(fā)模式和發(fā)布模式的構(gòu)建允許不同的變量時(shí)非常有用
optimize-css-assets-webpack-plugin 不同組件中重復(fù)的css可以快速去重
更多可點(diǎn)擊這里查看。
3.vue-loader


4.vue中配置webpack

5. 關(guān)閉eslint
在vue.config.js文件中添加一項(xiàng)lintOnSave: false和在devServer項(xiàng)中設(shè)置overlay中的錯(cuò)誤提示為false。
module.exports = {
devServer: {
port: 8081,
open: true,
overlay: {
warnings: false,
errors: false
}
},
lintOnSave: false
}
6.webpack優(yōu)缺點(diǎn)
webpack有哪些優(yōu)點(diǎn)
專(zhuān)注于處理模塊化的項(xiàng)目,能做到開(kāi)箱即用,一步到位
可通過(guò)plugin擴(kuò)展,完整好用又不失靈活
使用場(chǎng)景不局限于web開(kāi)發(fā)
社區(qū)龐大活躍,經(jīng)常引入緊跟時(shí)代發(fā)展的新特性,能為大多數(shù)場(chǎng)景找到已有的開(kāi)源擴(kuò)展
良好的開(kāi)發(fā)體驗(yàn)
webpack的缺點(diǎn)
- webpack的缺點(diǎn)是只能用于采用模塊化開(kāi)發(fā)的項(xiàng)目
7.分別介紹bundle,chunk,module是什么
bundle:是由webpack打包出來(lái)的文件。 chunk:代碼塊,一個(gè)chunk由多個(gè)模塊組合而成,用于代碼的合并和分割。 module:是開(kāi)發(fā)中的單個(gè)模塊,在webpack的世界,一切皆模塊,一個(gè)模塊對(duì)應(yīng)一個(gè)文件,webpack會(huì)從配置的entry中遞歸開(kāi)始找出所有依賴(lài)的模塊。
8.分別介紹什么是loader?什么是plugin
loader:模塊轉(zhuǎn)換器,用于將模塊的原內(nèi)容按照需要轉(zhuǎn)成你想要的內(nèi)容。 plugin:在webpack構(gòu)建流程中的特定時(shí)機(jī)注入擴(kuò)展邏輯,來(lái)改變構(gòu)建結(jié)果,是用來(lái)自定義webpack打包過(guò)程的方式,一個(gè)插件是含有apply方法的一個(gè)對(duì)象,通過(guò)這個(gè)方法可以參與到整個(gè)webpack打包的各個(gè)流程(生命周期)。
9.什么是模塊熱更新
模塊熱更新是webpack的一個(gè)功能,他可以使得代碼修改過(guò)后不用刷新瀏覽器就可以更新,是高級(jí)版的自動(dòng)刷新瀏覽器。 devServer中通過(guò)hot屬性可以空時(shí)模塊的熱替換
1,通過(guò)配置文件
const webpack = require('webpack');
const path = require('path');
let env = process.env.NODE_ENV == "development" ? "development" : "production";
const config = {
mode: env,
devServer: {
hot:true
}
}
plugins: [
new webpack.HotModuleReplacementPlugin(), //熱加載插件
],
module.exports = config;</pre>
2,通過(guò)命令行
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "NODE_ENV=development webpack-dev-server --config webpack.develop.config.js --hot",
}
10.什么是Tree-shaking
Tree-shaking可以用來(lái)剔除javascript中不用的死代碼,它依賴(lài)靜態(tài)的es6模塊化語(yǔ)法,例如通過(guò)哦import 和export 導(dǎo)入導(dǎo)出,Tree-shaking最先在rollup中出現(xiàn),webpack在2.0中將其引入,css中使用Tree-shaking需要引入Purify-CSS。
11.通過(guò)webpack處理長(zhǎng)緩存
瀏覽器在用戶(hù)訪問(wèn)頁(yè)面的時(shí)候,為了加快加載速度,會(huì)對(duì)用戶(hù)訪問(wèn)的靜態(tài)資源進(jìn)行存儲(chǔ),但是每一次代碼升級(jí)或是更新,都需要瀏覽器去下載新的代碼,最方便和簡(jiǎn)單的更新方式就是引入新的文件名稱(chēng)。在webpack中可以在output縱輸出的文件指定chunkhash,并且分離經(jīng)常更新的代碼和框架代碼。通過(guò)NameModulesPlugin或是HashedModuleIdsPlugin使再次打包文件名不變。
12.如何提高webpack的構(gòu)建速度
1. 通過(guò)externals配置來(lái)提取常用庫(kù)
2. 利用DllPlugin和DllReferencePlugin預(yù)編譯資源模塊
通過(guò)DllPlugin來(lái)對(duì)那些我們引用但是絕對(duì)不會(huì)修改的npm包來(lái)進(jìn)行預(yù)編譯,再通過(guò)DllReferencePlugin將預(yù)編譯的模塊加載進(jìn)來(lái)。
3. 使用Happypack 實(shí)現(xiàn)多線程加速編譯
要注意的第一點(diǎn)是,它對(duì)file-loader和url-loader支持不好,所以這兩個(gè)loader就不需要換成happypack了,其他loader可以類(lèi)似地?fù)Q一下
4. 使用Tree-shaking和Scope Hoisting來(lái)剔除多余代碼
5. 使用fast-sass-loader代替sass-loader
6. babel-loader開(kāi)啟緩存
babel-loader在執(zhí)行的時(shí)候,可能會(huì)產(chǎn)生一些運(yùn)行期間重復(fù)的公共文件,造成代碼體積大冗余,同時(shí)也會(huì)減慢編譯效率。 可以加上cacheDirectory參數(shù)或使用 transform-runtime 插件試試。
// webpack.config.js
use: [{
loader: 'babel-loader',
options: {
cacheDirectory: true
}]
// .bablerc
{
"presets": [
"env",
"react"
],
"plugins": ["transform-runtime"]
}
7. 不需要打包編譯的插件庫(kù)換成全局"script"標(biāo)簽引入的方式
比如jQuery插件,react, react-dom等,代碼量是很多的,打包起來(lái)可能會(huì)很耗時(shí) 可以直接用標(biāo)簽引入,然后在webpack配置里使用 expose-loader 或 externals 或 ProvidePlugin 提供給模塊內(nèi)部使用相應(yīng)的變量。
// @1
use: [{
loader: 'expose-loader',
options: '/pre>
}, {
loader: 'expose-loader',
options: 'jQuery'
}]
// @2
externals: {
jquery: 'jQuery'
},
// @3
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery'
})
8. 優(yōu)化構(gòu)建時(shí)的搜索路徑
在webpack打包時(shí),會(huì)有各種各樣的路徑要去查詢(xún)搜索,我們可以加上一些配置,讓它搜索地更快 比如說(shuō),方便改成絕對(duì)路徑的模塊路徑就改一下,以純模塊名來(lái)引入的可以加上一些目錄路徑 還可以善于用下resolve alias別名 這個(gè)字段來(lái)配置。 還有exclude等的配置,避免多余查找的文件,比如使用babel別忘了剔除不需要遍歷的。
參考鏈接
webpack面試題匯總
Webpack打包構(gòu)建太慢了?試試幾個(gè)方法
關(guān)于webpack的面試題總結(jié)