无法让puppeteer/chromium缓存静态资源,jest测试运行过慢如何解决?
问题根因
你开启了Puppeteer的请求拦截功能后,Chromium的原生缓存机制会被绕过,所有请求会直接进入你自定义的处理逻辑,所以你设置的Cache-Control响应头不会触发浏览器原生缓存,每次请求还是会走到你的handleRequest里执行文件读取逻辑,这就是缓存不生效的核心原因。
可行解决方案
1. 实现自定义内存缓存层
既然请求已经被你接管,直接在你的请求处理逻辑里加一层内存缓存,避免每次都读磁盘和匹配资源规则,改造成本最低:
// 全局初始化一个内存缓存对象,和browser实例同生命周期 const assetCache = new Map(); async handleRequest(request) { const url = request.url(); const method = request.method(); const cacheKey = `${method}:${url}`; // 优先读缓存 if (assetCache.has(cacheKey)) { const cached = assetCache.get(cacheKey); request.respond(cached); return true; } const asset = this.assetRegistry.find(a => a.url === url && a.method === method); if (asset) { const body = fs.readFileSync(asset.file); const responseOpts = { status: asset.status || 200, contentType: resourceTypes[request.resourceType()] || null, headers: { 'Cache-Control': 'max-age=604800' }, body, }; // 写入缓存,后续请求直接返回 assetCache.set(cacheKey, responseOpts); request.respond(responseOpts); return true; } // 其余原有逻辑 ... }
静态资源只需要读一次磁盘,后续所有page的请求直接返回内存中的内容,性能提升最明显。
2. 调整启动参数与请求拦截逻辑
你当前的启动参数里--disable-background-networking会影响浏览器缓存的后台校验逻辑,如果你不需要完全禁用后台网络,可以移除这个参数。如果你的测试场景不需要修改请求响应,也可以直接关闭请求拦截,让Chromium原生缓存机制生效,不需要自己实现缓存逻辑。
3. 预加载公共资源
可以在全局初始化browser之后,先新建一个临时page访问一次你的SPA页面,把所有静态资源都提前加载到你自己实现的内存缓存里,后续所有测试用例的page发起请求时可以直接命中缓存,不需要等待第一次资源读取的开销。
4. 优化页面复用逻辑
如果你的测试用例之间没有强状态隔离要求,可以复用同一个page实例,每次测试完成后调用page.evaluate(() => window.location.href = 'about:blank')清空页面状态,不需要每次都新建page,也能减少页面初始化的开销。如果必须新建page,建议复用同一个browserContext,不要每次新建上下文,也能提升资源复用率。
内容的提问来源于stack exchange,提问作者aquavitae

