问题描述
我知道如何进行 Lazy Hydration 并且我知道如何进行代码拆分,但是如何仅在组件处于 Hydrating 状态时才进行拆分的 chunck 下载?
我的代码是这样的
import React from 'react';
import dynamic from 'next/dynamic';
import ReactLazyHydrate from 'react-lazy-hydration';
const MyComponent = dynamic(() => import('components/my-component').then((mod) => mod.MyComponent));
export const PageComponent = () => {
return (
...
<ReactLazyHydrate whenVisible>
<MyComponent/>
</ReactLazyHydrate>
...
);
};
MyComponent
呈现在折叠下方,这意味着它只有在用户滚动时才会补水。问题是 MyComponent
的 JS 块会在页面加载时立即下载。
我能够通过仅在客户端上使用动态导入来破解它,但这会使组件在水合时消失一秒钟,因为在服务器上呈现的 html 不会被 react 使用。它将重新创建 DOM 元素,并且在 JS chunck 加载之前它将是空的。 当元素消失一秒钟时,它会增加页面 CLS,这就是我不能使用此 hack 的主要原因。 这是这个hack的代码
const MyComponent = typeof window === 'undefined'
? require('components/my-component').MyComponent
: dynamic(() => import('components/my-component').then((mod) => mod.MyComponent));
请注意,我想在服务器渲染上渲染组件的 HTML。这不是我不想延迟加载它的原因。我想要 Lazy Hydrate,这样我就可以在服务器上呈现组件的 HTML,但只能下载 并在可见时执行它的JS。
解决方法
import { useState } from "react";
import dynamic from "next/dynamic";
const MyComponent = dynamic(() => import("components/my-component"));
export const PageComponent = () => {
const [downloadComp,setDownloadComp] = useState(false);
return (
<>
<div className="some-class-name">
<button onClick={() => setDownloadComp(true)}>
Download the component
</button>
{downloadComp && <MyComponent />}
</div>
</>
);
};
一旦你点击按钮,上面的代码就会下载。如果您希望在滚动到位置时下载它,您可以使用类似 react-intersection-observer
的内容来设置 setDownloadComp
。我没有使用 react-lazy-hydration
的经验,但我一直在使用 react-intersection-observer
和 nextjs 动态导入来延迟加载依赖于用户滚动的组件。