Webpack 熱加載插件的實現原理


概述

最近面試被問到了 webpack 熱加載的實現原理,所以去研究了一下,記錄下來供以后開發時參考,相信對其它人也有用。

熱加載原理

這一部分我沒有去看源碼,只是看了別人的分析理清了一下思路,參考資料:

Webpack HMR 原理解析

從零實現webpack熱更新HMR

主要流程如下:

1.首先 webpack-dev-server 會建立一個服務器,並且和瀏覽器建立 websocket 通信。

2.服務器監聽文件變化,當文件變化的時候,會重新打包相應的 chunk,然后向瀏覽器發射 hash 和 ok 事件,通知瀏覽器對應的 chunkid 等信息。

3.瀏覽器監聽 hash 和 ok 事件,再接受信息之后,通過 jsonp 向服務端請求對應的熱更新代碼。

4.最后瀏覽器把 jsonp 獲得的代碼注入到 html 的 head 里面去執行,從而實現了對應的模塊替換。

vue-loader 是怎么熱更新的

vue-loader的源碼如下:

const hotReloadAPIPath = JSON.stringify(require.resolve('vue-hot-reload-api'))

const genTemplateHotReloadCode = (id, request) => {
  return `
    module.hot.accept(${request}, function () {
      api.rerender('${id}', {
        render: render,
        staticRenderFns: staticRenderFns
      })
    })
  `.trim()
}

exports.genHotReloadCode = (id, functional, templateRequest) => {
  return `
/* hot reload */
if (module.hot) {
  var api = require(${hotReloadAPIPath})
  api.install(require('vue'))
  if (api.compatible) {
    module.hot.accept()
    if (!api.isRecorded('${id}')) {
      api.createRecord('${id}', component.options)
    } else {
      api.${functional ? 'rerender' : 'reload'}('${id}', component.options)
    }
    ${templateRequest ? genTemplateHotReloadCode(id, templateRequest) : ''}
  }
}
  `.trim()
}

可以看到,它其實在編譯單文件組件的時候,會把熱加載相關的代碼注入到編譯后的代碼里面去,從而實現熱更新的。

vue-loader 熱更新的狀態怎么保留

通過vue-loader說明,我們可以看到對於狀態的保留規則:

1.當編輯一個 template 的時候,組件會重新渲染。(rerender)

2.當編輯一個 script 的時候,組件會就地銷毀並重新創建。(reload)

3.當編輯一個 style 的時候,通過 vue-style-loader 自行熱重載,並不影響狀態。

vue-loader 源碼里面的 api 是什么

里面的 api 其實是 vue-hot-reload-api,這個庫其實就控制了組件在重新渲染(rerender)和重新創建(reload)的時候做的事。

module.hot.accept

通過上面的源碼可以看到,module.hot.accept其實並沒有傳遞參數,這是什么用法呢?通過查閱webpack官方文檔,這個通常寫在對應的模塊里面,作用是標明這個模塊可以熱加載,在這個模塊改變的時候會熱加載這個模塊。

所以,vue-loader 的熱重載原理其實是:打包后的單文件組件在修改之后,會借用 devserver 的熱重載功能更新單文件組件,並且通過監聽module.hot.data的變化,使用module.hot.accept中的 api 對組件進行重新渲染或者重新創建。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM