[英]How do I use in-memory cache in Remix.run dev mode?
I need to fetch data from an API that is pretty slow and seldom changes, so I thought I'd use an in-memory cache.我需要从速度很慢且很少更改的 API 中获取数据,所以我想我会使用内存缓存。 I first tried a very simple approach by just saving it to a variable outside the scope of the loader function in my route:
我首先尝试了一种非常简单的方法,只需将其保存到我的路径中加载程序 function 的 scope 之外的变量中:
let cache;
export const loader = async () => {
if (!cache) {
// we always end up here
cache = await (await fetch("...)).json()
}
}
but that didn't work.但这没有用。 I then tried a proper caching library (
lru-cache
), but that cache was also always empty.然后我尝试了一个适当的缓存库(
lru-cache
),但那个缓存也总是空的。 I then realized that the entired file got reloaded on each request which I guess is a dev mode thing, so I tried moving the creation of the cache to a separate file cache.server.ts and importing it from there.然后我意识到整个文件都会在每个请求上重新加载,我猜这是一个开发模式的事情,所以我尝试将缓存的创建移动到一个单独的文件cache.server.ts并从那里导入它。
import LRU from "lru-cache";
console.log("Creating cache"); // this is logged on each request
const cache = new LRU({ max: 200 });
export default cache;
But that file also seems to be reloaded on each request.但是该文件似乎也会在每次请求时重新加载。
If I build a production version and run that everything works great, but it would be nice to have some way of getting it to work in dev mode as well.如果我构建了一个生产版本并运行它,一切都很好,但如果能有某种方法让它在开发模式下也能工作,那就太好了。
Remix purges the require
cache on every request in development to support <LiveReload/>
. Remix 清除开发中每个请求的
require
缓存以支持<LiveReload/>
。 To make sure your cache survives these purges, you need to assign it to the global
object.为了确保您的缓存能够在这些清除中幸存下来,您需要将其分配给
global
对象。
Here's an example from the Jokes Tutorial这是笑话教程中的一个示例
import { PrismaClient } from "@prisma/client";
let db: PrismaClient;
declare global {
var __db: PrismaClient | undefined;
}
// this is needed because in development we don't want to restart
// the server with every change, but we want to make sure we don't
// create a new connection to the DB with every change either.
if (process.env.NODE_ENV === "production") {
db = new PrismaClient();
} else {
if (!global.__db) {
global.__db = new PrismaClient();
}
db = global.__db;
}
export { db };
https://remix.run/docs/en/v1/tutorials/jokes#connect-to-the-database https://remix.run/docs/en/v1/tutorials/jokes#connect-to-the-database
As a follow up on Kilimans answer, here's how I did it:作为对 Kilimans 回答的跟进,我是这样做的:
/*
* @see https://www.npmjs.com/package/node-cache
*/
import NodeCache from "node-cache";
let cache: NodeCache;
declare global {
var __cache: NodeCache | undefined;
}
const cacheSettings = {
stdTTL: 60 * 60 * 24,
checkperiod: 60 * 60 * 24,
};
if (process.env.NODE_ENV === "production") {
cache = new NodeCache(cacheSettings);
} else {
if (!global.__cache) {
global.__cache = new NodeCache(cacheSettings);
}
cache = global.__cache;
}
export { cache };
And I used it in the loader:我在加载器中使用它:
import { getGitHubRepos } from "~/models/github.server";
import { cache } from "~/utils/cache";
export async function loader(args: LoaderArgs) {
if (cache.has("GitHubRepos")) {
return json(cache.get("GitHubRepos"));
}
const repos = await getGitHubRepos();
cache.set("GitHubRepos", repos);
return json(repos);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.