Skip to content

Commit 8372c59

Browse files
authored
Merge branch 'main' into closerace
2 parents 69aec02 + f7b4849 commit 8372c59

File tree

2 files changed

+62
-4
lines changed

2 files changed

+62
-4
lines changed

site/nextrouter/nextrouter.go

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,7 @@ func Handler(fileSystem fs.FS, options *Options) (http.Handler, error) {
4949
}
5050

5151
// Fallback to static file server for non-HTML files
52-
// Non-HTML files don't have special routing rules, so we can just leverage
53-
// the built-in http.FileServer for it.
54-
fileHandler := http.FileServer(http.FS(fileSystem))
55-
router.NotFound(fileHandler.ServeHTTP)
52+
router.NotFound(FileHandler(fileSystem))
5653

5754
// Finally, if there is a 404.html available, serve that
5855
err = register404(fileSystem, router, *options)
@@ -64,6 +61,31 @@ func Handler(fileSystem fs.FS, options *Options) (http.Handler, error) {
6461
return router, nil
6562
}
6663

64+
// FileHandler serves static content, additionally adding immutable
65+
// cache-control headers for Next.js content
66+
func FileHandler(fileSystem fs.FS) func(writer http.ResponseWriter, request *http.Request) {
67+
// Non-HTML files don't have special routing rules, so we can just leverage
68+
// the built-in http.FileServer for it.
69+
fileHandler := http.FileServer(http.FS(fileSystem))
70+
71+
return func(writer http.ResponseWriter, request *http.Request) {
72+
// From the Next.js documentation:
73+
//
74+
// "Caching improves response times and reduces the number
75+
// of requests to external services. Next.js automatically
76+
// adds caching headers to immutable assets served from
77+
// /_next/static including JavaScript, CSS, static images,
78+
// and other media."
79+
//
80+
// See: https://nextjs.org/docs/going-to-production
81+
if strings.HasPrefix(request.URL.Path, "/_next/static/") {
82+
writer.Header().Add("Cache-Control", "public, max-age=31536000, immutable")
83+
}
84+
85+
fileHandler.ServeHTTP(writer, request)
86+
}
87+
}
88+
6789
// registerRoutes recursively traverses the file-system, building routes
6890
// as appropriate for respecting NextJS dynamic rules.
6991
func registerRoutes(rtr chi.Router, fileSystem fs.FS, options Options) error {

site/nextrouter/nextrouter_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,42 @@ func TestNextRouter(t *testing.T) {
376376
require.EqualValues(t, "test-create", body)
377377
})
378378

379+
t.Run("Caching headers for _next resources", func(t *testing.T) {
380+
t.Parallel()
381+
382+
rootFS := fstest.MapFS{
383+
"index.html": &fstest.MapFile{
384+
Data: []byte("test-root"),
385+
},
386+
"_next/static/test.js": &fstest.MapFile{
387+
Data: []byte("test.js cached forever"),
388+
},
389+
"_next/static/chunks/app/test.css": &fstest.MapFile{
390+
Data: []byte("test.css cached forever"),
391+
},
392+
}
393+
394+
router, err := nextrouter.Handler(rootFS, nil)
395+
require.NoError(t, err)
396+
397+
server := httptest.NewServer(router)
398+
t.Cleanup(server.Close)
399+
400+
res, err := request(server, "/index.html")
401+
require.NoError(t, err)
402+
require.NoError(t, res.Body.Close())
403+
404+
require.Equal(t, http.StatusOK, res.StatusCode)
405+
require.Empty(t, res.Header.Get("Cache-Control"))
406+
407+
res, err = request(server, "/_next/static/test.js")
408+
require.NoError(t, err)
409+
require.NoError(t, res.Body.Close())
410+
411+
require.Equal(t, http.StatusOK, res.StatusCode)
412+
require.Equal(t, "public, max-age=31536000, immutable", res.Header.Get("Cache-Control"))
413+
})
414+
379415
t.Run("Injects template parameters", func(t *testing.T) {
380416
t.Parallel()
381417

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy