Webpack+React:主Chunk加载后预加载指定Chunk且不渲染组件
解决方案:预加载Chunk但延迟组件渲染
根据你的需求,我们可以通过拆分chunk加载逻辑和组件渲染逻辑来实现,下面提供几种适配你当前技术栈(Webpack 4.44.2 + React 17.0.1)的可行方案:
方案一:手动触发预加载,按需渲染组件
这个方案最灵活,完全分离预加载和渲染的时机:
- 在主组件中预加载chunk
在主chunk加载完成后(比如主组件的componentDidMount钩子),手动调用import()加载目标chunk,但不处理返回结果——Webpack会自动缓存已加载的chunk,后续再导入时会直接取缓存:
// 主组件 class App extends Component { componentDidMount() { // 预加载mychunk,但不渲染组件 import(/* webpackChunkName: "mychunk" */ "../../../components/Mymodule"); } render() { // 主组件内容 return <div>...</div>; } }
- 需要渲染时再使用你的asyncComponent
当你需要渲染Mymodule组件时,正常使用你现有的asyncComponent即可,此时chunk已经在缓存中,会立即渲染:
const Mymodule = asyncComponent(() => import(/* webpackChunkName: "mychunk" */ "../../../components/Mymodule")); // 在需要的地方渲染 <Mymodule />
方案二:修改现有asyncComponent,添加渲染控制开关
如果你想复用现有的asyncComponent逻辑,可以给它加一个开关,让它只加载chunk但不立即渲染:
import React, { Component } from "react"; const asyncComponent = (importComponent) => { return class extends Component { state = { component: null }; componentDidMount() { // 组件挂载时立即加载chunk(不管是否渲染) importComponent().then((cpm) => { this.setState({ component: cpm.default }); }); } render() { // 从props中接收渲染开关,只有开关为true且组件已加载时才渲染 const { shouldRender, ...restProps } = this.props; const C = this.state.component; return shouldRender && C ? <C {...restProps} /> : null; } }; }; export default asyncComponent;
使用时,先传入shouldRender={false}触发chunk加载但不渲染:
const Mymodule = asyncComponent(() => import(/* webpackChunkName: "mychunk" */ "../../../components/Mymodule")); // 主组件中挂载,此时会加载chunk但不显示 <Mymodule shouldRender={false} /> // 当需要渲染时,把shouldRender改为true <Mymodule shouldRender={true} />
方案三:利用Webpack预加载指令(webpackPreload)
Webpack提供了webpackPreload注释指令,可以让浏览器在主chunk加载完成后,并行预加载指定的chunk,适合需要自动预加载的场景:
- 触发预加载
在主组件的componentDidMount中导入chunk并添加webpackPreload指令:
componentDidMount() { // 告诉Webpack预加载mychunk import(/* webpackChunkName: "mychunk", webpackPreload: true */ "../../../components/Mymodule"); }
- 渲染时使用React.lazy(可选)
如果你愿意切换到React官方的动态导入方案,可以用React.lazy和Suspense来渲染组件(chunk已预加载,渲染会无延迟):
import React, { Suspense } from "react"; const Mymodule = React.lazy(() => import(/* webpackChunkName: "mychunk" */ "../../../components/Mymodule")); // 需要渲染时包裹在Suspense中 <Suspense fallback={null}> <Mymodule /> </Suspense>
注意事项
- Webpack会自动缓存已加载的chunk,所有方案都不会重复请求资源;
- 如果你使用函数组件,只需把
componentDidMount替换为useEffect(() => {}, [])即可; webpackPreloadvswebpackPrefetch:前者优先级更高,用于当前页面需要的资源;后者优先级低,用于未来页面可能用到的资源,根据你的场景选择即可。
内容的提问来源于stack exchange,提问作者Sikarwar
相关产品推荐
相关产品推荐

