Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(service): Webpack5 兼容小程序开发者工具的 hmr 功能 #14854

Merged
merged 2 commits into from
Nov 21, 2023

Conversation

Chen-jj
Copy link
Contributor

@Chen-jj Chen-jj commented Nov 20, 2023

这个 PR 做了什么? (简要描述所做更改)

fix #13876

这个 PR 是什么类型? (至少选择一个)

  • 错误修复(Bugfix) issue: fix #
  • 新功能(Feature)
  • 代码重构(Refactor)
  • TypeScript 类型定义修改(Typings)
  • 文档修改(Docs)
  • 代码风格更新(Code style update)
  • 其他,请描述(Other, please describe):

这个 PR 涉及以下平台:

  • 所有小程序
  • 微信小程序
  • 支付宝小程序
  • 百度小程序
  • 字节跳动小程序
  • QQ 轻应用
  • 京东小程序
  • 快应用平台(QuickApp)
  • Web 平台(H5)
  • 移动端(React-Native)
  • 鸿蒙(harmony)

@Chen-jj Chen-jj changed the title feat(service): 兼容小程序开发者工具的 hmr 功能 feat(service): Webpack5 兼容小程序开发者工具的 hmr 功能 Nov 20, 2023
@Chen-jj
Copy link
Contributor Author

Chen-jj commented Nov 20, 2023

关于兼容小程序开发者工具的热重载功能

从 Webpack HMR 聊起

Webpack HMR API 使用 jsonp 加载更新后的 chunk 文件,然后使用 acceptdispose 等 API 控制热更新的具体行为。而以微信小程序为例,其开发者工具建立了内部的 hmr server,有着自己的 HMR API,因此和 Webpack HMR 是不兼容的。

微信小程序开发者工具的 HMR

在热更新时,开发者工具会在 webview 中注入一段代码。假设我们更新了一个页面的 JS 代码,开发者工具将执行以下流程:

;(function(){
    window.__global.getInstanceWindow() // 获取 webview 的 window 对象
        .then(_window => {
            const scriptEl = _window.document.createElement('script')
            scriptEl.setAttribute('charset', 'UTF-8')
            scriptEl.text = `...` // 注入代码
            _window.document.head.appendChild(scriptEl)
        })
}())
// 注入的代码
window.__global?.WAServiceGlobal?.__virtualDOM__?.updateWxAppCode?.(
    'pages/index/index.js',
    () => {
      define("pages/index/index.js", function (...) {
        // 更新后的页面文件内容
      });
      require('pages/index/index.js')
    }
)

在执行上述 require 语句时,更新后的文件内容会被运行,页面对象会被重新构建,进而完成一次热更新。

而对于使用 Webpack 打包的代码来说,更新后的文件内容是一个 chunk,执行它会运行 Webpack 相关的 chunk 加载逻辑。清除 Webpack runtime 的 chunk & module 缓存,让更新后的 chunk 能再次加载,即可兼容开发者工具的 HMR,这也是此 PR 的处理逻辑。

但这样的兼容处理仍存在问题。上述是关于页面文件热更新的例子,假设更新的是页面引用的 JS 文件,开发者工具可以分分析 requireimport 语句,使用 updateWxAppCode API 分别更新依赖及页面文件,最终完成页面的刷新。但是 Webpack 的模块引用是内部实现的,并没有 requireimport 语句,开发者工具也就不能进行上述分析处理。

假设有一种场景,页面 chunk 引用的模块被 WebpackSplitChunkPlugin 抽取到公共 chunk base.js,当该模块更新时,webpack 将更新 base.js 的代码。开发者工具虽然会使用 updateWxAppCode 注入更新后的代码,但是并不会更新页面代码,最终页面也就不会被更新。

也就是说,目前只能使用页面文件 chunk 的热更新

或许,如果有一种方法可以获取开发者工具的 window 对象,给 webview 注入自定义的 JS 内容,则可以让 Taro 控制依赖对应的页面进行热更新。欢迎讨论~

@Chen-jj Chen-jj merged commit 95f8e53 into next Nov 21, 2023
6 of 7 checks passed
@Chen-jj Chen-jj deleted the feat/mini-hmr branch November 21, 2023 06:57
@jackple
Copy link

jackple commented Dec 14, 2023

刷新了, 是不回到首页了, 但是我改了字后界面没变化啊!!!

@Ryan-CW-Code
Copy link

3.6.20新建的工程,没有添加任何功能和页面,微信小程序hmr依然无法使用。
可以给个示例工程参考参考吗?
@Chen-jj

@Typeve
Copy link

Typeve commented Dec 19, 2023

3.6.20拉取的react默认模板,使用pnom。
hrm无效

@happyeveryseconds
Copy link

热加载依旧无效

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[FR] 热重载 Hot Reload
6 participants