webpack
與 grunt
、gulp
的區別grunt、gulp
是基於任務運行的工具:它們會自動執行指定的任務,就像流水線,把資源放上去而後經過不一樣插件進行加工,它們包含活躍的社區,豐富的插件,能方便的打造各類工做流。css
webpack
是基於模塊化打包的工具:webpack
把一切都當作模塊,當 webpack
處理程序時,會遞歸地構建一個依賴關係圖,其中包含應用程序須要的每一個模塊,而後將全部的模塊打包成一個或者多個 bundle
。html
所以這是兩類徹底不一樣性質的工具,而 npm script
也能夠打造任務流。前端
webpack
、rollup
、parcel
優劣webpack
適用於大型複雜的前端站點構建:webpack
有強大的 loader
和插件生態,打包後的文件實際上就是一個當即執行函數,這個當即執行函數接收一個參數(模塊對象),鍵爲各個模塊的路徑,值爲模塊內容。當即函數內部處理模塊之間的引用、執行模塊等,更適合文件依賴複雜的應用開發。vue
rollup
適用於基礎庫的打包,好比說vue
、d3
等。rollup
將各個模塊打包進一個文件中,並經過 Tree-shaking
來刪除無用的代碼,能夠最大程度上下降代碼體積,可是 rollup
沒有 webpack
那麼多的代碼分割、按需加載等功能,更加適合庫的開發。webpack
parcel
適用於簡單的實驗性項目:能夠知足低門檻的快速看到效果,可是生態差、報錯信息不夠全面都是問題,除了一些實驗性項目不建議使用。web
loader
file-loader
把文件輸出到一個文件夾中,在代碼中經過相對 URL 引用輸入的文件url_loader
和 file-loader 相似,能在文件很小的狀況下以 base64 的方式將文件內容注入到代碼中source-map-loader
加載額外的 Source Map 文件,方便斷點調試image-loader
加載並壓縮圖片文件babel-loader
將 ES6 轉換爲 ES5css-loader
加載 css,支持模塊化、壓縮、文件導入等特性style-loader
把 css 代碼注入到 JavaScript 中,經過 DOM 操做去加載 csseslint-loader
經過 ESLint 檢查 JavaScript 代碼html-minify-loader
壓縮HTMLloader
特性package.json
的 main 來將一個 npm 模塊導出爲 loader,還能夠在 module.rules
中使用 loader 字段直接引用一個模塊plugin
define-plugin
定義環境變量html-webpack-plugin
簡化 html 文件建立uglifyjs-webpack-plugin
經過 UglifyES 壓縮 ES6 代碼webpack-parallel-uglify-plugin
多核壓縮,提升壓縮速度webpack-bundle-analyzer
可視化 webpack 輸出文件的體積mini-css-extract-plugin
CSS 提取到單獨的文件中,支持按需加載clean-webpack-plugin
在每次構建前清理 /dist 文件夾loader
和 plugin
的不一樣loader 爲加載器,webpack 將一切文件視爲模塊,可是 webpack 原生只能解析 js 和 json 文件,若是想將其餘文件也打包的話,就會用到 loader,所以,loader 的做用是讓 webpack 能夠加載和解析非 JavaScript 文件。npm
plugin 爲插件。能夠擴展 webpack 的功能,讓 webpack 更靈活。在 webpack 的運行週期中會廣播出許多事件,plugin 能夠監聽這些事件,在合適的時機經過 webpack 提供的 API 改變輸出結果。json
loader 在 module.rules 中配置,即做爲模塊的解析規則存在。類型爲數組,每一項都是一個 object,裏面描述了對於什麼類型的文件是用什麼加載和使用的參數。gulp
plugin 在 plugins 中單獨配置。類型爲數組,每一項是一個 plugin 的實例,參數都是經過構造函數傳入。數組
bundle
、chunk
、module
bundle
由 webpack
打包出來的文件
chunk
代碼塊,一個 chunk
由多個模塊組合而成,用於代碼的合併和分割
module
開發中的單個模塊,webpack
中一切皆模塊,一個模塊對應一個文件
webpack
的構建流程webpack 的運行流程是一個串行的過程,從啓動到結束會一次執行如下流程:
在以上過程當中,webpack 會在特定的時間點廣播出特定的時間,插件在監聽到事件後,會執行特定的邏輯,而且插件能夠調用 webpack 提供的 API 改變 webpack 的運行結果。
loader
和 plugin
loader
把讀到的源文件內容轉義成新的文件內容,而且每一個 loader
經過鏈式操做,將源文件轉換成想要的樣子。
編寫 loader
的時候要遵循單一原則,每個 loader
只作一種轉義工做,loader
拿到的是源文件內容(source
),處理後能夠經過返回值的方式將處理後的內容輸出,也能夠調用 this.callback()
方法將內容返回給 webpack
。還能夠經過 this.async()
生成一個 callback
函數,再用這個 callback
將處理後的內容輸出出去。此外 webpack 還爲開發者準備了開發 loader
的工具函數集 —— loader-utils
plugin
監聽 webpack 運行中廣播出的事件,在合適的時機經過 webpack 提供的 API 改變輸出結果。
webpack
的熱更新是如何作到的熱更新又稱做熱替換(Hot Module Replacement),縮寫爲 HMR。這個機制能夠作到不用刷新瀏覽器而將新變動的模塊替換掉舊的模塊。
熱更新在 server
端和 client
端都作了處理
webpack
的 watch
模式下,文件系統中的某個文件發生改變,webpack
監聽到文件變化,根據配置文件對模塊從新編譯打包,並將打包後的代碼經過簡單的 JavaScript
對象保存在內存中。webpack-dev-server
和 webpack
之間的接口交互,這一步,主要是 dev-server
的中間件 webpack-dev-middleware
和 webpack
之間的交互,webpack-dev-middleware
調用 webpack
暴露的 API 對代碼變化進行監控,而且告訴 webpack
將代碼打包到內存中。webpack-dev-server
對文件變化的監控,並非監控代碼變化從新打包。當在配置文件中配置了 devServer.watchContentBase
爲 true
的時候,server
會監聽這些配置文件夾中靜態文件的變化,變化後會通知瀏覽器端對應用進行 live reload
,這裏是瀏覽器刷新。wecpack-dev-server
代碼的工做,主要經過 sockjs
(webpack-dev-server
的依賴)在瀏覽器端和服務器端創建一個 websocket
的長鏈接,將 webpack
編譯打包的各個階段的狀態信息告知瀏覽器端,同時也包括第3步中 server
監聽靜態文件變化的信息。瀏覽器端根據這些 socket
消息進行不一樣的操做,服務端傳遞的主要信息仍是新模塊的 hash
值,後面的步驟根據這一 hash
值來進行模塊熱替換。webpack-dev-server/client
端並不可以請求更新代碼,也不會執行熱更新模塊操做,這些工做依舊會交回給 webpack
,webpack/hot/dev-server
的工做是根據 webpack-dev-server/client
傳給它的信息以及 dev-server
的配置決定是刷新瀏覽器仍是進行模塊熱更新。若僅僅是刷新瀏覽器,就沒有後續的操做了。HotModuleReplacement.runtime
是客戶端 HMR
的中樞,接收上一步傳給它的新模塊的 hash
值,經過 JsonpMainTemplate.runtime
向 server
端發送 Ajax
請求,服務端返回一個 json
,該 json
包含了全部要更新的模塊的 hash
值,獲取到更新列表後,該模塊再次經過 jsonp
請求獲取到最新的模塊代碼。HotModulePlugin
會對新舊模塊進行對比,決定是否更新模塊,再決定更新模塊後,檢查模塊之間的依賴關係,更新模塊的同時更新模塊間的依賴引用。HMR
失敗後,回退到 live reload
操做,也就是進行瀏覽器刷新來獲取最新打包代碼。webpack
優化前端性能UglifyJsPlugin
和 ParallelUglifyPlugin
來壓縮 JS 文件,利用 cssnano
來壓縮 css 代碼。webpack
對於 output
參數和各個 loader
的 publicPath
參數來修改資源路徑。Tree Shaking
:將代碼中永遠不會走到的片斷刪除掉,能夠在啓動 webpack
時追加參數 --optimize-minimize
來實現。Code Splitting
:將代碼按照路由維度或者組件分塊,能夠作到按需加載,同時能夠充分利用瀏覽器緩存。SplitChunksPlugin
插件來進行公共模塊抽取,利用瀏覽器緩存能夠長期緩存這些無需頻繁變更的公共代碼。webpack
的打包速度happypack
:利用進程並行編譯 loader
,利用緩存來使得 rebuild
更快,相似的替代者:thread-loader
。webpack
打包,減小打包時間。dll
:採用 webpack
的 DllPlugin
和 DllReferencePlugin
引入 dll
,讓一些基本不會改動的代碼先打包成靜態資源,避免反覆編譯浪費時間。webpack.cache
、babel-loader.cacheDirectory
、HappyPack.cache
均可以利用緩存提升 rebuild
的時間。babel-loader
,若文件僅存在於 src
中可使用:include: path.resolve(__dirname, src)
webpack
的構建速度CommonsChunkPlugin
來提取公共代碼external
配置來提取經常使用庫DllPlugin
和 DllReferencePlugin
預編譯資源模塊,經過 DllPlugin
來對哪些引用可是絕對不會修改的 npm
包來進行預編譯,再經過 DllReferencePlugin
將預編譯的模塊加再加載進來HappyPack
實現多線程加速編譯webpack-uglify-parallel
來提高 uglifyPlugin
的壓縮速度Tree-shaking
和 Scope Hoisting
來剔除多餘代碼