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 學習筆記)