webpack从入门到精通(四)优化打包配置总结①
1.?HMR
HMR 即模塊熱替換(hot module replacement)的簡稱,當你對代碼進行修改并保存后,webpack 將對代碼重新打包,并將新的模塊發送到瀏覽器端,瀏覽器通過新的模塊替換老的模塊,這樣在不刷新瀏覽器的前提下就能夠對應用進行更新。
一個模塊發生變化,只會重新打包這一個模塊(而不是打包所有模塊), 極大的提升構建速度。
1)配置修改
基本代碼結構為之前博客里使用的webpack開發環境devServer。
使用webpack-dev-server,設置 hot 屬性為 true。
?devServer: {contentBase: resolve(__dirname, 'build'),compress: true,port: 3000,open: true,// // 開啟HMR功能// // 當修改了webpack配置,新配置要想生效,必須重新webpack服務hot: true}2)運行指令:npx webpack-dev-server
3)樣式文件的修改
css、less可以使用HMR功能:因為style-loader內部實現了。
我們修改我們的開發環境css代碼,可以發現頁面樣式改變了,控制臺打印如下:
4)js文件的修改
我們的js代碼如下:
index.js
// 引入 import print from './print'; import '../css/iconfont.css'; import '../css/index.less'; ? console.log('index.js文件被加載了~'); ? print(); ? function add(x, y) {return x + y; } ? console.log(add(1, 3));print.js
console.log('print.js被加載了~'); ? function print() {const content = 'hello webpack';console.log(content); } ? export default print;我們修改了print.js的代碼后,控制臺輸出如下:
可以發現,我們雖然只修改了print.js,但是index.js也同時被加載了。
js默認不能使用HMR功能 --> 需要修改js代碼,添加支持HMR功能的代碼
我們可以對js代碼進行處理:
index.js
if (module.hot) {// 一旦 module.hot 為true,說明開啟了HMR功能。 --> 讓HMR功能代碼生效module.hot.accept('./print.js', function() {// 方法會監聽 print.js 文件的變化,一旦發生變化,其他模塊不會重新打包構建。// 會執行后面的回調函數print();}); }這次修改print.js后,控制臺輸入如下:
2. source-map
我們在打包中,將開發環境中源代碼經過壓縮,去空格,babel編譯轉化,最終可以得到適用于生產環境的項目代碼,這樣處理后的項目代碼和源代碼之間差異性很大,會造成無法debug的問題。
舉例來說,如果壓縮等處理過的生產環境中的代碼出現bug,調試的時候只能定位到壓縮處理后的代碼的位置,無法定位到開發環境中的源代碼。
sourcemap就是為了解決上述代碼定位的問題,簡單理解,就是構建了處理前的代碼和處理后的代碼之間的橋梁。主要是方便開發人員的錯誤定位。這里的處理操作包括:
I)壓縮,減小體積
II)將多個文件合并成同一個文件
III)其他語言編譯成javascript,比如TypeScript和CoffeeScript等
webpack在打包中同樣支持Sourcemap,并且提供了十幾種的組合。
[inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map我們只需要在配置文件中增加配置即可:
devtool: 'eval-source-map'devtool屬性可以接受以下值:
不同的值會明顯影響到構建(build)和重新構建(rebuild)的速度。
其中一些值適用于開發環境,一些適用于生產環境。對于開發環境,通常希望更快速的source map,需要添加到bundle中以增加體積為代價;但是對于生產環境,則希望更精準的source map,需要從bundle中分離并獨立存在。
? 下面是選擇哪個值的思路:開發環境:速度快,調試更友好速度快(eval>inline>cheap>...)eval-cheap-souce-mapeval-source-map調試更友好souce-mapcheap-module-souce-mapcheap-souce-map ?--> eval-source-map / eval-cheap-module-souce-map ?生產環境:源代碼要不要隱藏? 調試要不要更友好內聯會讓代碼體積變大,所以在生產環境不用內聯nosources-source-map 全部隱藏hidden-source-map 只隱藏源代碼,會提示構建后代碼錯誤信息--> source-map / cheap-module-souce-map3. oneOf
webpack原本的loader是將每個文件都過一遍,比如有一個js文件,rules中有10個loader,第一個是處理js文件的loader,當第一個loader處理完成后webpack不會自動跳出,而是會繼續拿著這個js文件去嘗試匹配剩下的9個loader,相當于沒有break。而oneOf就相當于這個break。
用法:
rules:[oneOf:[{test:/\.css$/,use:[...common_css_loader]},{test:/\.less$/,use:[...common_css_loader,'less-loader']},{test:/\.html/,loader:'html-loader'}] ] ?4.?babel緩存
babel-loader在執行的時候,可能會產生一些運行期間重復的公共文件,造成代碼體積大而冗余,同時也會降低編譯效率。可以加上cacheDirectory參數開啟babel緩存。
? ? ? ? {test: /\.js$/,loader: 'babel-loader',options: {// 開啟babel緩存// 第二次構建時,會讀取之前的緩存cacheDirectory: true}}5. 靜態資源緩存
靜態資源緩存是前端性能優化的一個點,所以在前端開發過程中,一般會最大限度的利用緩存(這里主要是強緩存)。回到本文主題,在使用webpack構建的項目中,稍有不慎的話,即使服務器設置了緩存策略,可能構建的項目無法實現靜態資源緩存。那么webpack怎樣才能達到使用緩存的效果呢,下面就來談談這個問題。
我們都知道,webpack有各種hash值,包括每次項目構建hash,不同入口的chunkhash、文件的內容contenthash,這么多hash,它們有什么區別呢?
-
hash
hash是跟整個webpack構建項目相關的,每次項目構建hash對應的值都是不同的,即使項目文件沒有做“任何修改”。
其實是有修改的,因為每次webpack打包編譯都會注入webpack的運行時代碼,導致整個項目有變化,所以每次hash值都會變化的。由此推斷使用該方式是無法達到緩存的。
-
chunkhash
chunkhash,從字面上就能猜出它是跟webpack打包的chunk相關的。具體來說webpack是根據入口entry配置文件來分析其依賴項并由此來構建該entry的chunk,并生成對應的hash值。不同的chunk會有不同的hash值。一般在項目中把公共的依賴庫和程序入口文件隔離并進行單獨打包構建,用chunkhash來生成hash值,只要依賴公共庫不變,那么其對應的chunkhash就不會變,從而達到緩存的目的。
一般在項目中對webpack的entry使用chunkhash,具體表現在output配置項上:
moudule.exports = {entry: {app: './src/main.js',vendor: ['react', 'redux', 'react-dom', 'react-redux', 'react-router-redux']},output: {path:path.join(__dirname, '/dist/js'),filename: '[name].[chunkhash].js'}... }-
contenthash
contenthash表示由文件內容產生的hash值,內容不同產生的contenthash值也不一樣。在項目中,通常做法是把項目中css都抽離出對應的css文件來加以引用。比方在webpack配置這樣來用:
?plugins: [new MiniCssExtractPlugin({filename: 'css/built.[chunkhash:10].css'})]上面配置有一個問題,因為使用了chunkhash,它與依賴它的chunk共用chunkhash。
比方在上面app chunk例子中依賴一個index.css文件,index.css的hash是跟著app的chunkhash走的,只要app文件變更的話,那么即使index.css文件沒有變化,它的hash值也是會跟著變化的,導致緩存失效。
那么這時我們可以使用extra-text-webpack-plugin里的contenthash值,保證即使css文件所處的模塊里就算其他文件內容改變,只要css文件內容不變,它的hash值就不會變。
?plugins: [new MiniCssExtractPlugin({filename: 'css/built.[contenthash:10].css'})]?
總結
以上是生活随笔為你收集整理的webpack从入门到精通(四)优化打包配置总结①的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Promise和Async-Await的
- 下一篇: webpack从入门到精通(四)优化打包