우리 모두가 冗长한 로딩 화면을 기다리는 것과 响werive 페이지를 사용할 수 없는 것의 절망을 겪었습니다. 로딩 스틱이 모두 있지만 실제 진행이 되는 것은 없습니다. clearer picture for you:
이러한 현상은 사이트가 사용자가 페이지에 도착하면 필요한 모든 데이터를 가져오려고 하는 것 때문입니다. API 요청이 처리되고 있거나, 여러 API가 seqential data를 가져오는 것이 인쇄되고 있어 페이지 로딩이 지연되는 것입니다.
결과는? 낮은 사용자 경험입니다. 생각할 수 있습니다., “그렇다고 큰 회사가 사용자 경험을 중요시하지 않을 수 있을까? 이렇게 disappointhing.” 사용자는 자주 사이트를 떠나는 것으로 보입니다. 이러한 사용자의 마이닝 수치는 중요한 통계를 인fluence 할 수 있습니다.
그러나 이러한 重型 페이지의 데이터를 사용자가 도착하기 전에 가져오는 것을 예측할 수 있으면 어떻게 되는지?
이러한 예측 로딩(prefetching)이란 어떤 것인지 이 블로그 글에서 자세히 배울 수 있습니다. 더 이상 赘述을 하지 않고 시작해보겠습니다!
목차
Prefetching을 해결책으로
다음은 문법과_SPELLING_을 수정한 버전입니다:
위의 문제의 경우, 웹사이트에 로드될 때 데이터를 가져오는 것을 원하지 않으므로 사용자는 페이지 로드 시 데이터를 가져올 필요가 없습니다. 이를 prefetching이라고 합니다. 기술적인 관점에서는 다음과 같습니다:
주요 구성 요소가 데이터를 기다리지 않고 필요한 데이터를 사전에 가져옴으로써 경험을 향상시키는 방법입니다.
이를 통해 사용자 경험을 향상시키고 고객의 웹사이트에 대한 신뢰를 높일 수 있습니다.
Prefetching은 표준 프로세스보다 사용자 중심적인 간단하지만 우아한 해결책입니다. Prefetching을 구현하려면 웹사이트에서 사용자의 행동을 이해해야 합니다. 즉, 가장 자주 방문하는 페이지나 작은 상호 작용(例如, 호버)에서 데이터를 가져오는 구성 요소입니다.
이러한 상황을 분석하면 이를 예시로 미리 불러오는 기능을 적용하는 것이 合理的하다고 생각할 수 있지만, 開発자로서는 이러한 기능을 overextensively 使用する 것을 의심해야 한다. 過剰한 미리 불러오기는 사용자의 웹사이트를 느리게 하는 것이 마찬가지로 나타날 수 있으며, 메인 страница의 데이터 불러오기를 차단하는 것이 可能하다.
미리 불러오기가 사용자 경험을 改善시키는 방법
이러한 몇 가지 상황에서 미리 불러오기가 유용하게 나타나는 것을 보자.
-
예를 들어 LANDING PAGE에 “CONTACT US” 链接을 가지고 있다고 가정하자. 이 链接이 사용자들이 가장 자주 확인하는 链接이며, 로드 시 많은 데이터가 포함되어 있다고 가정하자. CONTACT US 页面이 로드 되기 전에 데이터를 불러오는 것보다, 데이터를 HOMEPAGE에서 simplicity 로 불러오면 사용자가 CONTACT US 页面에서 데이터를 기다리는 것을 avoid하게 된다. 미리 页面을 불러오는 것에 대해 더 많은 정보를 여기에서 읽을 수 있다.
- later page에 대한 table data를 prefetching 하는 것。
-
上层组件からデータを取得し、子组件に読み込む。
-
ポップアップで表示する必要のあるデータをプリフェッチする。
이러한 방법은 응용 프로그램에서 미리 읽기를 달성하는 것을 의미하며, 사용자 경험을 改善하는 것에 도움이 됩니다.
이 블로그 게시글에서는 마지막 상황을 다룹니다: “ポップアップで表示する必要のあるデータ를 미리 읽기”이며, 이것은 미리 읽기를 유용하게 만들 수 있는 классический 예제이며, 사용자에게 更に 顺滑한 경험을 제공합니다.
문제 이해
문제를 여기서 정의합니다. 다음과 같은 상황을 상상해봅시다:
-
정보를 보여주는 컴포넌트가 있습니다.
-
이 컴포넌트 안에 또 다른 ポップアップ/툴팁을 보여주는 요소가 있습니다.
-
ポップアップ은 로드 할 때 데이터를 가져옵니다.
이제 사용자가 요소를 마우스 오버로 가져가면 데이터를 가져오고 ポップアップ에 표시하는 것을 기다리는 것을 상상해봅시다. 이 기다리는 시간을 사용자는 스틱 로더를 보게 됩니다.
이 상황은 다음과 같습니다:
사용자가 이미지 위에 마우스를 가져가는 任何时候에 대기 시간이 얼마나 길어지는지 하는 것이 建设工作이 laborious하다.
이 문제를 해결하기 위해서는, 두 가지 솔루션이 시작하고 자신의 需要에 따라 솔루션을 최적화 할 수 있습니다.
솔루션 #1: 부모 组件에서 데이터를 미리 로딩하기
이 솔루션은 Martin Fowler의 블로그 글에서 영감을 얻었습니다. 팝업이 나타나기 전에 데이터를 가져오는 것이 而不是 组件 로딩 시에 데이터를 가져오는 것입니다.
팝업은 마우스가 그 위에 올라가면 나타납니다. 마우스가 부모 组件에 들어가는 때 데이터를 가져올 수 있습니다. 실제 组件인 이미지에 마우스가 hover 되기 전에, 팝오버 组件에 대한 데이터를 가져와 그를 전달하게 됩니다.
이 솔루션은 로딩 상태를 완전히 제거하는 것이 아니지만, 로딩 상태를 dramatisch 줄이는 것을 도울 수 있습니다.
솔루션 #2: 页面 로딩 시에 데이터를 미리 로딩하기
이 솔루션은 x.com에서 영감을 얻었습니다. 팝오버 组件에 대해서, 主要 页面 로딩 시에 데이터를 部分적으로 가져와 组件가 마ounted되면 나머지 데이터를 가져오는 것입니다.
上面的 视频에서, 사용자의 프로필 세부 정보가 팝오버에서 볼 수 있습니다. 자세히 보시면, 关注者 관련 정보는 나중에 가져와진 것입니다.
이 기술은 팝오버에 표시할 데이터가 많을 때 매우 효율적입니다. 그러나 이를 가져오는 것이 팝오버 마ount 시나 주요 페이지 로드 시에 비용이 많이 드는 것을 고려하면 더 좋은 솔루션을 찾아야 합니다.
이러한 솔루션은 주요 페이지에서 필요한 데이터를 부분적으로 로드하고 компонент 마운트 시에 나머지 데이터를 로드하는 것입니다.
우리의 예에서는 마우스가 이미지의 親 요소로 들어갔을 때 팝오버에 필요한 데이터를 가져옵니다. 이제 팝오버 데이터가 로드되면 추가적인 자세한 정보를 가져야 하는 것을 상상하세요. 따라서 위에서 말한 x.com의 방법에 따라 팝오버 로드 시에 추가적인 데이터를 가져올 수 있습니다. 이것의 결과는 다음과 같습니다.
이곳에서 다음과 같은 것을 하고 있습니다.
-
마우스가 이미지의 親 요소로 들어갔을 때 팝오버를 렌더링하기 위해 필요한 주요 데이터를 가져옵니다.
-
이렇게 주요 데이터를 가져오는 시간을 충분히 줍니다.
-
팝오버 로드 시에는 다른 데이터를 가져옵니다. 이것은 앨범 수입니다. 사용자가 이름과 이메일과 같은 데이터를 읽는 동안에도 다음 데이터가 사용할 수 있도록 준비되어 있습니다.
이러한 방법으로 컴포넌트에 적절한 미리 가져오는 기능을 추가하여 화면에서 로더의 기다리는 시간을 최소화할 수 있습니다. 😊
React로 미리 가져오기를 적용하는 방법
이 섹션에서는 예시 어플리케이션의 구현 방법에 대해 간단히 説明할 것입니다.
프로젝트 세팅
예시 어플리케이션 만들기 시작하기 전에 다음과 같은 과정을 따라야 합니다.:
이 예시에서는 vitejs (저는 이것을 사용했습니다) 또는 create-react-app를 사용하여 어플리케이션을 만들 수 있습니다. 아래 명령을 terminals에 붙여넣습니다:
yarn create vite prefetch-example --template react-ts
어플리케이션이 만들어지면, prefetch-example 폴더를 VS Code로 열었을 때 다음과 같은 폴더 구조가 있어야 합니다.
이제 이 어플리케이션에 빌드 할 컴포넌트에 대해 이동합니다.
컴포넌트
이 예시에서는 다음 세 COMPONENTS를 사용할 것입니다:
-
PopoverExample
-
UserProfile
-
UserProfileWithFetching
PopoverExample
컴포넌트
첫 번째 컴포넌트로 PopoverExample
를 시작해봅시다. 이 컴포넌트는 이미지 아바타와 왼쪽에 一些 텍스트를 보여줍니다. 이렇게 보이는 것이 아닐 것입니다:
이 컴포넌트의 목적은 실제 옵션과 유사한 예시를 제공하는 것입니다. 이 컴포넌트의 이미지는 마우스 오버 시에 팝overed 컴포넌트를 로딩합니다.
以下是文本的韩语翻译,按照您的要求保留了自定义分隔符。
Here’s the code for the component:
import { useState } from "react";
import { useFloating, useHover, useInteractions } from "@floating-ui/react";
import ContentLoader from "react-content-loader";
import UserProfile from "./UserProfile";
import UserProfileWithFetching from "./UserProfileWithFetching";
export const MyLoader = () => (
<ContentLoader
speed={2}
width={340}
height={84}
viewBox="0 0 340 84"
backgroundColor="#d1d1d1"
foregroundColor="#fafafa"
>
<rect x="0" y="0" rx="3" ry="3" width="67" height="11" />
<rect x="76" y="0" rx="3" ry="3" width="140" height="11" />
<rect x="127" y="48" rx="3" ry="3" width="53" height="11" />
<rect x="187" y="48" rx="3" ry="3" width="72" height="11" />
<rect x="18" y="48" rx="3" ry="3" width="100" height="11" />
<rect x="0" y="71" rx="3" ry="3" width="37" height="11" />
<rect x="18" y="23" rx="3" ry="3" width="140" height="11" />
<rect x="166" y="23" rx="3" ry="3" width="173" height="11" />
</ContentLoader>
);
export default function PopoverExample() {
const [isOpen, setIsOpen] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const [data, setData] = useState({});
const { refs, floatingStyles, context } = useFloating({
open: isOpen,
onOpenChange: setIsOpen,
placement: "top",
});
const hover = useHover(context);
const { getReferenceProps, getFloatingProps } = useInteractions([hover]);
const handleMouseEnter = () => {
if (Object.keys(data).length === 0) {
setIsLoading(true);
fetch("https://jsonplaceholder.typicode.com/users/1")
.then((resp) => resp.json())
.then((data) => {
setData(data);
setIsLoading(false);
});
}
};
return (
<div
id="hover-example"
style={{
display: "flex",
flexDirection: "row",
alignItems: "center",
textAlign: "left",
}}
onMouseEnter={handleMouseEnter}
>
<span
style={{
padding: "1rem",
}}
>
<img
ref={refs.setReference}
{...getReferenceProps()}
style={{
borderRadius: "50%",
}}
src="https://cdn.jsdelivr.net/gh/alohe/avatars/png/vibrent_5.png"
/>
</span>
<p>
Lorem Ipsum is simply dummy text of the printing and typesetting
industry. Lorem Ipsum has been the industry's standard dummy text ever
since the 1500s, when an unknown printer took a galley of type and
scrambled it to make a type specimen book. It has survived not only five
centuries, but also the leap into electronic typesetting, remaining
essentially unchanged. It was popularised in the 1960s with the release
of Letraset sheets containing Lorem Ipsum passages, and more recently
with desktop publishing software like Aldus PageMaker including versions
of Lorem Ipsum.
</p>
{isOpen && (
<div
className="floating"
ref={refs.setFloating}
style={{
...floatingStyles,
backgroundColor: "white",
color: "black",
padding: "1rem",
fontSize: "1rem",
}}
{...getFloatingProps()}
>
{isLoading ? (
<MyLoader />
) : (
<UserProfile hasAdditionalDetails {...data} />
)}
{/* <UserProfileWithFetching /> */}
</div>
)}
</div>
);
}
There are couple of things happening here, let me explain them step-by-step:
-
여기서 몇 가지 일이 있습니다, 저를 한 걸음씩 설명 드리겠습니다.
-
다음으로,
floating
라는 클래스 이름을 가진div
를 조건부로 렌더링했습니다. 이것은 이미지를 호버할 때 열리는 실제 팝오버 컴포넌트입니다.floating-ui
라이브러리를 사용하고 그의 기본 호버 예제를 이용하여 팝오버의 호버 효과를 달성했습니다.
-
팝오버 안에서는
UserProfile
와 스켈레톤 로더를 조건부로 로드했습니다. 이 로더는 사용자 프로필 데이터를 가져오는 동안 나타납니다. 이에 대한 자세한 내용은 나중에 설명드리겠습니다. -
이번에는
MyLoader
컴포넌트에서 react-content-loader 라이브러리를 사용하였습니다. 이 라이브러리는 로더를 생성하는 도움이 되는 웹사이트가 있으며, 여기서 확인할 수 있습니다.
UserProfile
컴포넌트
이제 Popover
예시를 정의했으므로, UserProfile
컴포넌트에 대한 세부사항을 알아보는 시간이 되었습니다.
이 컴포넌트는 팝오버 компо넌트 내에서 나타나며, name
, email
, phone
, website
정보를 로드하는 것이 목적입니다. 이러한 정보는 JSON placeholder API에서 읽어들여집니다.
UserProfile
컴포넌트가 visuals only 컴포넌트로 작동하는지 확인하기 위해서는 이 컴포넌트 내에서 명시적인 데이터 가져오는 로직이 있는지 확인할 필요가 있습니다.
이 컴포넌트의 주요 특징은 부모 컴포넌트인 PopoverExample
컴포넌트에서 데이터 가져오는 것입니다. 이 컴포넌트에서는 마우스가 이 컴포넌트로 들어갔을 때(mouseenter
이벤트) 데이터 가져오기를 시작합니다. 이것은 이전에 discuss 한 솔루션 #1입니다.
이러한 구성은 사용자가 이미지 위로 마우스를 올렸을 때까지 데이터를 가져오는 시간을 충분히 제공합니다. 이 코드가 다음과 같습니다:
import { useEffect, useState } from "react";
import ContentLoader from "react-content-loader";
const MyLoader = () => (
<ContentLoader
speed={2}
viewBox="0 0 476 124"
backgroundColor="#d1d1d1"
foregroundColor="#fafafa"
>
<rect x="4" y="43" rx="0" ry="0" width="98" height="30" />
</ContentLoader>
);
export default function UserProfile(props: Record<string, string | boolean>) {
const { name, email, phone, website, hasAdditionalDetails } = props;
const [isLoading, setIsLoading] = useState(false);
const [additionalData, setAdditionalData] = useState(0);
useEffect(() => {
if (hasAdditionalDetails) {
setIsLoading(true);
fetch("https://jsonplaceholder.typicode.com/albums")
.then((resp) => resp.json())
.then((data: Array<unknown>) => {
const albumCount = data.reduce((acc, curr) => {
if (curr.userId === 1) acc += 1;
return acc;
}, 0);
setAdditionalData(albumCount);
})
.finally(() => {
setIsLoading(false);
});
}
}, [hasAdditionalDetails]);
return (
<div id="user-profile">
<div id="user-name">name: {name}</div>
<div id="user-email">email: {email}</div>
<div id="user-phone">phone: {phone}</div>
<div id="user-website">website: {website}</div>
{hasAdditionalDetails && (
<>
{isLoading ? (
<MyLoader />
) : (
<div id="user-albums">Album Count: {additionalData}</div>
)}
</>
)}
</div>
);
}
이 컴포넌트는 hasAdditionalDetails
프로퍼티를 사용합니다. 이 프로퍼티의 목적은 컴포넌트가 마ounted되었을 때 extra data를 로드하는 것입니다. 이것은 위에서 mentioned 한 솔루션 #2를 설명합니다.
UserProfileWithFetching
컴포넌트
이 컴포넌트는 UserProfile
컴포넌트와 fairly 비슷합니다. 이 컴포넌트는 컴포넌트가 로드되었을 때 데이터 가져오는 로직을 포함합니다. 이 컴포넌트의 목적은 미리fetching 기술을 사용하지 않은 일반적인 솔루션을 보여주는 것입니다.
따라서 이 컴포넌트는 컴포넌트가 mount되었을 때 대부분 data를 로드하며 skeleton loader를 보여줍니다.
이 코드는 다음과 같습니다:
import { useEffect, useState } from "react";
import { MyLoader } from "./PopoverExample";
export default function UserProfileWithFetching() {
const [isLoading, setIsLoading] = useState(false);
const [data, setData] = useState<Record<string, string>>({});
useEffect(() => {
setIsLoading(true);
fetch("https://jsonplaceholder.typicode.com/users/1")
.then((resp) => resp.json())
.then((data) => {
setData(data);
setIsLoading(false);
});
}, []);
if (isLoading) return <MyLoader />;
return (
<div id="user-profile">
<div id="user-name">name: {data.name}</div>
<div id="user-email">email: {data.email}</div>
<div id="user-phone">phone: {data.phone}</div>
<div id="user-website">website: {data.website}</div>
</div>
);
}
이 앱의 모든 코드는 here에 있습니다.
과하한 prefetching이 느리게 만들 수 있습니다.
이러한 忠告를 들어 과하한 prefetching은 좋지 않습니다. 이유는 다음과 같습니다:
-
이것은 您的应用程序를 느리게 할 수 있습니다.
-
전략적으로 prediction이 적용되지 않는다면 사용자 经验이 저하될 수 있습니다.
prediction을 적용하는 것은 사용자의 행위를 이해할 때입니다. 즉, 인자의 값을 통해 사용자의 이동을 예측할 수 있고 他们이 주 주소를 방문하는지 여부를 알 수 있습니다. 그 경우 prediction이 좋은 아이디어입니다.
따라서 전략적으로 prediction을 적용하는 것을 기억하십시오.
요약
이제 여기가 모두 끝입니다! 저의 블로그 포스트를 좋아하시면 좋겠습니다. 이 블로그 포스트에서는 예측을 적용하는 것이 웹 응용 프로그램의 速度와 대응성을 значитель하게 향상시키는 것을 배울 수 있습니다. 이를 통해 사용자의 만족도를 향상시킵니다.
자세한 정보를 찾으시려면 아래 記事을 참조하십시오:
더 많은 내용을 보고하고자 한다면, 저를 Twitter, GitHub, 그리고 LinkedIn에서 ollow 해 주세요.
Source:
https://www.freecodecamp.org/news/boost-web-performance-with-prefetching/