在生产环境中优化性能有时可能是一项艰巨的任务。微调网站性能不容忽视,因为缺点会导致网页速度慢且用户体验不佳。这些网站往往加载缓慢,图像呈现缓慢,从长远来看,会导致网站访问者的跳出率增加,因为大多数用户不愿意等待内容弹出。
在本教程中,我们将介绍在 Next.js 应用程序中提高站点性能的不同模式。
在本文的最后,读者将清楚地了解如何在 Next.js Web 应用程序中最大限度地提高性能。我们将介绍以下内容:
什么是动态导入和代码拆分?
动态导入与静态导入有何不同?
Next.js 中动态导入的好处
在 Next.js 中实现动态导入和代码拆分
动态导入命名导出
动态导入多个组件
客户端渲染的动态导入
库的动态导入
要阅读本文,需要先了解 Next.js 框架。
动态导入,也称为代码拆分,是指将 JavaScript 代码包分成更小的块的做法,然后将它们拼凑在一起并加载到应用程序的运行时中,作为大幅提高网站性能的一种手段。
它是作为 JavaScript 中静态导入的升级而开发的,这是使用导入语法在 JavaScript 模块的顶层添加模块或组件的导入的标准方法。
虽然这是一种常用的方法,但在性能优化方面存在一些缺点,尤其是在以下情况下:
大型代码库,这会创建更大的包大小并导致加载时间更长,因为构建过程会将所有需要的文件编译到单个包中
需要某些用户操作的网页,例如单击导航菜单项以触发页面加载。此处,仅当满足导航条件时才会呈现所需页面,并且在静态导入组件时可能会触发缓慢的初始页面加载
与静态导入不同,动态导入通过应用称为代码拆分的方法来工作。代码拆分是将代码分成不同的包,这些包使用树形格式并行排列,其中模块是动态加载的——这些模块仅在需要时才导入并包含在 JavaScript 包中。代码分割得越多,包越小,页面加载速度越快。
此方法创建多个在网页运行时动态加载的捆绑包。动态导入使用编写为内联函数调用的导入语句。
让我们看一个比较。假设我们希望在我们的应用程序中导入一个导航组件;导航组件的静态和动态导入示例如下所示:
静态导入:
import Nav from './components/Nav' export default function Home() { return () }
动态导入:
import dynamic from "next/dynamic"; import { Suspense } from "react"; export default function Home() { const Navigation = dynamic(() => import("./components/Nav.js"), { suspense: true, }); return (}>Loading...
在这里,导航组件的相关部分在import()块中指定。请注意,next/dynamic不允许在参数中使用模板文字或变量import()。
此外,react/suspense有一个指定的后备元素,在导入的组件可用之前一直显示。
通过实施动态导入来优化站点性能,反过来会带来以下站点优势:
更快的页面加载:网站加载和显示内容的速度至关重要,因为您的受众希望快速完成工作并且不会停留在缓慢的网页上
动态导入也对图像加载时间产生积极影响
低跳出率:跳出率是指用户在不与网站交互的情况下退出您的网页的速率,通常表明(并且是由)缓慢的加载时间造成的。较低的跳出率通常意味着更快的网站性能
改进的站点交互时间:这涉及 TTI 或交互时间,即用户请求操作与用户获得结果之间的时间间隔。这些交互可以包括点击链接、滚动页面、在搜索字段中输入输入、将商品添加到购物车等。
更好的网站转化率:随着越来越多的用户从使用经过优化的网站中获得满足感,他们将更有可能进行转化
有了所有这些好处,您可能正在考虑如何在您的应用程序中使用动态导入。那么,最大的问题是,我们如何在 Next.js 应用程序中实现动态导入和代码拆分?下一部分显示了有关如何实现此目的的详细步骤。
Next.js 通过该模块可以轻松地在 Next 应用程序中创建动态导入next/dynamic,如上所示。该next/dynamic模块实现了 React 组件的延迟加载导入,并基于React Lazy构建。
它还利用React Suspense 库来允许应用程序在需要时推迟加载组件,从而由于更轻的 JavaScript 构建而提高了初始加载性能。
在本文前面,我们演示了使用next/dynamic. 但我们也可以对从另一个文件导出的函数或方法进行动态导入。这证明如下:
import React from 'react' export function SayWelcome() { return (Welcome to my application) } const SayHello = () => { return (SayHello) } export default SayHello
在上面的代码中,我们有一个组件 ,SayHello和一个命名的导入,SayWelcome。我们可以只对SayWelcome方法进行动态显式导入,如下所示:
import dynamic from "next/dynamic"; import { Suspense } from "react"; export default function Home() { const SayWelcome = dynamic( () => import("./components/SayHello").then((res) => res.SayWelcome) ); return (}>Loading...
上面的代码导入SayHello组件,然后SayWelcome从响应中返回导出。
假设我们有UserDetails和UserImage组件。我们可以按如下方式导入和显示这两个组件:
import dynamic from 'next/dynamic' const details = dynamic(() => import('./components/UserDetails')) const image = dynamic(() => import('./components/UserImage')) function UserAccount() { return () } const App = () => { return ( <>Profile Page
) > } export default App
UserDetails在上面的代码中,我们为和组件添加了动态导入UserImage,然后我们将这些组件组合成一个组件,UserAccount. 最后,我们UserAccount在应用程序中返回了组件。
使用该next/dynamic模块,我们还可以禁用导入组件的服务器端渲染,并在客户端渲染这些组件。这特别适用于不需要太多用户交互或具有外部依赖关系的组件,例如 API。这可以通过在导入组件时将ssr属性设置为来完成:false
import dynamic from 'next/dynamic' const HeroItem = dynamic(() => import('../components/HeroItem'), { ssr: false, }) const App = () => { return ( <>) > }
在这里,HeroItem组件将服务器端呈现设置为false,因此它改为在客户端呈现。
除了导入本地组件,我们还可以为外部依赖添加动态导入。
例如,假设我们希望在用户请求时使用 Axiosfetch从 API 获取数据。我们可以为它定义一个动态导入Axios并实现它,如下所示:
import styles from "../styles/Home.module.css"; import { React, useState } from "react"; export default function Home() { const [search, setSearch] = useState(""); let [response, setResponse] = useState([]); const api_url = `https://api.github.com/search/users?q=${search}&per_page=5`; return (setSearch(e.target.value)} /> ); }{search} Results
{response?.data ? ( response && response?.data.items.map((item, index) => (
{item.login}
)) ) : (No Results
)}
在上面的代码中,我们有一个用于在 GitHub 上搜索用户名的输入字段。我们使用useState()Hook 来管理和更新输入字段的状态,并且我们已经将Axios依赖设置为在单击按钮时动态导入Search for GitHub users。
当响应返回时,我们通过它进行映射并显示usernames其名称与输入字段中输入的搜索查询相对应的五个用户。 下面的 GIF 演示了上面的代码块:
我们在本文中了解了动态导入/代码拆分、其优势以及如何在 Next.js 应用程序中使用它。
总体而言,如果您想缩短网站加载所需的时间,动态导入和代码拆分是必不可少的方法。如果网站有图像,或者显示的结果取决于用户交互,动态导入将显着提高网站的性能和用户体验。