webpack HRM

webpack的HMR

Hot Module Replacement(如下簡稱 HMR)是 webpack 發展至今引入的最使人興奮的特性之一 ,當你對代碼進行修改並保存後,webpack 將對代碼從新打包,並將新的模塊發送到瀏覽器端,瀏覽器經過新的模塊替換老的模塊,這樣在不刷新瀏覽器的前提下就可以對應用進行更新。(注意不是瀏覽器刷新)。node

webpack-dev-server實現自動刷新

咱們只須要在webpack.config.js裏配置好devServe便可實現自動刷新,但並非HMR,以下:react

devServer: {
    // 服務器根目錄
    contentBase: path.join(__dirname, "./src"),
    port: 3000,
    //會把打包後的資源輸入到服務器根目錄 + publicPath
    publicPath: "/",
  },
複製代碼

webpack-dev-server實現熱更新原理(HMR)

下面咱們以 react 爲例子,大概講述一下如何實現HMR, 首先咱們理解一下他實現的原理,如圖:webpack

1.webpack監聽到文件的變化,進行新的編譯和打包,而且以簡單的js對象保存在內存中。web

2.webpack與devServer進行交互,告訴webpack要保存代碼到內存中。json

3.devServer對文件的監控,而且經過配置來告訴devServer是刷新仍是進行熱更新。瀏覽器

4.devServer經過sock.js和瀏覽器創建websock長連接,把webpack編譯代碼各階段信息告訴瀏覽器(包括更新模塊的hash),就是經過這一個hash來進行更新的。服務器

5.webpack經過devServer的配置和傳遞給他的信息(也就是第二部監聽的信息)來決定是否進行瀏覽器刷新或者熱更新。babel

6.webpack的HotModuleReplacement經過JsonpMainTemplate.runtime 向 server 端發送 Ajax 請求,服務端返回一個 json,該 json 包含了全部要更新的模塊的hash值,獲取到更新列表後,該模塊再次經過jsonp請求,獲取到最新的模塊代碼。這就是上圖中 七、八、9 步驟。webpack-dev-server

10.HotModulePlugin將會對新舊模塊進行對比,決定是否更新模塊,在決定更新模塊後,檢查模塊之間的依賴關係,更新模塊的同時更新模塊間的依賴引用。jsonp

11.當 HMR 失敗後,回退到 live reload 操做,刷新瀏覽器。

實現熱更新具體配置(HMR)

webpack.config.js配置以下:

devServer: {
    // 服務器根目錄
    contentBase: path.join(__dirname, "./src"),
    port: 3000,
    //會把打包後的資源輸入到服務器根目錄 + publicPath
    publicPath: "/",
    inline: true,
    hot: true,
  },
  plugins: [
    ...
    new webpack.HotModuleReplacementPlugin(),
  ]
複製代碼

入口文件配置

若是已經經過 HotModuleReplacementPlugin 啓用了模塊熱替換(Hot Module Replacement),則它的接口將被暴露在module.hot屬性下面。一般,用戶先要檢查這個接口是否可訪問,而後再開始使用它。 ——引自webpack官網

if (module.hot) {
  module.hot.accept(() => {
    ReactDom.render(
        <App />, document.getElementById('root') ) }) } ReactDOM.render(<App />, document.getElementById("root")); 複製代碼

因爲熱更新並不會保存react的state狀態,因此咱們必須引用一個loader,react-hot-loader。

webpack.config.js配置

rules: [
    ...
    {
        test: /\.(js|jsx)$/,
        exclude: /(node_modules|bower_components)/,
        loader: "babel-loader",
        options: {
          presets: ["@babel/env"],
          plugins: ["react-hot-loader/babel"] //增長
        }
    },
]
複製代碼
entry: [
    'react-hot-loader/patch', //添加
    "./src/index.js",
  ],
複製代碼

入口文件

if (module.hot) {
  module.hot.accept(() => {
    ReactDom.render(
      <AppContainer> <App /> </AppContainer>,
        document.getElementById('root')
    )
  })
}
ReactDOM.render(<App />, document.getElementById("root")); 複製代碼

##小結 webpack的HMR就到此爲止啦,參考文章: zhuanlan.zhihu.com/p/30669007

相關文章
相關標籤/搜索