webpack热更新


首先要知道webpack-dev-server和webpack-dev-middleware这两个依赖库的主要区别。

webpack-dev-server主要负责项目的服务启动和一些前置工作(比如生成webpack编译主引擎(compile实例))。

webpack-dev-middleware主要提供的是本地文件操作方面相关的服务,比如文件的编译,输出(setFs())和监听(compile.watch();

当执行npm start的时候:

  1. webpack-dev-server就开始生成编译引擎(也就是compiler实例
  2. 生成完实例以后,紧接着启动Server服务,而且可以看到,Server.js主要使用的是express框架
         
  3. 启动了本地服务以后,又紧接着启动了websocket服务
  4. Server.js还做了一件事情,就是修改了webpack.config.js的entry配置,主要实现的步骤是:
    1. 调用了updateCompiler方法,updateCompiler中又调用了addEntries方法,addEntries方法中有 2 段很关键的代码
      1. addEntries方法执行以后,会改变entry入口的配置
      2. { entry:
            { index: 
                [
                    '../node_modules/webpack-dev-server/client/index.js',
                    '../node_modules/webpack/hot/dev-server.js',
                    './src/index.js'
            	],
            },
        }
      3. 新增websocket文件的原因,是因为上面的webpack-dev-server启动的websocket服务目前服务端(webpack项目)代码已经有了,但是浏览器的代码还没有,总不能webpack通知浏览器要更新代码了,但是浏览器怎么接收消息并触发更新事件呢?所以肯定要把这部分代码给到浏览器。而第二个文件主要是用于检查更新逻辑的
  5. Server.js调用了updateCompiler方法实现了入口文件配置的修改以后,又紧接着做了一件事,就是调用了setupHooks方法,这个方法主要是用来监听每次webpack编译完成的。
  6. 上面主要就是Server.js做的事情,下面看看文件的监听是怎么做的
    1. 文件的监听主要是在webpack-dev-middleware中做的
    2. 监听文件的变化主要是通过文件的生成时间是否有变动来实现的。
  7. 现在,文件的监听以及websocket通知已经做好了,下面看看浏览器收到通知以后具体做了哪些事情
    1. 刚才Server.js调用updateCompiler方法把websocket的客户端代码配置到了entry入口中,所以现在看看那段代码做了什么
  8. 现在,Server.js通过updateCompiler方法添加到entry中的第一个文件作用已经说清楚了,添加的第二个文件,也就是webpack/hot/dev-server的作用还没说
    1. 补充一点,check方法是是HotModuleReplacementPlugin插件搞的,把代码注入到了bundle.js中
    2. check方法的源码在webpack/lib/HotModuleReplacement.runtime.js(简称HMR runtime)中
    3. check方法中会利用 到webpack/lib/web/JsonpMainTemplate.runtime(简称Jsonp runtime)中的两个方法hotDownloadManifest和hotDownloadUpdateChunk
      1. hotDownloadManifest的主要作用是发送{hash}.hot-update.json的ajax请求,获取更新清单以及获取下次热更新的Hash 标识
      2. hotDownloadUpdateChunk主要作用是通过得到上面的更新清单去发送{hash}.hot-update.js 请求下载相应的更新块,而且是通过JSONP的方式
  9. 通过上面一系列的文件监听、socket通信、浏览器收到通信并请求到新文件这些操作以后,就看是如何进行热更新的。打开hot-update.js文件以后,会发现一个webpackHotUpdate的方法。
    1. 源码中这个方法有一个callback,会执行hotAddUpdateChunk方法,
    2. hotAddUpdateChunk接收两个参数,一个是chunkId(对应hot-update.js响应体中的webpackHotUpdate函数中的“main”),一个是moreModules(对应hot-update.js响应体中的webpackHotUpdate函数中的那个对象);拿到需要更新的模块以后,hotAddUpdateChunk会用for in的形式遍历模块对象,并且赋值给全局全量hotUpdate。然后执行hotUpdateDownloaded方法

    3. 来看下hotUpdateDownloaded做了什么事,当执行hotUpdateDownloaded的时候,也就意味着热更新的前期工作已经全部做完了(webpack监听变更文件、Browser请求变更文件、处理变更文件)。所以hotUpdateDownloaded会把runtime状态置为“ready”,然后执行hotApply准备开始应用。
  10. 上面的所有的操作全部处于准备阶段,接下的hotApply才是正式应用module到页面中
    1. hotApply主要调用了hotApplyInternal这个方法。应用新模块主要分为了三个阶段
    2. 第一阶段,找出所有过期的依赖和模块
    3. 第二阶段,删除缓存中的依赖要替换的模块,
    4. 将runtime的状态置为“apply”并将新的模块添加到modules中
  11. 到此,所有的新模块已经全部在module中了,代码下次调用__webpack_require__的时候,就是最新模块


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM