如何让 webpack-dev-server 停止使用 React 延迟/Suspense 代码拆分在内容更改时下载不正确的块?

Posted

技术标签:

【中文标题】如何让 webpack-dev-server 停止使用 React 延迟/Suspense 代码拆分在内容更改时下载不正确的块?【英文标题】:How can I get webpack-dev-server to stop downloading incorrect chunks on content change with React lazy/Suspense code splitting? 【发布时间】:2020-03-02 11:30:38 【问题描述】:

这是我的设置:

const DesktopApp = lazy(() => import(/* webpackChunkName: "DesktopApp" */'./DesktopApp'));
const MobileApp = lazy(() => import(/* webpackChunkName: "MobileApp" */'./MobileApp'));

type Props =  shouldServeMobile: boolean ;

export const App = ( shouldServeMobile : Props): JSX.Element => (
  shouldServeMobile
    ? (
      <Suspense fallback=<AppLoading />>
        <MobileApp />
      </Suspense>
    ) : (
      <Suspense fallback=<AppLoading />>
        /* GlobalDesktopStyle is injected in multiple places due to a bug where the
          theme gets reset when lazy loading via React.Lazy + webpack */
        <GlobalDesktopStyle />
        <DesktopApp />
      </Suspense>
    )
);

这是由具有以下配置的webpack-dev-server 加载的:

  devServer: 
    contentBase: paths.output.path,
    // this host value allows devices on a LAN to connect to the dev server
    host: '0.0.0.0',
    https: true,
    port: 9001,
    hotOnly: true,
    // lets any URL work
    historyApiFallback: true,
  ,
  plugins: [
    new webpack.HotModuleReplacementPlugin()
  ]

现在,假设我们正在渲染

import  hot  from 'react-hot-loader/root';
// some imports omitted

const HotApp = hot(App);

ReactDOM.render(
  <HotApp shouldServeMobile=true />,
  document.getElementById('root')
);

在初始加载时,这可以正常工作。 MobileApp 块下载,DesktopApp 不下载。但是,只要我更改了组件中的任何数据并且HMR 启动 - 重新加载就会下载DesktopApp 块。

这显然违背了代码拆分的目的。有谁知道如何阻止这种情况发生?

要明确:我输出了console.log(shouldServeMobile),它始终是true。另外,我在这里尝试了这个建议:Webpack-dev-server emits all chunks after every change,但它根本没有帮助。

【问题讨论】:

为什么你需要react-hot-loader/root 而只是使用webpack hot reloader。 ? @SakhiMansoor 我很确定这样反应钩子也可以热重载。设置好久了,可能记错了。代码分割是新的 - 使用这种热重载设置不是。但是是的 - 如果内存服务正确,没有它你就不能热重载钩子。 【参考方案1】:

我认为这与react-hot-loader有关

每https://github.com/gaearon/react-hot-loader

我们重新渲染 React 树的内部流程,这是在 React 尝试重新渲染之前协调更新的应用程序所必需的

所以我认为您使用的热加载器在设计上会尝试渲染整个树,而不管惰性或当前状态如何,以便协调更改。

要研究的选项可能不是像您那样热重新加载整个应用程序,而是在这些组件中分别热重新加载 &lt;MobileApp /&gt;&lt;DesktopApp /&gt;。这样,您可以保持应用程序对捆绑拆分的惰性,这在加载时有效,但热重载会根据正在使用的捆绑而变化。

【讨论】:

考虑到react-hot-loader 是由Suspense/lazy 背后的主要人物之一制作的,并且考虑到react-hot-loader github README 有一个专门用于code splitting 的部分,它明确表示它支持@ 987654329@ - 我怀疑这就是问题所在。 (虽然它可能是)关于热重新加载单独组件的建议是一个很好的建议 - 但我已经共享了在该开关之上运行的逻辑,然后将不再在热重新加载中捕获。 该仓库中有一些人在代码拆分方面存在问题。有些人根本无法让它工作,怀疑如果热重载通常工作,他们是否过于关心捆绑。如果你使用钩子,它看起来就像是一个废话。希望你能把它确定下来,对不起,不能提供更多帮助。 这个答案不符合我的需求,但它可能在正确的轨道上并且信息丰富(并且不像另一个那样显然完全不知情和不正确)。我宁愿有人得到赏金也不愿让它过期,所以我把它给了你。虽然你给我的只是猜想,但不会将其作为正确答案来检查。【参考方案2】:

应该有效:

    const DesktopApp = lazy(() => import(/* webpackChunkName: "DesktopApp" */'./DesktopApp'));
    const MobileApp = lazy(() => import(/* webpackChunkName: "MobileApp" */'./MobileApp'));

    type Props =  shouldServeMobile: boolean ;

    export const App = ( shouldServeMobile : Props): JSX.Element => (
        <Suspense fallback=<AppLoading />>
            shouldServeMobile
            ?
              <MobileApp />
            : <GlobalDesktopStyle />
              <DesktopApp />
         </Suspense>

    );

【讨论】:

以上是关于如何让 webpack-dev-server 停止使用 React 延迟/Suspense 代码拆分在内容更改时下载不正确的块?的主要内容,如果未能解决你的问题,请参考以下文章

如何让 webpack 不那么冗长?

webpack-dev-server启动后会自动退出 怎么解决

3.2.1 webpack-dev-server的使用

如何同时观看运行 Jest 测试的 webpack-dev-server?

如何检测webpack-dev-server是否正在运行?

Webpack-dev-server 如何删除 React 应用程序的默认路由?