
Security News
Browserslist-rs Gets Major Refactor, Cutting Binary Size by Over 1MB
Browserslist-rs now uses static data to reduce binary size by over 1MB, improving memory use and performance for Rust-based frontend tools.
@shopify/react-async
Advanced tools
Tools for creating powerful, asynchronously-loaded React components.
@shopify/react-async
Tools for creating powerful, asynchronously-loaded React components.
$ yarn add @shopify/react-async
createAsyncComponent()
createAsyncComponent
is a function for creating components that are loaded asynchronously on initial mount. However, the resulting component does more than just help you split up your application along component lines; it also supports customized rendering for loading, and creates additional components for smartly preloading or preloading the component’s bundle. Best of all, in conjunction with the Babel and Webpack plugins provided by @shopify/async
, you can easily extract the bundles needed to render your application during server side rendering.
To start, import the createAsyncComponent
function. The simplest use of this function requires just a load
function, which returns a promise for a component:
import {createAsyncComponent} from '@shopify/react-async';
const MyComponent = createAsyncComponent({
load: () => import('./MyComponent'),
});
This function returns a component that accepts the same props as the original one.
createAsyncComponent
also adds a few static members that are themselves components: Preload
, Prefetch
, and KeepFresh
.
const MyComponent = createAsyncComponent({
load: () => import('./MyComponent'),
});
// All of these are available:
<MyComponent />
<MyComponent.Prefetch />
<MyComponent.Preload />
<MyComponent.KeepFresh />
By default, Preload
, Prefetch
, and KeepFresh
all simply prefetch the bundle for the component in the background. However, you can provide additional markup to render in these components with the renderPreload
, renderPrefetch
, and renderKeepFresh
options to createAsyncComponent
:
const MyComponent = createAsyncComponent({
load: () => import('./MyComponent'),
renderPrefetch: () => <PrefetchSomethingElse />,
});
// Now prefetches the component, and <PrefetchSomethingElse />!
<MyComponent.Prefetch />;
While you can supply whatever markup you like for these, we recommend that you use them for the following purposes:
Prefetch
: loading resources that will be used by the componentPreload
: loading resources and data that will be used by the componentKeepFresh
: loading resources and data that will be used by the component, and keeping data up to dateIf you want props for your Preload
, Prefetch
, or KeepFresh
components, simply provide them in the render
option for that component. The resulting components will have those prop types baked in.
const MyComponent = createAsyncComponent({
load: () => import('./MyComponent'),
renderPreload: ({priority}: {priority: 'high' | 'low'}) => (
<PreloadSomethingElse priority={priority} />
),
});
// This is a type error, we need a `priority` prop!
<MyComponent.Preload />;
// Ah, much better!
<MyComponent.Preload priority="high" />;
This system is designed to work well with our @shopify/react-graphql
package. Simply create an async GraphQL query using that library, and then Prefetch
, Preload
, and KeepFresh
that component alongside the React component itself:
const MyQuery = createAsyncComponent({
load: () => import('./graphql/MyQuery.graphql'),
});
const MyComponent = createAsyncComponent({
load: () => import('./MyComponent'),
renderLoading: () => <Loading />,
// If you use `graphql-typescript-definitions` for generating types from your
// GraphQL documents, you'll be warned if there are required variables you aren’t
// providing here!
renderPrefetch: () => <MyQuery.Prefetch />,
renderPreload: () => <MyQuery.Preload />,
renderKeepFresh: () => <MyQuery.KeepFresh />,
});
Prepare
The Prepare
component allows you to use the asynchronous component you generated with createAsyncComponent
and automatically render its Prefetch
component when the user looks like they are going to navigate to a page that uses it. This component takes as its props the asynchronous component, a URL pattern to look for (a string or RegExp
that is compared against the target pathname), and an optional function that can map the URL to a set of props for your prefetch component.
Consider this async component:
const ProductDetails = createAsyncComponent({
load: () => import('./ProductDetails'),
renderPrefetch: ({id}: {id: string}) => <PrefetchGraphQLQuery id={id} />,
});
This component might be rendered when the URL matches /products/:id
. If we want to prefetch this component (including its GraphQL query!) whenever the user is going to navigate to a matching URL, we would register this intent with the following Prepare
component:
<Prefetch
component={ProductDetails}
url={/^\/products\/(\d+)$/}
mapUrlToProps={pathname => {
// If you don’t pass the right types, or don’t pass mapUrlToProps()
// at all, you’ll get a type error.
const id = pathname.split('/').pop();
return {id};
}}
/>
And that’s it. While we reserve the right to change it, the basic process for determining merchant navigation intent is fairly simple. We listen for users mousing over or focusing in to elements with an href
attribute (or, data-href
, if you can’t use a real link) and, if the user doesn’t mouse/ focus out in some small amount of time, we prefetch all matching components. We also do the prefetch when the user begins their click on an element with an href
attribute.
AsyncManager
and AsyncProvider
AsyncManager
and AsyncProvider
allow you to extract the asynchronous bundles that were required for your application. If you use the Babel plugin, every component created by createAsyncComponent
will report its existence when rendered to an AsyncManager
. So, on the server, you simply need to provide an AsyncManager
to your app, render the app to a string, and then inspect the AsyncManager
’s used
property.
import {AsyncManager, AsyncProvider} from '@shopify/react-async';
const asyncManager = new AsyncManager();
renderToString(
<AsyncProvider manager={asyncManager}>
<App />
</AsyncProvider>,
);
const moduleIds = [...asyncManager.used];
These module IDs can be looked up in the manifest created by @shopify/async
’s Webpack plugin. If you are using sewing-kit-koa
, you can follow the instructions from that package to automatically collect the required JavaScript and CSS bundles.
FAQs
Tools for creating powerful, asynchronously-loaded React components
The npm package @shopify/react-async receives a total of 23,958 weekly downloads. As such, @shopify/react-async popularity was classified as popular.
We found that @shopify/react-async demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Browserslist-rs now uses static data to reduce binary size by over 1MB, improving memory use and performance for Rust-based frontend tools.
Research
Security News
Eight new malicious Firefox extensions impersonate games, steal OAuth tokens, hijack sessions, and exploit browser permissions to spy on users.
Security News
The official Go SDK for the Model Context Protocol is in development, with a stable, production-ready release expected by August 2025.