如何让 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 尝试重新渲染之前协调更新的应用程序所必需的
所以我认为您使用的热加载器在设计上会尝试渲染整个树,而不管惰性或当前状态如何,以便协调更改。
要研究的选项可能不是像您那样热重新加载整个应用程序,而是在这些组件中分别热重新加载 <MobileApp />
和 <DesktopApp />
。这样,您可以保持应用程序对捆绑拆分的惰性,这在加载时有效,但热重载会根据正在使用的捆绑而变化。
【讨论】:
考虑到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-dev-server启动后会自动退出 怎么解决