You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Express部署的Create-React-App配置高效缓存策略以通过Lighthouse审计

Fixing "Serve static assets with an efficient cache policy" for Create-React-App + Express on Heroku

Hey there! I totally get wanting to nail those Lighthouse audits before diving into your actual project—great call. Let's break down why you're seeing that error and how to fix it with your Express setup.

The Root Issue

By default, express.static doesn't set aggressive enough caching headers for static assets. Create-React-App generates static files (like JS bundles, CSS, images) with content-hashed filenames (e.g., main.abc123.js), which means the filename changes automatically whenever the file content updates. This lets us safely cache these files for a very long time. The only exception is index.html—we can't cache it for too long, since it's the entry point to your app and needs to pull in the latest hashed assets when you deploy updates.

Step 1: Update Your server.js

First, we'll modify how Express serves static files to set proper cache headers. We'll also make sure we're serving the optimized build folder (not the raw public folder from CRA, which is intended for development use).

Here's the updated server.js:

const express = require("express");
const app = express();
const helmet = require("helmet");
const path = require("path"); // Add this to handle file paths properly

app.use(
  helmet({
    dnsPrefetchControl: false,
    contentSecurityPolicy: false,
  })
);

// Serve static assets with optimized caching headers
app.use(express.static(path.join(__dirname, "build"), {
  maxAge: "1y", // Cache hashed assets for 1 year
  etag: false, // Disable ETags since filenames already have content hashes
  setHeaders: (res, filePath) => {
    // Don't cache index.html—we need it to fetch the latest assets on deploy
    if (filePath.endsWith("index.html")) {
      res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
      res.setHeader("Pragma", "no-cache");
      res.setHeader("Expires", "0");
    }
  }
}));

// Catch-all route to serve index.html (works for React Router too, if you add it later)
app.get("*", (req, res) => {
  res.sendFile(path.join(__dirname, "build", "index.html"));
});

const listener = app.listen(process.env.PORT || 3000, () => {
  console.log("Your app is listening on port " + listener.address().port);
});

Step 2: Configure Heroku to Build Your React App

Make sure your package.json tells Heroku to build your CRA app during deployment. Add a heroku-postbuild script to automate this step:

{
  "name": "your-app-name",
  "version": "0.1.0",
  "scripts": {
    "start": "node server.js",
    "build": "react-scripts build",
    "heroku-postbuild": "npm run build" // This runs automatically on Heroku after deployment
  },
  // ... rest of your package.json content
}

Why This Works

  • Hashed assets (JS/CSS/images): The maxAge: "1y" tells browsers to cache these files for a full year. Since the filename changes when the content updates, browsers will automatically request the new file when you deploy changes—no stale cache issues.
  • index.html: The no-cache headers ensure browsers always check if there's a new version of index.html when users visit your site. This way, they'll get the latest references to your hashed assets right after a deploy.

Verify the Fix

After deploying these changes to Heroku, run another Lighthouse audit. The "Serve static assets with an efficient cache policy" error should be resolved. You can also double-check the response headers using Chrome DevTools:

  • Go to the Network tab
  • Reload your site
  • Click on any JS/CSS file—you should see Cache-Control: public, max-age=31536000
  • Click on index.html—you should see Cache-Control: no-cache, no-store, must-revalidate

内容的提问来源于stack exchange,提问作者Hunter Scott Lacefield

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 14:53:00