面试题答案
一键面试路由层面优化策略
- 动态路由分段加载
- 策略:在Next.js中,对于动态路由,如
pages/post/[id].js
,可以利用动态导入(Dynamic Imports)实现分段加载。这样,只有在访问特定路由时,相关页面组件及其依赖才会被加载,而不是在应用启动时就全部加载。 - 实施示例:
// pages/post/[id].js const PostPage = dynamic(() => import('./PostPageComponent'), { ssr: false }); export default function Post() { return <PostPage />; }
- 策略:在Next.js中,对于动态路由,如
- 路由预取
- 策略:Next.js提供了
next/link
组件,它具有预取(Prefetching)功能。通过设置prefetch
属性为true
(默认值),当用户将鼠标悬停在链接上时,Next.js会在后台预取该链接对应的页面,加快页面切换速度。 - 实施示例:
import Link from 'next/link'; function MyApp() { return ( <div> <Link href="/about"> <a>About</a> </Link> </div> ); } export default MyApp;
- 策略:Next.js提供了
- 嵌套路由优化
- 策略:对于多层嵌套路由,避免过深的嵌套结构,尽量保持路由结构扁平化。同时,可以使用
next/router
的shallow
路由更新,它不会重新运行数据获取方法,适用于只更新URL参数而不改变页面数据的场景。 - 实施示例:
import { useRouter } from 'next/router'; function Page() { const router = useRouter(); const handleClick = () => { router.push({ pathname: router.pathname, query: { newParam: 'value' } }, undefined, { shallow: true }); }; return ( <div> <button onClick={handleClick}>Update URL param without re - fetching data</button> </div> ); } export default Page;
- 策略:对于多层嵌套路由,避免过深的嵌套结构,尽量保持路由结构扁平化。同时,可以使用
组件层面优化策略
- 组件懒加载
- 策略:与路由层面类似,对于大型组件,可以使用动态导入进行懒加载。这对于不常使用或占用较大资源的组件非常有效,只有在需要渲染时才加载。
- 实施示例:
const BigComponent = dynamic(() => import('./BigComponent'), { ssr: false }); function MyPage() { return ( <div> <BigComponent /> </div> ); } export default MyPage;
- Memoization
- 策略:使用
React.memo
来包裹无状态组件,它会浅比较组件的props
,如果props
没有变化,则不会重新渲染该组件,从而提高性能。对于有状态组件,可以使用useMemo
和useCallback
来缓存计算结果和函数,避免不必要的重新计算和重新创建。 - 实施示例:
const MyComponent = React.memo((props) => { return <div>{props.value}</div>; }); function ParentComponent() { const [count, setCount] = useState(0); const expensiveValue = useMemo(() => { // 复杂计算 return count * 10; }, [count]); const handleClick = useCallback(() => { setCount(count + 1); }, [count]); return ( <div> <MyComponent value={expensiveValue} /> <button onClick={handleClick}>Increment</button> </div> ); }
- 策略:使用
- Fragment和Portal
- 策略:使用Fragment(
<></>
)来避免额外的DOM节点,减少渲染开销。Portal可以将组件渲染到DOM树的其他位置,这在处理模态框等组件时很有用,因为它们不会影响父组件的布局计算。 - 实施示例:
// 使用Fragment function MyList() { return ( <ul> {[1, 2, 3].map((item) => ( <> <li>{item}</li> <li>{item * 2}</li> </> ))} </ul> ); } // 使用Portal import { createPortal } from'react'; function Modal() { return createPortal( <div className="modal"> <p>Modal content</p> </div>, document.getElementById('modal - root') ); }
- 策略:使用Fragment(
数据获取层面优化策略
- Static Site Generation (SSG)
- 策略:在构建时获取数据并生成静态HTML页面。这适用于数据不经常变化的页面,如博客文章、产品介绍等。使用
getStaticProps
函数在构建阶段获取数据,并将其传递给页面组件。 - 实施示例:
export async function getStaticProps() { const res = await fetch('https://api.example.com/data'); const data = await res.json(); return { props: { data }, revalidate: 60 * 60 * 24 // 一天后重新验证(增量静态再生) }; } function MyPage({ data }) { return ( <div> {data.map((item) => ( <div key={item.id}>{item.title}</div> ))} </div> ); } export default MyPage;
- 策略:在构建时获取数据并生成静态HTML页面。这适用于数据不经常变化的页面,如博客文章、产品介绍等。使用
- Incremental Static Regeneration
- 策略:结合SSG,通过设置
revalidate
选项,可以在页面构建后重新验证数据。这对于数据有一定更新频率但不需要实时更新的场景很有用,如新闻文章,在一定时间间隔后重新获取数据并更新静态页面。 - 实施示例:如上述
getStaticProps
示例中设置revalidate
参数。
- 策略:结合SSG,通过设置
- Server - Side Rendering (SSR)
- 策略:在每次请求时获取数据并渲染页面。这适用于数据实时性要求高的页面,如用户个人信息页面。使用
getServerSideProps
函数在服务器端获取数据并传递给页面组件。 - 实施示例:
export async function getServerSideProps(context) { const res = await fetch('https://api.example.com/user - data', { headers: { 'Cookie': context.req.headers.cookie || '' } }); const data = await res.json(); return { props: { data } }; } function MyPage({ data }) { return ( <div> {data.userName} </div> ); } export default MyPage;
- 策略:在每次请求时获取数据并渲染页面。这适用于数据实时性要求高的页面,如用户个人信息页面。使用
- Caching
- 策略:在客户端和服务器端实现缓存机制。在客户端,可以使用浏览器本地存储或IndexedDB缓存数据。在服务器端,可以使用内存缓存(如
node - cache
)或分布式缓存(如Redis)。对于重复的数据请求,先检查缓存中是否有可用数据,避免重复的API调用。 - 实施示例(客户端缓存):
const getData = async () => { const cachedData = localStorage.getItem('my - data'); if (cachedData) { return JSON.parse(cachedData); } const res = await fetch('https://api.example.com/data'); const data = await res.json(); localStorage.setItem('my - data', JSON.stringify(data)); return data; };
- 策略:在客户端和服务器端实现缓存机制。在客户端,可以使用浏览器本地存储或IndexedDB缓存数据。在服务器端,可以使用内存缓存(如