feat(widgets): add server-side prefetch for weather and RSS feed
Prefetch weather and RSS feed data during SSR so widgets render with content on first paint instead of showing loading states.
This commit is contained in:
3 files changed
+55
No files matched your search
@@ -11,6 +11,8 @@ import prefetchForApps from "./app/prefetch";
|
||||
import prefetchForBookmarks from "./bookmarks/prefetch";
|
||||
import type { Prefetch, WidgetOptionsRecordOf } from "./definition";
|
||||
import type { inferOptionsFromCreator } from "./options";
|
||||
import prefetchRssFeedsAsync from "./rssFeed/prefetch";
|
||||
import prefetchWeatherAsync from "./weather/prefetch";
|
||||
|
||||
const cachedGetServerSettingsAsync = cache(getServerSettingsAsync);
|
||||
|
||||
@@ -19,6 +21,8 @@ const prefetchCallbacks: Partial<{
|
||||
}> = {
|
||||
bookmarks: prefetchForBookmarks,
|
||||
app: prefetchForApps,
|
||||
weather: prefetchWeatherAsync,
|
||||
rssFeed: prefetchRssFeedsAsync,
|
||||
};
|
||||
|
||||
export const prefetchForKindAsync = async <TKind extends WidgetKind>(
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import { api, trpc } from "@homarr/api/server";
|
||||
import { createLogger } from "@homarr/core/infrastructure/logs";
|
||||
|
||||
import type { Prefetch } from "../definition";
|
||||
|
||||
const logger = createLogger({ module: "rssFeedWidgetPrefetch" });
|
||||
|
||||
const prefetchRssFeedsAsync: Prefetch<"rssFeed"> = async (queryClient, items) => {
|
||||
for (const item of items) {
|
||||
const input = {
|
||||
urls: item.options.feedUrls,
|
||||
maximumAmountPosts: item.options.maximumAmountPosts,
|
||||
};
|
||||
|
||||
const data = await api.widget.rssFeed.getFeeds(input);
|
||||
queryClient.setQueryData(trpc.widget.rssFeed.getFeeds.queryKey(input), data);
|
||||
}
|
||||
|
||||
logger.info("Successfully prefetched RSS feeds", { count: items.length });
|
||||
};
|
||||
|
||||
export default prefetchRssFeedsAsync;
|
||||
@@ -0,0 +1,29 @@
|
||||
import { api, trpc } from "@homarr/api/server";
|
||||
import { createLogger } from "@homarr/core/infrastructure/logs";
|
||||
|
||||
import type { Prefetch } from "../definition";
|
||||
|
||||
const logger = createLogger({ module: "weatherWidgetPrefetch" });
|
||||
|
||||
const prefetchWeatherAsync: Prefetch<"weather"> = async (queryClient, items) => {
|
||||
const locations = items.map((item) => ({
|
||||
latitude: item.options.location.latitude,
|
||||
longitude: item.options.location.longitude,
|
||||
}));
|
||||
|
||||
const uniqueLocations = locations.filter(
|
||||
(loc, idx, arr) =>
|
||||
arr.findIndex((other) => other.latitude === loc.latitude && other.longitude === loc.longitude) === idx,
|
||||
);
|
||||
|
||||
await Promise.all(
|
||||
uniqueLocations.map(async (input) => {
|
||||
const data = await api.widget.weather.atLocation(input);
|
||||
queryClient.setQueryData(trpc.widget.weather.atLocation.queryKey(input), data);
|
||||
}),
|
||||
);
|
||||
|
||||
logger.info("Successfully prefetched weather data", { count: uniqueLocations.length });
|
||||
};
|
||||
|
||||
export default prefetchWeatherAsync;
|
||||
Reference in new issue
Block a user