延迟加载
next.js 允许你延迟加载客户端组件和导入的库,仅在需要时才会加载它们。
dynamic()
'use client'
import { useState } from 'react'
import dynamic from 'next/dynamic'
const ComponentA = dynamic(() => import('../components/A'))
const ComponentB = dynamic(() => import('../components/B'))
const ComponentC = dynamic(() => import('../components/C'), { ssr: false })
export default function ClientComponentExample() {
const [showMore, setShowMore] = useState(false)
return (
<div>
<ComponentA />
{showMore && <ComponentB />}
<button onClick={() => setShowMore(!showMore)}>Toggle</button>
<ComponentC />
</div>
)
}
上述代码动态加载了三个组件,ComponentA、ComponentB 和 ComponentC。
其中 ComponentA 和 ComponentB 是在 SSR 阶段进行的渲染,ComponentC 则是在客户端运行时进行的渲染。
ssr 阶段延迟加载的意义
默认情况下,dynamic 的组件是在 SSR 阶段进行渲染,可能有的小伙伴会问,这样做的意义是什么呢?
- 流式加载,首先,ssr延迟加载,可以避免因为某个组件加载时间过长,而导致整个页面加载时间过长。
- 代码分割,其次,可以将客户端组件的 bundle 进行更细粒度的拆分,避免单个 bundle 过大,进而影响页面的加载速度。
跳过 ssr
其实某些情况下,我们并不希望组件在 SSR 阶段进行渲染,而是期望在客户端运行时进行渲染,进而减少 SSR 阶段的渲染时间,提高页面的加载速度,我们可以使用 ssr 参数来进行控制。
const ComponentC = dynamic(() => import('../components/C'), { ssr: false })
自定义加载动画
我们也可以自定义加载动画,通过 dynamic 的 loading 参数来进行设置。
import dynamic from 'next/dynamic'
const WithCustomLoading = dynamic(
() => import('../components/WithCustomLoading'),
{
loading: () => <p>Loading...</p>,
}
)
export default function Page() {
return (
<div>
<WithCustomLoading />
</div>
)
}
加载第三方库
上边我们介绍了如何延迟加载客户端组件,那么如何延迟加载第三方库呢?
很简单,通过 import()
函数就能实现第三方库的延迟加载,进而避免在 SSR 阶段加载不必要的第三方库。
'use client'
import { useState } from 'react'
const names = ['Tim', 'Joe', 'Bel', 'Lee']
export default function Page() {
const [results, setResults] = useState()
return (
<div>
<input
type="text"
placeholder="Search"
onChange={async e => {
const { value } = e.currentTarget
const Fuse = (await import('fuse.js')).default
const fuse = new Fuse(names)
setResults(fuse.search(value))
}}
/>
<pre>Results: {JSON.stringify(results, null, 2)}</pre>
</div>
)
}