diff --git a/docs/docs/docs/api/api.en-US.md b/docs/docs/docs/api/api.en-US.md
index 5c7432892927..b3b99b46e91b 100644
--- a/docs/docs/docs/api/api.en-US.md
+++ b/docs/docs/docs/api/api.en-US.md
@@ -207,7 +207,7 @@ function IndexPage({ user }) {
`` supports relative path navigation; `` does not do routing navigation and is equivalent to the jump behavior of ``.
-If `prefetch` is enabled, then when the user hovers over the component, Umi will automatically start preloading the component js files and data for the routing jump.
+If `prefetch` is enabled, then when the user hovers over the component, Umi will automatically start preloading the component js files and data for the routing jump. (Note: Use this feature when `routePrefetch` and `manifest` are enabled)
### matchPath
diff --git a/docs/docs/docs/api/api.md b/docs/docs/docs/api/api.md
index a43c0c3f9548..4139c76bbb32 100644
--- a/docs/docs/docs/api/api.md
+++ b/docs/docs/docs/api/api.md
@@ -206,7 +206,7 @@ function IndexPage({ user }) {
`` 支持相对路径跳转;`` 不做路由跳转,等同于 `` 的跳转行为。
-若开启了 `prefetch` 则当用户将鼠标放到该组件上方时,Umi 就会自动开始进行跳转路由的组件 js 文件和数据预加载。
+若开启了 `prefetch` 则当用户将鼠标放到该组件上方时,Umi 就会自动开始进行跳转路由的组件 js 文件和数据预加载。(注:使用此功能请同时开启 `routePrefetch` 和 `manifest` 配置)
### matchPath
diff --git a/packages/renderer-react/src/browser.tsx b/packages/renderer-react/src/browser.tsx
index 116d60d1b2be..ca8c7d0f7347 100644
--- a/packages/renderer-react/src/browser.tsx
+++ b/packages/renderer-react/src/browser.tsx
@@ -249,42 +249,17 @@ const getBrowser = (
) || []
).filter(Boolean);
matchedRouteIds.forEach((id) => {
- // preload
- // @ts-ignore
- const manifest = window.__umi_manifest__;
- if (manifest) {
- const routeIdReplaced = id.replace(/[\/\-]/g, '_');
- const preloadId = `preload-${routeIdReplaced}.js`;
- if (!document.getElementById(preloadId)) {
- const keys = Object.keys(manifest).filter((k) =>
- k.startsWith(routeIdReplaced + '.'),
- );
- keys.forEach((key) => {
- if (!/\.(js|css)$/.test(key)) {
- throw Error(`preload not support ${key} file`);
- }
- let file = manifest[key];
- const link = document.createElement('link');
- link.rel = 'preload';
- link.as = 'style';
- if (key.endsWith('.js')) {
- link.as = 'script';
- link.id = preloadId;
- }
- // publicPath already in the manifest,
- // but if runtimePublicPath is true, we need to replace it
- if (opts.runtimePublicPath) {
- file = file.replace(
- new RegExp(`^${opts.publicPath}`),
- // @ts-ignore
- window.publicPath,
- );
- }
- link.href = file;
- document.head.appendChild(link);
- });
+ // preload lazy component
+ // window.__umi_manifest__ is available when routePrefetch and manifest config is enabled
+ // __umi_manifest__ is not needed for preload, keep this is for compatibility and minimal change
+ if ((window as any).__umi_manifest__) {
+ // ref: https://github.com/facebook/react/blob/0940414/packages/react/src/ReactLazy.js#L135
+ const lazyCtor = opts.routeComponents[id]?._payload?._result;
+ if (typeof lazyCtor == 'function') {
+ lazyCtor();
}
}
+
const clientLoader = opts.routes[id]?.clientLoader;
const hasClientLoader = !!clientLoader;
const hasServerLoader = opts.routes[id]?.hasServerLoader;