Next.js: Set proper Cache-Control max-age for static assets

Created on 24 Apr 2017  路  15Comments  路  Source: vercel/next.js

I am missing a proper max-age resp. Cache-Control header set for /static assets (serve defaults to set max-age to 0). I plan to invalidate/bust the browser cache using query parameters on these. Shouldn't static assets always be served with long max-age?

Most helpful comment

I ran into this problem when using CloudFlare as a CDN. It takes the cache settings from the origin server (max-age=0), so all assets in /static/ are not cached despite being on the CDN. A next.js config setting would be nice as an improvement at some point, but a workaround if using Express as a server is pretty easy:

    server.use("/static", express.static(__dirname + "/static", {
        maxAge: "365d"
    }));

It needs to come before the next catch-all '*' route in your server.js to take effect.

All 15 comments

That idea is that you set a CDN, I think the Next static folder it's only for development usage.

@dbo since we don't hash static files, we are not possible to do that.
It's a pretty good idea to move your static content into a CDN or something similar and avoid /static as possible as you can.

We should improve this behavior in the future. But it's not happening anytime sooner.

@arunoda So if it's generally discouraged to be used on zeit/now (other than during dev-time), I think it's worth to be stressed out in the README.

I ran into this problem when using CloudFlare as a CDN. It takes the cache settings from the origin server (max-age=0), so all assets in /static/ are not cached despite being on the CDN. A next.js config setting would be nice as an improvement at some point, but a workaround if using Express as a server is pretty easy:

    server.use("/static", express.static(__dirname + "/static", {
        maxAge: "365d"
    }));

It needs to come before the next catch-all '*' route in your server.js to take effect.

@mike-low
You don't sent immutable ?

Mine is like

app.use(Express.static(path.join(appDir, '/dist/'), {
    setHeaders(res) {
        res.setHeader("Cache-Control", "public,max-age=31536000,immutable");
    }
}));

@sergiodxa Probably at least files from _next should get non-zero max age by default as they are in hashed folders.

since we don't hash static files, we are not possible to do that.

Any plan to change that one day? Having expire headers is quite common and a recommended practice

you can use the render api to set this now
https://nuxtjs.org/api/configuration-render/

@bovas85 I've hidden your comment as it's related to Nuxt.js, not Next.js.

Sorry! I read nuxt and commented 馃憥 my bad :)

@bovas85 no worries at all 馃槃

i tried providing max-age like @mike-low and @aseem2625 suggested, but it did not change the cache header on my static resources. any suggestions? i also tried etag: false without any effect.

server.use("/static", express.static(__dirname + "/static", {
maxAge: "365d"
}));

This works for /static folder, but not for /_next/static... I tried changing /static to /_next or /_next/static, but that did not work either.

I put this line right above this one, as suggested:

    server.get( '*', ( req, res ) => {
        return handle( req, res );
    } );

Response header cache-control max-age is still 0 for CSS files coming from /_next/static/css. Any tips?

Same here.

I have the following, which is not working

 app.prepare().then(() => {
const server = express();


server.use('/images', express.static(path.join(__dirname, 'images'), {
    maxAge: dev ? '0' : '365d'
}));
server.use(compression());
server.use(bodyParser.json());

 server.get('*', (req, res) => {
        res.setHeader(
          "Cache-Control",
          "public, max-age=31536000, immutable",
        );

    return handle(req, res)
});

@DaleOC @geochanto @fabb I had the same issue. Eventually got it:

(async () => {
  await app.prepare();
  const server = express();

  server.get("*.woff2?", (req, res) => {
    res.setHeader("Cache-Control", "public,max-age=31536000,immutable");
    return handle(req, res);
  });

  server.get("*", (req, res) => handle(req, res));

  await server.listen(port);
  console.log(`> Ready on http://localhost:${port}`); // eslint-disable-line no-console
})();
Was this page helpful?
0 / 5 - 0 ratings

Related issues

swrdfish picture swrdfish  路  3Comments

flybayer picture flybayer  路  3Comments

olifante picture olifante  路  3Comments

timneutkens picture timneutkens  路  3Comments

knipferrc picture knipferrc  路  3Comments