경로 기반 코드 분할 앱에 사전 로드를 추가하는 방법
React Loadable과 React Lazy 및 Suspense를 처음 사용한 이후로, 나는 큰 응용 프로그램을 위한 라우트 기본 코드 분할을 크게 옹호했습니다. 이를 통해 클라이언트는 화면에 무언가를 렌더링 하기 전에 전체 앱을 다운로드하지 않고 실제로 액세스하는 앱의 청크만 로드 할 수 있습니다. 이 패턴은 React Library의 공식 문서에도 나와 있습니다.
그러나 나는 항상 최종 사용자 경험을 더 좋게 만드는 방법에 대한 팁과 요령을 찾고 있습니다. 그래서 최근에 경로 기본 코드 분할에서 청크를 미리 로드하는 방법의 문제를 해결하려고 시도했습니다. 청크 간 탐색을 보다 원활하게 합니다. 일부 Gatsby 사이트에서 이 동작을 보았고 그것이 얼마나 이산적이고 효율적인지 정말 좋아했습니다. 그렇기 때문에 사전 로드 구현에 대한 독자적인 의견을 작성하고 모든 사람과 공유하기로 결정했습니다.
참고 :이 구현은 react-router-dom을 기반으로 하고 16.8.0 이상을 반응 시킵니다. 이 게시물에 사용 된 코드는 여기에 있습니다.
https://blog.maximeheckel.com/posts/preloading-views-with-react
Our app
방문 페이지 경로, 할 일 목록을 가져 오는 또 다른 일, 할 일을 검사하는 다른 일 등 여러 경로가 있는 React 앱을 살펴 보겠습니다. 각 경로는 특정 뷰 / 구성 요소를 렌더링 합니다. 코드 분할에 대한 React 문서를 주의 깊게 읽고 React.Lazy 및 React.Suspense를 사용하여 다음과 유사한 코드베이스를 얻었습니다.
import React from 'React';
import { Route, Router, Switch } from 'react-router-dom'
const App = React.lazy(() => import('./App'));
const Todos = React.lazy(() => import('./Todos'));
const Todo = React.lazy(() => import('./Todo'));
const routes = [
{ path: "/", exact: true, component: App },
{ path: "/todos", exact: true, component: Todos },
{ path: "/todos/:id", exact: true, component: Todo }
];
ReactDOM.render(
<Router>
<React.Suspense fallback={"Loading"}>
<Switch>
{routes.map(route => (
<Route
key={route.path}
exact={route.exact}
path={route.path}
component={route.component}
/>
))}
</Switch>
</React.Suspense>
</Router>
);
앱을 실행하면 브라우저의 개발자 도구에서 한보기에서 다른 보기로 이동하는 것이 앱의 다른 "조각"또는 "청크"를 로드하고 있음을 알 수 있습니다. 이제 사용자가 새 경로로 이동 한 후 로드 하지 않고 탐색 링크 중 하나를 가리킬 때 이러한 청크를 로드 할 수 있는 방법에 초점을 맞추겠습니다.
React Lazy를 사용하여 사전로드 컴포넌트
뷰를 사전 로드 하려면 청크에서 사전로드 메소드를 호출 할 수 있어야 합니다. 이 사전 로드 메소드는 React Lazy에 전달 된 가져 오기 명령문을 실행하기 위해 호출 될 수 있습니다. 이러한 기능은 React Loadable에서 즉시 사용할 수 있지만 React Lazy는 제공하지 않는 것 같으므로 다음 코드를 사용하여 처음부터 구현해야 합니다.
const ReactLazyPreload = importStatement => {
const Component = React.lazy(importStatement);
Component.preload = importStatement;
return Component;
};
이제 코드 분할 청크를 다음과 같이 다시 선언 할 수 있습니다.
const App = ReactLazyPreload(() =>
import("./App")
);
const Todos = ReactLazyPreload(() =>
import("./Todos")
);
const Todo = ReactLazyPreload(() =>
import("./Todo")
);
위의 코드를 사용하여 컴포넌트에 대해 프리로드 메소드를 호출 할 수 있으며, 그 결과 각각의 컴포넌트가 각각의 청크를로드하게됩니다.
App.preload()
Todos.preload()
Todo.preload()
주어진 경로에 대한 올바른 구성 요소에 대한 사전 로드 호출
사용자가 주어진 링크를 가리킬 때 미리 로드 할 구성 요소를 지정할 수 있지만 경로를 기반으로 미리 로드 할 구성 요소를 "찾을"수 있다면 좋지 않을까요? 이 포스트의 첫 번째 코드 스니펫을 살펴보면 React Router Route 구성 요소에 필요한 모든 속성이 포함 된 routes 객체를 선언했음을 알 수 있습니다. 이것은 의도적이며 어떤 구성 요소가 어떤 경로와 연관되어 있는지 찾는 데 유용합니다.
findComponentForRoute 함수를 선언하자 :
import { matchPath } from "react-router-dom";
const findComponentForRoute = (path, routes) => {
const matchingRoute = routes.find(route =>
matchPath(path, {
path: route.path,
exact: route.exact
})
);
return matchingRoute ? matchingRoute.component : null;
};
React Router에는 matchPath라는 매우 편리한 메소드가 제공되는데, 주어진 경로에 대해 두 번째 인수로 전달 된 경로가 일치하면 true를 반환합니다. 위의 코드 스니펫의 함수는 이 방법을 사용하며 일치하는 것이 있으면 연결된 구성 요소를 반환하거나 경로를 찾지 못하면 null을 반환합니다.
주어진 경로에 관련된 컴포넌트를 찾을 수 있는 방법이 있으므로, 미리 로드 하는 함수를 만들 수 있습니다 :
const preloadRouteComponent = (path) => {
const component = findComponentForRoute(path, routes);
if (component && component.preload) {
component.preload();
}
};
마지막으로 onMouseEnter 이벤트 핸들러에 이 함수를 모든 Link 구성 요소에 추가하고 하루에 호출 할 수 있지만 방금 구현 한 기능을 보다 쉽게 사용할 수 있습니다. Link와 동일한 소품을 가지지 만 preloadRouteComponent 함수를 사용하는 LinkWithPreload 구성 요소를 만들어 보겠습니다.
import { Link } from 'react-router-dom'
...
const LinkWithPreload = ({ to, onPreload, ...rest }) => {
return (
<Link
to={to}
onMouseEnter={() => preloadRouteComponent(to)}
{...rest}
/>
);
};
export default LinkWithPreload;
이제 링크 대신이 구성 요소를 사용하여 아래에서 볼 수 있듯이 앱에서 탐색 링크를 가리키면 해당 링크의 경로와 관련된 청크를 로드해야 합니다.
전체 코드를 보시겠습니까? 이 기사에 소개 된 앱을 여기에서 사용할 수 있게 했습니다!
등록된 댓글이 없습니다.