React Native 快速刷新是否支持 module.hot.dispose 数据参数?

Does react native fast refresh support module.hot.dispose data argument?

我正在研究 react-native 故事书项目,我正在尝试重新使用一些用于将文件(故事)加载到应用程序中的代码。在网络版应用程序中,此代码用于跟踪之前的故事文件列表 (previousexports),以便在您重新加载时不会重复故事。

if (m && m.hot && m.hot.dispose) {
  ({ previousExports = new Map() } = m.hot.data || {});
  m.hot.dispose((data) => {
    loaded = false;
    // eslint-disable-next-line no-param-reassign
    data.previousExports = previousExports;
  });
  m.hot.accept();
}

Link 到此代码:https://github.com/storybookjs/storybook/blob/f2cc478dcf1e249c29a1014f7d53d71931f824f8/lib/core-client/src/preview/loadCsf.ts#L237

然而,当我 运行 这段代码在 React Native 上时,数据字段是未定义的。在热模块重新加载的 webpack 实现中,dispose 函数具有此签名。

__WebpackModuleApi.Hot.dispose(callback: (data: any) => void): void

有了这个描述

Add a one time handler, which is executed when the current module code is replaced. Here you should destroy/remove any persistent resource you have claimed/created. If you want to transfer state to the new module, add it to data object. The data will be available at module.hot.data on the new module.

我正在努力寻找用于热模块替换的 React Native api。据我所知,快速刷新实现仍然使用类似的 api 并且这些 m.hot 调用是在快速刷新调用时触发的。

React Native 是否只是不支持此数据参数?我在哪里可以找到有关 react-native/metro 的 module.hot api 的信息?

到目前为止我发现的是:

https://github.com/facebook/react/issues/16604#issuecomment-528663101

https://reactnative.dev/blog/2019/09/18/version-0.61#fast-refresh

https://reactnative.dev/blog/2016/03/24/introducing-hot-reloading

值得注意的信息是

Fast Refresh relies on several pieces working together:

  • "Hot module replacement" mechanism in the module system.
    • That is usually also provided by the bundler.
    • E.g. in webpack, module.hot API lets you do this.

HMR in React Native extends the module system by introducing the hot object. This API is based on Webpack's one. The hot object exposes a function called accept which allows you to define a callback that will be executed when the module needs to be hot swapped.

自从在这里问这个问题后,我与一位同事进行了讨论,这让我相信数据参数不受支持。

同时查看 metro 代码(react native 的 metro bundler)似乎证实了这一点。

如果您查看 Metro 存储库中的 require polyfill,您可以看到以下类型定义。

type HotModuleReloadingCallback = () => void;
type HotModuleReloadingData = {|
  _acceptCallback: ?HotModuleReloadingCallback,
  _disposeCallback: ?HotModuleReloadingCallback,
  _didAccept: boolean,
  accept: (callback?: HotModuleReloadingCallback) => void,
  dispose: (callback?: HotModuleReloadingCallback) => void,
|};

如您所见,dispose 函数共享相同的回调签名 ()=>void

你可以找到上面代码的来源here

我最终采用了另一种解决方案,将导出存储在全局变量中。这并不理想,但它正在工作。该全局变量看起来有点像这样 global.previousExports = new Map<any, string>(); 我扩展了节点全局类型以避免类型错误。