盤點一些面試經(jīng)常被問的webpack知識點
點擊下方“前端開發(fā)愛好者”,選擇“設(shè)為星標”
第一時間關(guān)注技術(shù)干貨!
前言
哈嘍,大家好 我是
xy???????。雖然Vite越來越火,但是作為前端構(gòu)建工具的霸主webpack依然成為面試必考熱點,于是周末匯總整理了webpack的常見面試題分享給大家,!!!
對 webpack 的理解?
webpack 是一個用于現(xiàn)代 JavaScript 應(yīng)用程序的「靜態(tài)模塊打包工具」。我們可以使用webpack管理模塊。因為在webpack看來,項目中的所有資源皆為模塊,通過分析模塊間的依賴關(guān)系,在其內(nèi)部構(gòu)建出一個依賴圖,最終編繹輸出模塊為 HTML、JavaScript、CSS 以及各種靜態(tài)文件(圖片、字體等),讓我們的開發(fā)過程更加高效。
webpack的主要作用如下:
-
模塊打包。可以將不同模塊的文件打包整合在一起,并且保證它們之間的引用正確,執(zhí)行有序。利用打包我們就可以在開發(fā)的時候根據(jù)我們自己的業(yè)務(wù)自由劃分文件模塊,保證項目結(jié)構(gòu)的清晰和可讀性。 -
編譯兼容。在前端的“上古時期”,手寫一堆瀏覽器兼容代碼一直是令前端工程師頭皮發(fā)麻的事情,而在今天這個問題被大大的弱化了,通過webpack的Loader機制,不僅僅可以幫助我們對代碼做polyfill,還可以編譯轉(zhuǎn)換諸如.less,.vue,.jsx這類在瀏覽器無法識別的格式文件,讓我們在開發(fā)的時候可以使用新特性和新語法做開發(fā),提高開發(fā)效率。 -
能力擴展。通過webpack的Plugin機制,我們在實現(xiàn)模塊化打包和編譯兼容的基礎(chǔ)上,可以進一步實現(xiàn)諸如按需加載,代碼壓縮等一系列功能,幫助我們進一步提高自動化程度,工程效率以及打包輸出的質(zhì)量。
webpack 的構(gòu)建流程?
webpack的運行流程是一個串行的過程,從啟動到結(jié)束會依次執(zhí)行以下流程:
-
初始化參數(shù):從配置文件和 Shell 語句中讀取與合并參數(shù),得出最終的參數(shù) -
開始編譯:用上一步得到的參數(shù)初始化 Compiler 對象,加載所有配置的插件,執(zhí)行對象的 run 方法開始執(zhí)行編譯 -
確定入口:根據(jù)配置中的 entry 找出所有的入口文件 -
編譯模塊:從入口文件出發(fā),調(diào)用所有配置的 loader 對模塊進行翻譯,再找出該模塊依賴的模塊,再遞歸本步驟直到所有入口依賴的文件都經(jīng)過了本步驟的處理 -
完成模塊編譯:在經(jīng)過上一步使用 loader 翻譯完所有模塊后,得到了每個模塊被翻譯后的最終內(nèi)容以及它們之間的依賴關(guān)系 -
輸出資源:根據(jù)入口和模塊之間的依賴關(guān)系,組裝成一個個包含多個模塊的 Chunk,再把每個 Chunk 轉(zhuǎn)換成一個單獨的文件加入到輸出列表,這步是可以修改輸出內(nèi)容的最后機會 -
輸出完成:在確定好輸出內(nèi)容后,根據(jù)配置確定輸出的路徑和文件名,把文件內(nèi)容寫入到文件系統(tǒng)
在以上過程中,webpack會在特定的時間點廣播出特定的事件,插件在監(jiān)聽到感興趣的事件后會執(zhí)行特定的邏輯,并且插件可以調(diào)用webpack提供的 API 改變webpack的運行結(jié)果。
「簡單說:」
-
初始化:啟動構(gòu)建,讀取與合并配置參數(shù),加載 Plugin,實例化 Compiler -
編譯:從 entry 出發(fā),針對每個 Module 串行調(diào)用對應(yīng)的 loader 去翻譯文件的內(nèi)容,再找到該 Module 依賴的 Module,遞歸地進行編譯處理 -
輸出:將編譯后的 Module 組合成 Chunk,將 Chunk 轉(zhuǎn)換成文件,輸出到文件系統(tǒng)中
常見的 loader 有哪些?
默認情況下,webpack只支持對js和json文件進行打包,但是像css、html、png等其他類型的文件,webpack則無能為力。因此,就需要配置相應(yīng)的loader進行文件內(nèi)容的解析轉(zhuǎn)換。
常用的loader如下:
-
image-loader:加載并且壓縮圖片文件。 -
less-loader:加載并編譯 LESS 文件。 -
sass-loader:加載并編譯 SASS/SCSS 文件。 -
css-loader:加載 CSS,支持模塊化、壓縮、文件導入等特性,使用css-loader必須要配合使用style-loader。 -
style-loader:用于將 CSS 編譯完成的樣式,掛載到頁面的 style 標簽上。需要注意loader執(zhí)行順序,style-loader要放在第一位,loader都是從后往前執(zhí)行。 -
babel-loader:把 ES6 轉(zhuǎn)換成 ES5 -
postcss-loader:擴展 CSS 語法,使用下一代 CSS,可以配合autoprefixer插件自動補齊 CSS3 前綴。 -
eslint-loader:通過 ESLint 檢查 JavaScript 代碼。 -
vue-loader:加載并編譯 Vue 組件。 -
file-loader:把文件輸出到一個文件夾中,在代碼中通過相對 URL 去引用輸出的文件 (處理圖片和字體) -
url-loader:與file-loader類似,區(qū)別是用戶可以設(shè)置一個閾值,大于閾值會交給file-loader處理,小于閾值時返回文件 base64 形式編碼 (處理圖片和字體)
更多 loader,點擊此處查看官方文檔[1]
常見的 plugin 有哪些?
webpack中的plugin賦予其各種靈活的功能,例如打包優(yōu)化、資源管理、環(huán)境變量注入等,它們會運行在webpack的不同階段(鉤子 / 生命周期),貫穿了webpack整個編譯周期。目的在于「解決 loader 無法實現(xiàn)的其他事」。
常用的plugin如下:
-
HtmlWebpackPlugin:簡化 HTML 文件創(chuàng)建 (依賴于 html-loader) -
mini-css-extract-plugin: 分離樣式文件,CSS 提取為獨立文件,支持按需加載 (替代 extract-text-webpack-plugin) -
clean-webpack-plugin: 目錄清理
更多 plugin,點擊此處查看官方文檔[2]
loader 和 plugin 的區(qū)別?
loader是文件加載器,能夠加載資源文件,并對這些文件進行一些處理,諸如編譯、壓縮等,最終一起打包到指定的文件中;plugin賦予了webpack各種靈活的功能,例如打包優(yōu)化、資源管理、環(huán)境變量注入等,目的是解決 loader無法實現(xiàn)的其他事。
在運行時機上,loader 運行在打包文件之前;plugin則是在整個編譯周期都起作用。
在配置上,loader在module.rules中配置,作為模塊的解析規(guī)則,類型為數(shù)組。每一項都是一個 Object,內(nèi)部包含了 test(類型文件)、loader、options (參數(shù))等屬性;plugin在 plugins中單獨配置,類型為數(shù)組,每一項是一個 plugin 的實例,參數(shù)都通過構(gòu)造函數(shù)傳入。
webpack 的熱更新原理是?
模塊熱替換(HMR \- hot module replacement),又叫做熱更新,在不需要刷新整個頁面的同時更新模塊,能夠提升開發(fā)的效率和體驗。熱更新時只會局部刷新頁面上發(fā)生了變化的模塊,同時可以保留當前頁面的狀態(tài),比如復(fù)選框的選中狀態(tài)等。
熱更新的核心就是客戶端從服務(wù)端拉去更新后的文件,準確的說是 chunk diff (chunk 需要更新的部分),實際上webpack-dev-server與瀏覽器之間維護了一個websocket,當本地資源發(fā)生變化時,webpack-dev-server會向瀏覽器推送更新,并帶上構(gòu)建時的hash,讓客戶端與上一次資源進行對比。客戶端對比出差異后會向webpack-dev-server發(fā)起 Ajax 請求來獲取更改內(nèi)容(文件列表、hash),這樣客戶端就可以再借助這些信息繼續(xù)向webpack-dev-server發(fā)起 jsonp 請求獲取該chunk的增量更新。
后續(xù)的部分(拿到增量更新之后如何處理?哪些狀態(tài)該保留?哪些又需要更新?)由HotModulePlugin 來完成,提供了相關(guān) API 以供開發(fā)者針對自身場景進行處理,像react-hot-loader和vue-loader都是借助這些 API 實現(xiàn)熱更新。
如何提高 webpack 的構(gòu)建速度?
-
代碼壓縮
-
JS 壓縮 webpack 4.0默認在生產(chǎn)環(huán)境的時候是支持代碼壓縮的,即mode=production模式下。實際上webpack 4.0默認是使用terser-webpack-plugin這個壓縮插件,在此之前是使用uglifyjs-webpack-plugin,兩者的區(qū)別是后者對 ES6 的壓縮不是很好,同時我們可以開啟parallel參數(shù),使用多進程壓縮,加快壓縮。 -
CSS 壓縮
CSS 壓縮通常是去除無用的空格等,因為很難去修改選擇器、屬性的名稱、值等。可以使用另外一個插件:css-minimizer-webpack-plugin。 -
HTML 壓縮
使用HtmlWebpackPlugin插件來生成 HTML 的模板時候,通過配置屬性minify進行 html 優(yōu)化。
module.exports = {
plugin:[
new HtmlwebpackPlugin({
minify:{
minifyCSS: false, // 是否壓縮css
collapseWhitespace: false, // 是否折疊空格
removeComments: true // 是否移除注釋
}
})
]
}
-
圖片壓縮
配置image-webpack-loader -
Tree Shaking
Tree Shaking是一個術(shù)語,在計算機中表示消除死代碼,依賴于 ES Module 的靜態(tài)語法分析(不執(zhí)行任何的代碼,可以明確知道模塊的依賴關(guān)系)。在webpack實現(xiàn)Tree shaking有兩種方案: -
usedExports:通過標記某些函數(shù)是否被使用,之后通過 Terser來進行優(yōu)化的
module.exports = {
...
optimization:{
usedExports
}
}
使用之后,沒被用上的代碼在webpack打包中會加入unused harmony export mul注釋,用來告知Terser在優(yōu)化時,可以刪除掉這段代碼。
sideEffects:跳過整個模塊/文件,直接查看該文件是否有副作用
sideEffects用于告知webpack compiler哪些模塊時有副作用,配置方法是在package.json中設(shè)置sideEffects屬性。如果sideEffects設(shè)置為false,就是告知webpack可以安全的刪除未用到的exports。如果有些文件需要保留,可以設(shè)置為數(shù)組的形式,如:
"sideEffecis":[
"./src/util/format.js",
"*.css" // 所有的css文件
]
-
縮小打包域
排除webpack不需要解析的模塊,即在使用loader的時候,在盡量少的模塊中去使用。可以借助include和exclude這兩個參數(shù),規(guī)定loader只在那些模塊應(yīng)用和在哪些模塊不應(yīng)用。 -
減少 ES6 轉(zhuǎn)為 ES5 的冗余代碼
使用bable-plugin-transform-runtime插件 -
提取公共代碼
通過配置CommonsChunkPlugin插件,將多個頁面的公共代碼抽離成單獨的文件
