Webpack 高頻面試題匯總

# 什么是 webpack

webpack 是個(gè)靜態(tài)模塊打包工具。在 webpack 看來,項(xiàng)目里所有資源皆模塊,利用資源依賴關(guān)系萍肆,把各模塊之間關(guān)聯(lián)起來袍榆。
簡(jiǎn)單講就: webpack 對(duì)有依賴關(guān)系的多個(gè)模塊文件進(jìn)行打包處理后,生成瀏覽器可以直接 高效運(yùn)行的資源塘揣。
通過 入口文件 開始包雀,利用 遞歸 找到直接依賴或間接依賴的所有模塊,并在內(nèi)部構(gòu)建一個(gè)能映射出項(xiàng)目所需的所有模塊的 依賴圖勿负,并進(jìn)行 webpack 打包生成一個(gè)或多個(gè) bundle 文件馏艾。

打包是用的 webpack 命令即:npm webpack
webpack 4.x 開始,把 webpack 拆成 webpackwebpack-cli 兩部分奴愉,分工如下:
webpack: 負(fù)責(zé) Js 的打包工作
webpack-cli:解析 webpack 命令,命令內(nèi)部使用 webpack 的功能
并且 webpack 能解析打包各種模塊規(guī)范的 Js 代碼铁孵,包括:ES6锭硼、Commonjs、AND/Requirejs 以及 CMD/Seajs蜕劝。

優(yōu)點(diǎn)

  1. 專注于處理模塊化的項(xiàng)目檀头,能做到開箱即用,一步到位
  2. 可通過 plugin 擴(kuò)展岖沛,完整好用又不失靈活
  3. 使用場(chǎng)景不局限于 web 開發(fā)
  4. 社區(qū)龐大活躍暑始,經(jīng)常引入緊跟時(shí)代發(fā)展的新特性,能為大多數(shù)場(chǎng)景找到已有的開源擴(kuò)展
  5. 良好的開發(fā)體驗(yàn)

缺點(diǎn)

只能用于采用模塊化開發(fā)的項(xiàng)目

# 什么是 loader ? 什么是 plugin ?

loader:模塊轉(zhuǎn)換器婴削,webpack 將一切文件視為模塊廊镜,但 webpack 只能解析 JavaScript 文件,而 loader 作用是讓 webpack 擁有了加載 和 解析非 JavaScript 文件的能力唉俗。

plugin:在 webpack 構(gòu)建流程中的特定時(shí)機(jī)注入擴(kuò)展邏輯嗤朴,讓它具有更多的靈活性。在 webpack 運(yùn)行的生命周期中會(huì)廣播出許多事件虫溜,plugin 可以監(jiān)聽這些事件雹姊,在合適的時(shí)機(jī)通過 webpack 提供的 API 改變輸出結(jié)果。

用法的區(qū)別:

Loadermodule.rules 中配置衡楞,也就是說他作為模塊的解析規(guī)則而存在吱雏。 類型為數(shù)組,每一項(xiàng)都是一個(gè)Object瘾境,里面描述了對(duì)于什么類型的文件(test)歧杏,使用什么加載(loader)和使用的參數(shù)(options)
Pluginplugins 中單獨(dú)配置。 類型為數(shù)組寄雀,每一項(xiàng)是一個(gè) plugin 的實(shí)例得滤,參數(shù)都通過構(gòu)造函數(shù)傳入。

# 有哪些常見的 Loader 盒犹?他們是解決什么問題的懂更?

file-loader:把文件輸出到一個(gè)文件夾中眨业,在代碼中通過相對(duì) URL 去引用輸出的文件
url-loader:和 file-loader 類似,但是能在文件很小的情況下以 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 中聘殖,通過 DOM 操作去加載 CSS。
eslint-loader:通過 ESLint 檢查 JavaScript 代碼
svg-inline-loader:將壓縮后的 SVG 內(nèi)容注入代碼中
json-loader : 加載 JSON 文件(默認(rèn)包含)
ts-loader : 將 TypeScript 轉(zhuǎn)換成 JavaScript
awesome-typescript-loader:將 TypeScript 轉(zhuǎn)換成 JavaScript行瑞,性能優(yōu)于 ts-loader
sass-loader:將 CSS 代碼注入 JavaScript 中奸腺,通過 DOM 操作去加載 CSS
postcss-loader:擴(kuò)展 CSS 語法,使用下一代 CSS血久,可以配合 autoprefixer 插件自動(dòng)補(bǔ)齊 CSS3 前綴
tslint-loader:通過 TSLint檢查 TypeScript 代碼
vue-loader:加載 Vue.js 單文件組件

# 有哪些常見的 Plugin突照?他們是解決什么問題的?

define-plugin:定義環(huán)境變量
commons-chunk-plugin:提取公共代碼
terser-webpack-plugin : 支持壓縮 ES6 (Webpack4)
ignore-plugin:忽略部分文件
html-webpack-plugin:簡(jiǎn)化 HTML 文件創(chuàng)建 (依賴于 html-loader)
web-webpack-plugin:可方便地為單頁應(yīng)用輸出 HTML氧吐,比 html-webpack-plugin 好用
mini-css-extract-plugin : 分離樣式文件讹蘑,CSS 提取為獨(dú)立文件,支持按需加載
serviceworker-webpack-plugin:為網(wǎng)頁應(yīng)用增加離線緩存功能
clean-webpack-plugin : 刪除打包文件
happypack:實(shí)現(xiàn)多線程加速編譯

# 如何利用 webpack 來優(yōu)化前端性能筑舅?

webpack 優(yōu)化前端性能是指優(yōu)化 webpack 的輸出結(jié)果座慰,讓打包的最終結(jié)果在瀏覽器運(yùn)行快速高效。

1.壓縮代碼翠拣。刪除多余的代碼版仔、注釋、簡(jiǎn)化代碼的寫法等等方式心剥。
UglifyJsPluginParallelUglifyPlugin 壓縮JS文件
mini-css-extract-plugin 壓縮 CSS

  1. 利用 CDN 加速邦尊。在構(gòu)建過程中,將引用的靜態(tài)資源路徑修改為CDN上對(duì)應(yīng)的路徑优烧〔踝幔可以利用 webpack 對(duì)于output 參數(shù)和各 loaderpublicPath 參數(shù)來修改資源路徑
  2. 刪除死代碼。JS 用 Tree Shaking畦娄,CSS 需要使用 Purify-CSS
  3. 提取公共代碼又沾。用 CommonsChunkPlugin 插件

# 分別介紹 bundle,chunk熙卡,module 是什么

bundle:是由 webpack 打包出來的文件杖刷,
chunk:代碼塊,一個(gè) chunk 由多個(gè)模塊組合而成驳癌,用于代碼的合并和分割滑燃。
module:是開發(fā)中的單個(gè)模塊,在 webpack 的世界颓鲜,一切皆模塊表窘,一個(gè)模塊對(duì)應(yīng)一個(gè)文件典予,webpack 會(huì)從配置的 entry 中遞歸開始找出所有依賴的模塊。

.說一下 webpack 的熱更新原理吧

熱更新又稱熱替換(Hot Module Replacement)乐严,縮寫為 HMR瘤袖,基于 webpack-dev-server
當(dāng)你對(duì)代碼修改并保存后昂验,將會(huì)對(duì)代碼進(jìn)行重新打包捂敌,并將改動(dòng)的模塊發(fā)送到瀏覽器端,瀏覽器用新的模塊替換掉舊的模塊既琴,去實(shí)現(xiàn)局部更新頁面而非整體刷新頁面占婉。

# webpack 的構(gòu)建流程是什么?

webpack 的運(yùn)行流程是一個(gè)串行的過程,從啟動(dòng)到結(jié)束會(huì)依次執(zhí)行以下流程:

  1. 初始化參數(shù):從配置文件 和 Shell 語句中讀取與合并參數(shù)甫恩,得出最終的參數(shù)锐涯;
  2. 開始編譯:用上一步得到的參數(shù)初始化 Compiler 對(duì)象,加載所有配置的插件填物,執(zhí)行對(duì)象的 run 方法開始執(zhí)行編譯;
  3. 確定入口:根據(jù)配置中的 entry 找出所有的入口文件霎终;
  4. 編譯模塊:從入口文件出發(fā)滞磺,調(diào)用所有配置的 Loader 對(duì)模塊進(jìn)行翻譯,再找出該模塊依賴的模塊莱褒,再遞歸本步驟直到所有入口依賴的文件都經(jīng)過了本步驟的處理击困;
    完成模塊編譯:在經(jīng)過第4步使用 Loader 翻譯完所有模塊后,得到了每個(gè)模塊被翻譯后的最終內(nèi)容以及它們之間的依賴關(guān)系广凸;
  5. 輸出資源:根據(jù)入口和模塊之間的依賴關(guān)系阅茶,組裝成一個(gè)個(gè)包含多個(gè)模塊的 Chunk,再把每個(gè) Chunk 轉(zhuǎn)換成一個(gè)單獨(dú)的文件加入到輸出列表谅海,這步是可以修改輸出內(nèi)容的最后機(jī)會(huì)脸哀;
  6. 輸出完成:在確定好輸出內(nèi)容后,根據(jù)配置確定輸出的路徑和文件名扭吁,把文件內(nèi)容寫入到文件系統(tǒng)撞蜂。
    在以上過程中,webpack 會(huì)在特定的時(shí)間點(diǎn)廣播出特定的事件侥袜,插件在監(jiān)聽到感興趣的事件后會(huì)執(zhí)行特定的邏輯蝌诡,并且插件可以調(diào)用 webpack 提供的 API 改變 webpack 的運(yùn)行結(jié)果。

# 如何提高 webpack 的構(gòu)建速度枫吧?

  1. 多入口情況下浦旱,使用 CommonsChunkPlugin 來提取公共代碼
  2. 通過externals配置來提取常用庫
  3. 利用 DllPluginDllReferencePlugin 預(yù)編譯資源模塊 通過 DllPlugin 來對(duì)那些我們引用但是絕對(duì)不會(huì)修改的npm包來進(jìn)行預(yù)編譯,再通過 DllReferencePlugin 將預(yù)編譯的模塊加載進(jìn)來九杂。
  4. 使用 Happypack 實(shí)現(xiàn)多線程加速編譯
  5. 使用 webpack-uglify-parallel 來提升 uglifyPlugin 的壓縮速度颁湖。 原理上 webpack-uglify-parallel 采用了多核并行壓縮來提升壓縮速度
  6. 使用 Tree-shakingScope Hoisting 來剔除多余代碼

# webpack 文件之間相互依賴如何處理宣蠕?

.npm 打包時(shí)需要注意哪些?如何利用 webpack 來更好的構(gòu)建爷狈?

npm 是目前最大的 JavaScript 模塊倉庫植影,里面有來自全世界開發(fā)者上傳的可復(fù)用模塊。你可能只是 JS 模塊的使用者涎永,但是有些情況你也會(huì)去選擇上傳自己開發(fā)的模塊思币。 關(guān)于 NPM 模塊上傳的方法可以去官網(wǎng)上進(jìn)行學(xué)習(xí),這里只講解如何利用webpack來構(gòu)建羡微。

NPM模塊需要注意以下問題:

要支持 CommonJS 模塊化規(guī)范谷饿,所以要求打包后的最后結(jié)果也遵守該規(guī)則。
Npm模塊使用者的環(huán)境是不確定的妈倔,很有可能并不支持ES6博投,所以打包的最后結(jié)果應(yīng)該是采用ES5編寫的。并且如果ES5是經(jīng)過轉(zhuǎn)換的盯蝴,請(qǐng)最好連同SourceMap一同上傳毅哗。
Npm包大小應(yīng)該是盡量小(有些倉庫會(huì)限制包大信跬Α)
發(fā)布的模塊不能將依賴的模塊也一同打包虑绵,應(yīng)該讓用戶選擇性的去自行安裝。這樣可以避免模塊應(yīng)用者再次打包時(shí)出現(xiàn)底層模塊被重復(fù)打包的情況闽烙。
UI組件類的模塊應(yīng)該將依賴的其它資源文件翅睛,例如.css文件也需要包含在發(fā)布的模塊里。
基于以上需要注意的問題黑竞,我們可以對(duì)于webpack配置做以下擴(kuò)展和優(yōu)化:

CommonJS模塊化規(guī)范的解決方案: 設(shè)置output.libraryTarget='commonjs2'使輸出的代碼符合CommonJS2 模塊化規(guī)范捕发,以供給其它模塊導(dǎo)入使用
輸出ES5代碼的解決方案:使用babel-loader把 ES6 代碼轉(zhuǎn)換成 ES5 的代碼。再通過開啟devtool: 'source-map'輸出SourceMap以發(fā)布調(diào)試很魂。
Npm包大小盡量小的解決方案:Babel 在把 ES6 代碼轉(zhuǎn)換成 ES5 代碼時(shí)會(huì)注入一些輔助函數(shù)扎酷,最終導(dǎo)致每個(gè)輸出的文件中都包含這段輔助函數(shù)的代碼,造成了代碼的冗余莫换。解決方法是修改.babelrc文件霞玄,為其加入transform-runtime插件
不能將依賴模塊打包到NPM模塊中的解決方案:使用externals配置項(xiàng)來告訴webpack哪些模塊不需要打包。
對(duì)于依賴的資源文件打包的解決方案:通過css-loader和extract-text-webpack-plugin來實(shí)現(xiàn)

.文件指紋是什么拉岁?怎么用坷剧?

文件指紋是打包后輸出的文件名的后綴。

Hash:和整個(gè)項(xiàng)目的構(gòu)建相關(guān)喊暖,只要項(xiàng)目文件有修改惫企,整個(gè)項(xiàng)目構(gòu)建的 hash 值就會(huì)更改
Chunkhash:和 Webpack 打包的 chunk 有關(guān),不同的 entry 會(huì)生出不同的 chunkhash
Contenthash:根據(jù)文件內(nèi)容來定義 hash,文件內(nèi)容不變狞尔,則 contenthash 不變

JS的文件指紋設(shè)置
設(shè)置 output 的 filename丛版,用 chunkhash。

module.exports = {
    entry: {
        app: './scr/app.js',
        search: './src/search.js'
    },
    output: {
        filename: '[name][chunkhash:8].js',
        path:__dirname + '/dist'
    }
}

CSS的文件指紋設(shè)置
設(shè)置 MiniCssExtractPlugin 的 filename偏序,使用 contenthash页畦。

module.exports = {
    entry: {
        app: './scr/app.js',
        search: './src/search.js'
    },
    output: {
        filename: '[name][chunkhash:8].js',
        path:__dirname + '/dist'
    },
    plugins:[
        new MiniCssExtractPlugin({
            filename: `[name][contenthash:8].css`
        })
    ]
}

圖片的文件指紋設(shè)置
設(shè)置file-loader的name,使用hash研儒。

占位符名稱及含義

ext 資源后綴名
name 文件名稱
path 文件的相對(duì)路徑
folder 文件所在的文件夾
contenthash 文件的內(nèi)容hash豫缨,默認(rèn)是md5生成
hash 文件內(nèi)容的hash,默認(rèn)是md5生成
emoji 一個(gè)隨機(jī)的指代文件內(nèi)容的emoji
const path = require('path');

module.exports = {
    entry: './src/index.js',
    output: {
        filename:'bundle.js',
        path:path.resolve(__dirname, 'dist')
    },
    module:{
        rules:[{
            test:/\.(png|svg|jpg|gif)$/,
            use:[{
                loader:'file-loader',
                options:{
                    name:'img/[name][hash:8].[ext]'
                }
            }]
        }]
    }
}

.在實(shí)際工程中端朵,配置文件上百行乃是常事好芭,如何保證各個(gè)loader按照預(yù)想方式工作?

可以使用 enforce 強(qiáng)制執(zhí)行 loader 的作用順序冲呢,pre 代表在所有正常 loader 之前執(zhí)行舍败,post 是所有 loader 之后執(zhí)行。(inline 官方不推薦使用)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末敬拓,一起剝皮案震驚了整個(gè)濱河市邻薯,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌乘凸,老刑警劉巖弛说,帶你破解...
    沈念sama閱讀 212,718評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異翰意,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)信柿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門冀偶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人渔嚷,你說我怎么就攤上這事进鸠。” “怎么了形病?”我有些...
    開封第一講書人閱讀 158,207評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵客年,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我漠吻,道長(zhǎng)量瓜,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,755評(píng)論 1 284
  • 正文 為了忘掉前任途乃,我火速辦了婚禮绍傲,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己烫饼,他們只是感情好猎塞,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,862評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著杠纵,像睡著了一般荠耽。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上比藻,一...
    開封第一講書人閱讀 50,050評(píng)論 1 291
  • 那天铝量,我揣著相機(jī)與錄音,去河邊找鬼韩容。 笑死款违,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的群凶。 我是一名探鬼主播插爹,決...
    沈念sama閱讀 39,136評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼请梢!你這毒婦竟也來了赠尾?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,882評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤毅弧,失蹤者是張志新(化名)和其女友劉穎气嫁,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體够坐,經(jīng)...
    沈念sama閱讀 44,330評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡寸宵,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,651評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了元咙。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片梯影。...
    茶點(diǎn)故事閱讀 38,789評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖庶香,靈堂內(nèi)的尸體忽然破棺而出甲棍,到底是詐尸還是另有隱情,我是刑警寧澤赶掖,帶...
    沈念sama閱讀 34,477評(píng)論 4 333
  • 正文 年R本政府宣布感猛,位于F島的核電站,受9級(jí)特大地震影響奢赂,放射性物質(zhì)發(fā)生泄漏陪白。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,135評(píng)論 3 317
  • 文/蒙蒙 一膳灶、第九天 我趴在偏房一處隱蔽的房頂上張望拷泽。 院中可真熱鬧,春花似錦、人聲如沸司致。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽脂矫。三九已至枣耀,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間庭再,已是汗流浹背捞奕。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評(píng)論 1 267
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留拄轻,地道東北人颅围。 一個(gè)月前我還...
    沈念sama閱讀 46,598評(píng)論 2 362
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像恨搓,于是被迫代替她去往敵國(guó)和親院促。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,697評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容