如何在 Next.js 中创建预加载器
由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!
在您阅读本文之前,我想让您知道这篇文章存在一些缺陷,对于我之前在撰写本文时所犯的错误,我深表歉意。
我非常感谢各位在评论区分享的意见,我从中受益匪浅!你可以在这里找到一篇新文章,它详细介绍了如何正确地向 Next.js 网站添加预加载器。
在将网页内容显示给访问您的 Web 应用程序/网站的用户之前,始终需要准备好网页的所有内容。
如果网页内容尚未准备就绪,人们就必须等待网页显示,这会导致网站访问量大幅下降。
在本文中,我们将探讨如何构建一个加载屏幕组件,该组件会在页面内容即将挂载到 DOM 时显示。
在继续阅读本文之前,您应该熟悉以下内容:
入门
在本文中,我们将使用 NextJS 来设置我们的应用程序,如果您不熟悉 NextJS,可以使用create-react-app 。
首先,我们需要安装本项目所需的依赖项。首先,我们需要创建一个 Next.js 应用。以下命令会获取 Next.js 应用所需的依赖项。
npx create-next-app [name-of-your-app]
我们将使用该"styled-component"库来设置加载屏幕组件的样式。让我们通过在终端中输入以下命令来获取上述依赖项。
npm install --save styled-components
我们 Nextjs 应用中的组件
在本节中,我们将看到构成此项目架构的不同文件及其各自的功能。
该pages目录是应用程序所有路由操作的场所。这是 Next.js 的一个开箱即用功能。它省去了您编写独立路由的麻烦。
-
pages/apiapi 目录使您能够在同一个代码库中为您的 Next.js 应用程序拥有后端,而不是像通常那样为您的 REST 或 GraphQL API 创建单独的存储库,并将它们部署到 Heroku 等后端托管平台上。 -
pages/_app.js:是所有组件连接到 DOM 的地方。如果你查看组件结构,你会发现所有组件也都作为 props 传递pageProps进去Component。
function MyApp({ Component, pageProps }) {
return (
<React.Fragment>
<Component {...pageProps} />
</React.Fragment>
);
}
export default MyApp;
它类似于index.jsCreate-React-App 中的文件。唯一的区别在于,你不需要将你的应用程序连接到名为“root”的 DOM 节点。
React.render(document.getElementById("root"), <App />)
index.js这是 pages 文件夹中的默认路由。运行以下命令后,它会启动一个开发服务器,并将 的内容index.js渲染到网页上。
npm run dev
构建加载屏幕组件
前面的章节引导您完成了构建加载屏幕组件所需的依赖项的安装过程,以及典型 Nextjs 应用程序中每个文件的功能。
在本节中,我们将逐步介绍构建组件本身的过程。
首先,我们来看看加载器的样式。为此,我们使用了 styled-components 库。
该Screen样式化组件作为父容器包裹加载动画。它使用fade关键帧来确保屏幕过渡效果正确无误。
// loadingScreen.js
import styled from "styled-components";
const Screen = styled.div`
position: relative;
height: 100vh;
width: 100%;
opacity: 0;
animation: fade 0.4s ease-in forwards;
background: black;
@keyframes fade {
0% {
opacity: 0.4;
}
50% {
opacity: 0.8;
}
100% {
opacity: 1;
}
}
`;
下面的代码片段展示了Balls样式化的组件。它用作子元素的容器。divs容器中对应的元素是我们将要添加动画效果的小球。
你会注意到容器中的className每个div元素都被分配了唯一的标识符。这是为了让我们能够animation-delay为每个球设置属性,从而正确地看到振荡效果。
import styled from "styled-components";
const Balls = styled.div`
display: flex;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
.ball {
height: 20px;
width: 20px;
border-radius: 50%;
background: #1b5299;
margin: 0 6px 0 0;
animation: oscillate 0.7s ease-in forwards infinite;
}
.one {
animation-delay: 0.5s;
}
.two {
animation-delay: 1s;
}
.three {
animation-delay: 2s;
}
@keyframes oscillate {
0% {
transform: translateY(0);
}
50% {
transform: translateY(20px);
}
100% {
transform: translateY(0);
}
}
`;
如果你是 CSS 动画新手,可以看看这篇讲解基础知识的指南。
现在您已经了解了以上组件的样式。接下来,我们将引用LoadingScreeen以下组件的样式。
import React from "react"
import styled from "styled-components"
const Screen = styled.div``
const Balls = styled.div``
const LoadingScreen = () => {
return (
<Screen>
<Balls>
<div className="ball one"></div>
<div className="ball two"></div>
<div className="ball three"></div>
</Balls>
</Screen>
);
};
export default LoadingScreen;
实现预加载器功能
我们已经了解了加载屏幕样式的功能以及动画在幕后的工作原理。
在本节中,我们将把组件导入到系统中_app.js。请看下面的示例。
import LoadingScreen from "../src/components/LoadingScreen";
function MyApp({ Component, pageProps }) {
const [loading, setLoading] = React.useState(false);
React.useEffect(() => {
setLoading(true);
}, []);
return (
<>
{!loading ? (
<React.Fragment>
<Component {...pageProps} />
</React.Fragment>
) : (
<LoadingScreen />
)}
</>
);
}
export default MyApp
上面的代码片段展示了我们如何使用条件渲染来检查加载组件的状态。我们需要使用useStateReact Hook 创建一个局部状态变量来保存当前状态。
const [loading, setLoading] = React.useState(false)
加载器的初始状态设置为布尔值false。
HookuseEffect是 React 中的一个生命周期方法,当 DOM 发生变化时就会触发。它整合了典型类组件的所有生命周期方法。
React.useEffect(() => {
setLoading(true);
}, []);
true通过在钩子函数中将加载器的初始“假”状态设置为useEffecttrue,我们告诉浏览器显示加载器。
结论
以前,我曾利用该setTimeout()功能在显示用户界面内容之前,先显示加载动画相当长一段时间。
React.useEffect(() =>{
setTimeout(() => setLoading(true), 6000);
})
我当时并不知道这是一种糟糕的做法。这种做法会带来很多性能问题,进而导致访问该网页应用的用户体验很差,因为网页上的内容可能在函数设定的时间之前就已经加载完毕setTimeout。
幸好Martin Vandersteen和Stephen Scaff为我做了很好的解释。你可以看看这个帖子来了解他们的想法。
下面这张 GIF 动画展示了我们一直以来一直在构建的东西。
虽然这种方法有助于我们确保网页/网站上的内容可用,但如果要处理动态数据(例如来自 API 端点的数据),方法则会略有不同。
如果您不想花费时间自己创建自定义加载组件,可以选择使用react-spinners包。
感谢您阅读本文。请在评论区留下您的想法,并将本文分享给您的朋友,谢谢。
文章来源:https://dev.to/seven/how-to-create-a-preloader-in-nextjs-15n8