watch
首先介紹watch選項,參考這里。可實現相關源文件改變后自動更新bundle.js文件的功能。在配置文件中添加 watch:true 或執行 webpack -w,即可開啟watch功能;
測試發現,與(一個或多個)bundle.js有關的所有js、css等模塊發生變化,就會自動執行打包,更新硬盤上的bundle.js文件。
webpack-dev-server
webpack-dev-server默認開啟以上的監視功能。但兩者監視效果存在差異:
- webpack-dev-server自帶的監視自動打包功能,新打包的文件存在於內存中,對硬盤上的bundle.js無影響。新文件的內存路徑與配置文件中的publicPath相關,如http://localhost:8080/{publicPath}/bundle.js
- 手動執行webpack -w來啟動的watch效果,會修改硬盤上的bundle.js文件
假如在配置文件中配置了publicPath(沒有配置的話默認是是 /):
output: { path: __dirname + "/dist", filename: "bundle.js", publicPath: "/p/" },
則webpack-dev-server 的監視功能只會更新內存中的文件,如 以上就是http://localhost:8080/p/bundle.js(該頁面不會自動刷新)。但這個 http://localhost:8080/webpack-dev-server/p/bundle.js 這個路徑下的文件也會更新,而且會自動刷新。
到這里可以理解為:
- 打包后文件的內存路徑 = devServer.contentBase + output.publicPath + output.filename,只能通過瀏覽器來訪問這個路由來訪問內存中的bundle
- 使用webpack打包更新的文件硬盤路徑 = output.path + output.filename
- 在路由前加上/webpack-dev-server/,只要源文件發生變化,這個地址下的頁面都會自動刷新。以上面的/webpack-dev-server/p/bundle.js為例,自動刷新后頁面的內容為/p/bundle.js。(這里實際就是后面會說到的iframe模式)
對於publicPath,有兩個用處:
- 像以上的被webpack-dev-server作為在內存中的輸出目錄。
- 被其他的loader插件所讀取,修改url地址等。
自動刷新
根據文檔的提示。自動刷新有兩種方式:
iframe模式
使用這個模式不需要任何的配置,但需要改變頁面的訪問路徑,比如要訪問根目錄下的首頁,源鏈接是 http://localhost:8080/index.html 需要換成http://localhost:8080/webpack-dev-server/index.html 。訪問這個連接時,查看頁面的dom結構,發現頁面是嵌入到一個iframe中顯示的:
修改相關聯模塊文件時,這個頁面會自動刷新。
inline模式
這個模式中有兩種使用方式,分別是node和html方式。inline模式下訪問頁面不需要像iframe模式那樣需要改變訪問的路徑,inline模式下只需要訪問源路徑即可
html方式:在需要自動刷新的頁面中添加如下腳本即可,不需要像文檔所說那樣需要添加 --inline參數 或者 配置添加 devServer: { inline: true }
<script src="http://localhost:8080/webpack-dev-server.js"></script>
理解就是當webpack-dev-server自帶的watch檢測到變化時,會通過以上的這個js來使瀏覽器自動刷新
node方式:
對於這里的理解實際就是,不直接運行webpack-dev-server指令了,而是通過node來啟動webpack-dev-server。node代碼如下:
var config = require("./webpack.config.js"); var webpack = require("webpack"); var WebpackDevServer = require("Webpack-dev-server"); config.entry.unshift("webpack-dev-server/client?http://localhost:8080/"); var compiler = webpack(config); var server = new WebpackDevServer(compiler, {}); server.listen(8080);
光光運行這段代碼是沒辦法使瀏覽器自動刷新的,因為這效果僅僅是運行了webpack-dev-server而已,還需要配合以上說的html方式來使瀏覽器自動刷新。
總結inline模式
就是直接或通過node來間接啟動webpack-dev-server來檢測文件變化,自動打包,然后再html中添加一個額外js來使瀏覽器自動刷新。以上代碼中允許webpack的動態配置,即在js中配置運行,而不需要去修改配置文件。
回顧一個重點
webpack-dev-server檢測到變化自動打包后,新打包后的文件實際上存在於內存中,而硬盤上的bundle.js依然是舊的。所以就算瀏覽器自動刷新了,讀取的是硬盤上的文件,頁面刷新后,還是和刷新前的頁面一樣。
解決辦法有兩個:
- 使頁面讀取內存中的文件。將頁面中的bundle.js路徑修改為內存路徑(上文有提到),不推薦這種方式
- 更新硬盤上的文件。即開啟webpack-dev-server的同時,開始webpack -w。前者的作用時使瀏覽器自動刷新,后者的作用是更新硬盤上的文件。
- 【推薦】。在webpack的output配置中,使文件的輸出路徑與內存路徑一致。如:
output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist'), publicPath:"dist" }, devServer: { contentBase: "." } // 或者 output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist'), }, devServer: { contentBase: './dist', hot: true }
因為webpack-dev-server對於文件請求會優先到內存中查找,沒有的話再轉到硬盤上。所以這樣瀏覽器訪問/dist/bundle.js時,能訪問到內存中的文件,而且當沒有啟動server時,訪問的剛好就是對應文件在硬盤上的路徑。這樣一來,在開發的時候,修改和讀取的文件都是內存中的文件,能提升開發效率。