2023前端面試系列-- webpack & Git篇

語言: CN / TW / HK

theme: cyanosis

前言

本文是我的前端面試系列的工具篇,彙總整理了webpackGit的常見面試題,後續的複習過程中隨時會對本文查漏補缺。如有不當之處,歡迎指正,感謝。

其他章節內容可點選連結檢視: - 2023前端面試系列--HTML & CSS 篇 - 2023前端面試系列-- JS 篇 - 2023前端面試系列-- Vue 篇 - 2023前端面試系列--網路篇

webpack

對webpack的理解?

webpack 是一個用於現代 JavaScript 應用程式的靜態模組打包工具。我們可以使用webpack管理模組。因為在webpack看來,專案中的所有資源皆為模組,通過分析模組間的依賴關係,在其內部構建出一個依賴圖,最終編繹輸出模組為 HTML、JavaScript、CSS 以及各種靜態檔案(圖片、字型等),讓我們的開發過程更加高效。

image.png webpack的主要作用如下: - 模組打包。可以將不同模組的檔案打包整合在一起,並且保證它們之間的引用正確,執行有序。利用打包我們就可以在開發的時候根據我們自己的業務自由劃分檔案模組,保證專案結構的清晰和可讀性。 - 編譯相容。在前端的“上古時期”,手寫一堆瀏覽器相容程式碼一直是令前端工程師頭皮發麻的事情,而在今天這個問題被大大的弱化了,通過webpackLoader機制,不僅僅可以幫助我們對程式碼做polyfill,還可以編譯轉換諸如.less.vue.jsx這類在瀏覽器無法識別的格式檔案,讓我們在開發的時候可以使用新特性和新語法做開發,提高開發效率。 - 能力擴充套件。通過webpackPlugin機制,我們在實現模組化打包編譯相容的基礎上,可以進一步實現諸如按需載入,程式碼壓縮等一系列功能,幫助我們進一步提高自動化程度,工程效率以及打包輸出的質量。

webpack的構建流程?

webpack的執行流程是一個序列的過程,從啟動到結束會依次執行以下流程: - 初始化引數:從配置檔案和 Shell 語句中讀取與合併引數,得出最終的引數 - 開始編譯:用上一步得到的引數初始化 Compiler 物件,載入所有配置的外掛,執行物件的 run 方法開始執行編譯 - 確定入口:根據配置中的 entry 找出所有的入口檔案 - 編譯模組:從入口檔案出發,呼叫所有配置的 loader 對模組進行翻譯,再找出該模組依賴的模組,再遞迴本步驟直到所有入口依賴的檔案都經過了本步驟的處理 - 完成模組編譯:在經過上一步使用 loader 翻譯完所有模組後,得到了每個模組被翻譯後的最終內容以及它們之間的依賴關係 - 輸出資源:根據入口和模組之間的依賴關係,組裝成一個個包含多個模組的 Chunk,再把每個 Chunk 轉換成一個單獨的檔案加入到輸出列表,這步是可以修改輸出內容的最後機會 - 輸出完成:在確定好輸出內容後,根據配置確定輸出的路徑和檔名,把檔案內容寫入到檔案系統

在以上過程中,webpack會在特定的時間點廣播出特定的事件,外掛在監聽到感興趣的事件後會執行特定的邏輯,並且外掛可以呼叫webpack提供的 API 改變webpack的執行結果。

簡單說: - 初始化:啟動構建,讀取與合併配置引數,載入 Plugin,例項化 Compiler - 編譯:從 entry 出發,針對每個 Module 序列呼叫對應的 loader 去翻譯檔案的內容,再找到該 Module 依賴的 Module,遞迴地進行編譯處理 - 輸出:將編譯後的 Module 組合成 Chunk,將 Chunk 轉換成檔案,輸出到檔案系統中

常見的loader有哪些?

預設情況下,webpack只支援對jsjson檔案進行打包,但是像csshtmlpng等其他型別的檔案,webpack則無能為力。因此,就需要配置相應的loader進行檔案內容的解析轉換。

常用的loader如下: - image-loader:載入並且壓縮圖片檔案。 - less-loader: 載入並編譯 LESS 檔案。 - sass-loader:載入並編譯 SASS/SCSS 檔案。 - css-loader:載入 CSS,支援模組化、壓縮、檔案匯入等特性,使用css-loader必須要配合使用style-loader。 - style-loader:用於將 CSS 編譯完成的樣式,掛載到頁面的 style 標籤上。需要注意 loader 執行順序,style-loader 要放在第一位,loader 都是從後往前執行。 - babel-loader:把 ES6 轉換成 ES5 - postcss-loader:擴充套件 CSS 語法,使用下一代 CSS,可以配合 autoprefixer 外掛自動補齊 CSS3 字首。 - eslint-loader:通過 ESLint 檢查 JavaScript 程式碼。 - vue-loader:載入並編譯 Vue 元件。 - file-loader:把檔案輸出到一個資料夾中,在程式碼中通過相對 URL 去引用輸出的檔案 (處理圖片和字型) - url-loader:與 file-loader 類似,區別是使用者可以設定一個閾值,大於閾值會交給 file-loader 處理,小於閾值時返回檔案 base64 形式編碼 (處理圖片和字型)

更多loader,點選此處檢視官方文件

常見的plugin有哪些?

webpack中的plugin賦予其各種靈活的功能,例如打包優化、資源管理、環境變數注入等,它們會執行在webpack的不同階段(鉤子 / 生命週期),貫穿了webpack整個編譯週期。目的在於解決 loader 無法實現的其他事

常用的plugin如下: - HtmlWebpackPlugin:簡化 HTML 檔案建立 (依賴於 html-loader) - mini-css-extract-plugin: 分離樣式檔案,CSS 提取為獨立檔案,支援按需載入 (替代extract-text-webpack-plugin) - clean-webpack-plugin: 目錄清理

更多plugin,點選此處檢視官方文件

loader和plugin的區別?

loader是檔案載入器,能夠載入資原始檔,並對這些檔案進行一些處理,諸如編譯、壓縮等,最終一起打包到指定的檔案中;plugin賦予了webpack各種靈活的功能,例如打包優化、資源管理、環境變數注入等,目的是解決 loader無法實現的其他事。

在執行時機上,loader 執行在打包檔案之前;plugin則是在整個編譯週期都起作用。

在配置上,loadermodule.rules中配置,作為模組的解析規則,型別為陣列。每一項都是一個 Object,內部包含了 test(型別檔案)loaderoptions (引數)等屬性;pluginplugins中單獨配置,型別為陣列,每一項是一個 plugin 的例項,引數都通過建構函式傳入。

webpack的熱更新原理是?

模組熱替換(HMR - hot module replacement),又叫做熱更新,在不需要重新整理整個頁面的同時更新模組,能夠提升開發的效率和體驗。熱更新時只會區域性重新整理頁面上發生了變化的模組,同時可以保留當前頁面的狀態,比如複選框的選中狀態等。

熱更新的核心就是客戶端從服務端拉去更新後的檔案,準確的說是 chunk diff (chunk 需要更新的部分),實際上webpack-dev-server與瀏覽器之間維護了一個websocket,當本地資源發生變化時,webpack-dev-server會向瀏覽器推送更新,並帶上構建時的hash,讓客戶端與上一次資源進行對比。客戶端對比出差異後會向webpack-dev-server發起 Ajax 請求來獲取更改內容(檔案列表、hash),這樣客戶端就可以再借助這些資訊繼續向webpack-dev-server發起 jsonp 請求獲取該chunk的增量更新。

後續的部分(拿到增量更新之後如何處理?哪些狀態該保留?哪些又需要更新?)由HotModulePlugin 來完成,提供了相關 API 以供開發者針對自身場景進行處理,像react-hot-loadervue-loader都是藉助這些 API 實現熱更新。

如何提高webpack的構建速度?

  1. 程式碼壓縮
    • JS壓縮
      webpack 4.0預設在生產環境的時候是支援程式碼壓縮的,即mode=production模式下。 實際上webpack 4.0預設是使用terser-webpack-plugin這個壓縮外掛,在此之前是使用 uglifyjs-webpack-plugin,兩者的區別是後者對 ES6 的壓縮不是很好,同時我們可以開啟 parallel引數,使用多程序壓縮,加快壓縮。
    • CSS壓縮
      CSS 壓縮通常是去除無用的空格等,因為很難去修改選擇器、屬性的名稱、值等。可以使用另外一個外掛:css-minimizer-webpack-plugin
    • HTML壓縮
      使用HtmlWebpackPlugin外掛來生成 HTML 的模板時候,通過配置屬性minify進行 html 優化。 module.exports = { plugin:[ new HtmlwebpackPlugin({ minify:{ minifyCSS: false, // 是否壓縮css collapseWhitespace: false, // 是否摺疊空格 removeComments: true // 是否移除註釋 } }) ] }
  2. 圖片壓縮
    配置image-webpack-loader
  3. Tree Shaking
    Tree Shaking是一個術語,在計算機中表示消除死程式碼,依賴於ES Module的靜態語法分析(不執行任何的程式碼,可以明確知道模組的依賴關係)。 在webpack實現Tree shaking有兩種方案:
    • usedExports:通過標記某些函式是否被使用,之後通過 Terser 來進行優化的
      module.exports = { ... optimization:{ usedExports } } 使用之後,沒被用上的程式碼在webpack打包中會加入unused harmony export mul註釋,用來告知Terser在優化時,可以刪除掉這段程式碼。
    • sideEffects:跳過整個模組/檔案,直接檢視該檔案是否有副作用
      sideEffects用於告知webpack compiler哪些模組時有副作用,配置方法是在package.json中設定sideEffects屬性。如果sideEffects設定為false,就是告知webpack可以安全的刪除未用到的exports。如果有些檔案需要保留,可以設定為陣列的形式,如: "sideEffecis":[ "./src/util/format.js", "*.css" // 所有的css檔案 ]
  4. 縮小打包域
    排除webpack不需要解析的模組,即在使用loader的時候,在儘量少的模組中去使用。可以藉助 includeexclude這兩個引數,規定loader只在那些模組應用和在哪些模組不應用。

更多優化構建速度方式,推薦閱讀:淺談 webpack 效能優化(內附 webpack 學習筆記)

Git

常用命令

  • 初始化一個倉庫:git init
  • 檢視分支:git branch
  • 將已修改或未跟蹤的檔案新增到暫存區:git add [file] 或 git add .
  • 提交至本地倉庫:git commit -m "提及記錄xxxx"
  • 本地分支推送至遠端分支:git push
  • 檢視當前工作目錄和暫存區的狀態: git status
  • 檢視提交的日誌記錄: git log
  • 從遠端分支拉取程式碼:git pull
  • 合併某分支(xxx)到當前分支: git merge xxx
  • 切換到分支xxx:git checkout xxx
  • 建立分支xxx並切換到該分支:git checkout -b xxx
  • 刪除分支xxx:git branch -d xxx
  • 將當前分支到改動儲存到堆疊中:git stash
  • 恢復堆疊中快取的改動內容:git stash pop

git merge 和git rebase的區別?

相同點:

git mergegit rebase兩個命令都⽤於從⼀個分⽀獲取內容併合併到當前分⽀。

不同點:
1. git merge會⾃動建立⼀個新的commit,如果合併時遇到衝突的話,只需要修改後重新commit
- 優點:能記錄真實的commit情況,包括每個分⽀的詳情
- 缺點:由於每次merge會⾃動產⽣⼀個commit,因此在使用⼀些視覺化的git工具時會看到這些自動產生的commit,這些commit對於程式設計師來說沒有什麼特別的意義,多了反而會影響閱讀。 2. git rebase會合並之前的commit歷史。
- 優點:可以得到更簡潔的提交歷史,去掉了merge 產生的commit
- 缺點:因為合併而產生的程式碼問題,就不容易定位,因為會重寫提交歷史資訊

場景:
- 當需要保留詳細的合併資訊,建議使⽤git merge, 尤其是要合併到master上 - 當發現⾃⼰修改某個功能時提交比較頻繁,並覺得過多的合併記錄資訊對自己來說沒有必要,那麼可嘗試使用git rebase

對GitFlow的理解?

GitFlow重點解決的是由於原始碼在開發過程中的各種衝突導致開發活動混亂的問題。重點是對各個分支的理解。 - master:主分支。 - develop:主開發分支,平行於master分支。 - feature:功能分支,必須從develop分支建立,開發完成後合併到develop分支。 - release:釋出分支,釋出的時候用,一般測試時候發現的 bug 在該分支進行修復。從develop分支建立,完成後合併回developmaster分支。 - hotfix:緊急修復線上bug使用,必須從master分支建立,完成後合併回developmaster分支。

如果有合作開發經驗,且開發過程規範的話,這部分問題不大,描述一下日常的開發流程即可。不瞭解的話,推薦閱讀:從零開始,學會Git和Gitflow工作流

後記

webpack 基礎內容推薦閱讀:帶你深度解鎖Webpack系列(基礎篇)

參考連結: - 「吐血整理」再來一打Webpack面試題 - 淺談 webpack 效能優化(內附 webpack 學習筆記)