-
-
Notifications
You must be signed in to change notification settings - Fork 382
feat: enable cacheImmutable by default #2247
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
4e0bb32
4d25a22
0f5c4f6
d66f6b8
a1d4cb9
548a48d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -571,9 +571,13 @@ function wrapper(context) { | |
| } | ||
|
|
||
| if (!getResponseHeader(res, "Cache-Control")) { | ||
| // TODO enable the `cacheImmutable` by default for the next major release | ||
| const hasCacheImmutable = | ||
| context.options.cacheImmutable === undefined | ||
| ? true | ||
| : context.options.cacheImmutable; | ||
|
|
||
| const cacheControl = | ||
| context.options.cacheImmutable && extra.immutable | ||
| hasCacheImmutable && extra.immutable | ||
| ? { immutable: true } | ||
| : context.options.cacheControl; | ||
|
|
||
|
|
@@ -582,12 +586,20 @@ function wrapper(context) { | |
|
|
||
| if (typeof cacheControl === "boolean") { | ||
| cacheControlValue = "public, max-age=31536000"; | ||
|
|
||
| if (hasCacheImmutable) { | ||
| cacheControlValue += ", immutable"; | ||
| } | ||
| } else if (typeof cacheControl === "number") { | ||
| const maxAge = Math.floor( | ||
| Math.min(Math.max(0, cacheControl), MAX_MAX_AGE) / 1000, | ||
| ); | ||
|
|
||
| cacheControlValue = `public, max-age=${maxAge}`; | ||
|
|
||
| if (hasCacheImmutable) { | ||
| cacheControlValue += ", immutable"; | ||
| } | ||
| } else if (typeof cacheControl === "string") { | ||
| cacheControlValue = cacheControl; | ||
| } else { | ||
|
|
@@ -600,7 +612,7 @@ function wrapper(context) { | |
|
|
||
| cacheControlValue = `public, max-age=${maxAge}`; | ||
|
|
||
| if (cacheControl.immutable) { | ||
| if (cacheControl.immutable !== false && hasCacheImmutable) { | ||
| cacheControlValue += ", immutable"; | ||
| } | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we refactor this place? Convert boolean/number/string to object value to avoid logic duplication?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5943,7 +5943,7 @@ describe.each([ | |
| expect(response.statusCode).toBe(200); | ||
| expect(response.headers["cache-control"]).toBeDefined(); | ||
| expect(response.headers["cache-control"]).toBe( | ||
| "public, max-age=31536000", | ||
| "public, max-age=31536000, immutable", | ||
| ); | ||
| }); | ||
| }); | ||
|
|
@@ -5969,7 +5969,9 @@ describe.each([ | |
|
|
||
| expect(response.statusCode).toBe(200); | ||
| expect(response.headers["cache-control"]).toBeDefined(); | ||
| expect(response.headers["cache-control"]).toBe("public, max-age=100"); | ||
| expect(response.headers["cache-control"]).toBe( | ||
| "public, max-age=100, immutable", | ||
| ); | ||
| }); | ||
| }); | ||
|
|
||
|
|
@@ -6086,7 +6088,9 @@ describe.each([ | |
|
|
||
| expect(response.statusCode).toBe(200); | ||
| expect(response.headers["cache-control"]).toBeDefined(); | ||
| expect(response.headers["cache-control"]).toBe("public, max-age=100"); | ||
| expect(response.headers["cache-control"]).toBe( | ||
| "public, max-age=100, immutable", | ||
| ); | ||
| }); | ||
| }); | ||
|
|
||
|
|
@@ -6114,7 +6118,7 @@ describe.each([ | |
| expect(response.statusCode).toBe(200); | ||
| expect(response.headers["cache-control"]).toBeDefined(); | ||
| expect(response.headers["cache-control"]).toBe( | ||
| "public, max-age=31536000", | ||
| "public, max-age=31536000, immutable", | ||
| ); | ||
| }); | ||
| }); | ||
|
|
@@ -6129,7 +6133,6 @@ describe.each([ | |
| name, | ||
| framework, | ||
| compiler, | ||
| { cacheImmutable: true }, | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @bjohansebas Why it was changed? This is a serous breaking change, by default we should cache only Please avoid merge without approve
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It was changed to check how it behaves when that option doesn’t exist, and that’s why I added tests below to verify how it behaves when cacheImmutable is explicitly set to false
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The only breaking change is that now, if an asset is immutable, it will add that header by default. Otherwise, it behaves as before. In the first commit there was an error, but after reviewing the code I realized it was wrong, which is why I added those two new commits that fixed the issue (0f5c4f6, d66f6b8) where the header was being added even when the asset was not immutable yet. |
||
| ); | ||
| }); | ||
|
|
||
|
|
@@ -6221,7 +6224,7 @@ describe.each([ | |
| expect(response.statusCode).toBe(200); | ||
| expect(response.headers["cache-control"]).toBeDefined(); | ||
| expect(response.headers["cache-control"]).toBe( | ||
| "public, max-age=1000", | ||
| "public, max-age=1000, immutable", | ||
| ); | ||
| }); | ||
|
|
||
|
|
@@ -6235,6 +6238,290 @@ describe.each([ | |
| ); | ||
| }); | ||
| }); | ||
|
|
||
| describe("should not generate `Cache-Control` header for immutable assets when cacheImmutable is false", () => { | ||
| beforeEach(async () => { | ||
| const compiler = getCompiler({ | ||
| ...webpackConfigImmutable, | ||
| output: { | ||
| path: path.resolve(__dirname, "./outputs/basic"), | ||
| }, | ||
| }); | ||
|
|
||
| [server, req, instance] = await frameworkFactory( | ||
| name, | ||
| framework, | ||
| compiler, | ||
| { cacheImmutable: false }, | ||
| ); | ||
| }); | ||
|
|
||
| afterEach(async () => { | ||
| await close(server, instance); | ||
| }); | ||
|
|
||
| it('should return the "200" code for the "GET" request to the bundle file and don\'t generate `Cache-Control` header', async () => { | ||
| const response = await req.get("/main.js"); | ||
|
|
||
| expect(response.statusCode).toBe(200); | ||
| expect(response.headers["cache-control"]).toBeUndefined(); | ||
| }); | ||
|
|
||
| it('should return the "200" code for the "GET" request to the immutable asset and don\'t generate `Cache-Control` header', async () => { | ||
| const response = await req.get("/6076fc274f403ebb2d09.svg"); | ||
|
|
||
| expect(response.statusCode).toBe(200); | ||
| expect(response.headers["cache-control"]).toBeUndefined(); | ||
| }); | ||
| }); | ||
|
|
||
| describe("should use cacheControl option when cacheImmutable is false even for immutable assets", () => { | ||
| beforeEach(async () => { | ||
| const compiler = getCompiler({ | ||
| ...webpackConfigImmutable, | ||
| output: { | ||
| path: path.resolve(__dirname, "./outputs/basic"), | ||
| }, | ||
| }); | ||
|
|
||
| [server, req, instance] = await frameworkFactory( | ||
| name, | ||
| framework, | ||
| compiler, | ||
| { cacheImmutable: false, cacheControl: 1000000 }, | ||
| ); | ||
| }); | ||
|
|
||
| afterEach(async () => { | ||
| await close(server, instance); | ||
| }); | ||
|
|
||
| it('should return the "200" code for the "GET" request to the bundle file and generate `Cache-Control` header from cacheControl option', async () => { | ||
| const response = await req.get("/main.js"); | ||
|
|
||
| expect(response.statusCode).toBe(200); | ||
| expect(response.headers["cache-control"]).toBeDefined(); | ||
| expect(response.headers["cache-control"]).toBe( | ||
| "public, max-age=1000", | ||
| ); | ||
| }); | ||
|
|
||
| it('should return the "200" code for the "GET" request to the immutable asset and generate `Cache-Control` header from cacheControl option (not immutable)', async () => { | ||
| const response = await req.get("/6076fc274f403ebb2d09.svg"); | ||
|
|
||
| expect(response.statusCode).toBe(200); | ||
| expect(response.headers["cache-control"]).toBeDefined(); | ||
| expect(response.headers["cache-control"]).toBe( | ||
| "public, max-age=1000", | ||
| ); | ||
| }); | ||
| }); | ||
|
|
||
| describe("should use cacheControl string option when cacheImmutable is false", () => { | ||
| beforeEach(async () => { | ||
| const compiler = getCompiler({ | ||
| ...webpackConfigImmutable, | ||
| output: { | ||
| path: path.resolve(__dirname, "./outputs/basic"), | ||
| }, | ||
| }); | ||
|
|
||
| [server, req, instance] = await frameworkFactory( | ||
| name, | ||
| framework, | ||
| compiler, | ||
| { cacheImmutable: false, cacheControl: "max-age=500" }, | ||
| ); | ||
| }); | ||
|
|
||
| afterEach(async () => { | ||
| await close(server, instance); | ||
| }); | ||
|
|
||
| it('should return the "200" code for the "GET" request to the bundle file and generate `Cache-Control` header from cacheControl string option without immutable', async () => { | ||
| const response = await req.get("/main.js"); | ||
|
|
||
| expect(response.statusCode).toBe(200); | ||
| expect(response.headers["cache-control"]).toBeDefined(); | ||
| expect(response.headers["cache-control"]).toBe("max-age=500"); | ||
| }); | ||
|
|
||
| it('should return the "200" code for the "GET" request to the immutable asset and generate `Cache-Control` header from cacheControl string option without immutable', async () => { | ||
| const response = await req.get("/6076fc274f403ebb2d09.svg"); | ||
|
|
||
| expect(response.statusCode).toBe(200); | ||
| expect(response.headers["cache-control"]).toBeDefined(); | ||
| expect(response.headers["cache-control"]).toBe("max-age=500"); | ||
| }); | ||
| }); | ||
|
|
||
| describe("should use cacheControl object option when cacheImmutable is false", () => { | ||
| beforeEach(async () => { | ||
| const compiler = getCompiler({ | ||
| ...webpackConfigImmutable, | ||
| output: { | ||
| path: path.resolve(__dirname, "./outputs/basic"), | ||
| }, | ||
| }); | ||
|
|
||
| [server, req, instance] = await frameworkFactory( | ||
| name, | ||
| framework, | ||
| compiler, | ||
| { cacheImmutable: false, cacheControl: { maxAge: 2000000 } }, | ||
| ); | ||
| }); | ||
|
|
||
| afterEach(async () => { | ||
| await close(server, instance); | ||
| }); | ||
|
|
||
| it('should return the "200" code for the "GET" request to the bundle file and generate `Cache-Control` header from cacheControl object option without immutable', async () => { | ||
| const response = await req.get("/main.js"); | ||
|
|
||
| expect(response.statusCode).toBe(200); | ||
| expect(response.headers["cache-control"]).toBeDefined(); | ||
| expect(response.headers["cache-control"]).toBe( | ||
| "public, max-age=2000", | ||
| ); | ||
| }); | ||
|
|
||
| it('should return the "200" code for the "GET" request to the immutable asset and generate `Cache-Control` header from cacheControl object option without immutable', async () => { | ||
| const response = await req.get("/6076fc274f403ebb2d09.svg"); | ||
|
|
||
| expect(response.statusCode).toBe(200); | ||
| expect(response.headers["cache-control"]).toBeDefined(); | ||
| expect(response.headers["cache-control"]).toBe( | ||
| "public, max-age=2000", | ||
| ); | ||
| }); | ||
| }); | ||
|
|
||
| describe("should use cacheControl object option with explicit immutable false", () => { | ||
| beforeEach(async () => { | ||
| const compiler = getCompiler({ | ||
| ...webpackConfigImmutable, | ||
| output: { | ||
| path: path.resolve(__dirname, "./outputs/basic"), | ||
| }, | ||
| }); | ||
|
|
||
| [server, req, instance] = await frameworkFactory( | ||
| name, | ||
| framework, | ||
| compiler, | ||
| { cacheControl: { maxAge: 3000000, immutable: false } }, | ||
| ); | ||
| }); | ||
|
|
||
| afterEach(async () => { | ||
| await close(server, instance); | ||
| }); | ||
|
|
||
| it('should return the "200" code for the "GET" request to the bundle file and generate `Cache-Control` header without immutable when explicitly set to false', async () => { | ||
| const response = await req.get("/main.js"); | ||
|
|
||
| expect(response.statusCode).toBe(200); | ||
| expect(response.headers["cache-control"]).toBeDefined(); | ||
| expect(response.headers["cache-control"]).toBe( | ||
| "public, max-age=3000", | ||
| ); | ||
| }); | ||
|
|
||
| it('should return the "200" code for the "GET" request to the immutable asset and generate `Cache-Control` header without immutable when explicitly set to false', async () => { | ||
| const response = await req.get("/6076fc274f403ebb2d09.svg"); | ||
|
|
||
| expect(response.statusCode).toBe(200); | ||
| expect(response.headers["cache-control"]).toBeDefined(); | ||
| expect(response.headers["cache-control"]).toBe( | ||
| "public, max-age=31536000, immutable", | ||
| ); | ||
| }); | ||
| }); | ||
|
|
||
| describe("should use cacheControl boolean option when cacheImmutable is false", () => { | ||
| beforeEach(async () => { | ||
| const compiler = getCompiler({ | ||
| ...webpackConfigImmutable, | ||
| output: { | ||
| path: path.resolve(__dirname, "./outputs/basic"), | ||
| }, | ||
| }); | ||
|
|
||
| [server, req, instance] = await frameworkFactory( | ||
| name, | ||
| framework, | ||
| compiler, | ||
| { cacheImmutable: false, cacheControl: true }, | ||
| ); | ||
| }); | ||
|
|
||
| afterEach(async () => { | ||
| await close(server, instance); | ||
| }); | ||
|
|
||
| it('should return the "200" code for the "GET" request to the bundle file and generate `Cache-Control` header from cacheControl boolean option without immutable', async () => { | ||
| const response = await req.get("/main.js"); | ||
|
|
||
| expect(response.statusCode).toBe(200); | ||
| expect(response.headers["cache-control"]).toBeDefined(); | ||
| expect(response.headers["cache-control"]).toBe( | ||
| "public, max-age=31536000", | ||
| ); | ||
| }); | ||
|
|
||
| it('should return the "200" code for the "GET" request to the immutable asset and generate `Cache-Control` header from cacheControl boolean option without immutable', async () => { | ||
| const response = await req.get("/6076fc274f403ebb2d09.svg"); | ||
|
|
||
| expect(response.statusCode).toBe(200); | ||
| expect(response.headers["cache-control"]).toBeDefined(); | ||
| expect(response.headers["cache-control"]).toBe( | ||
| "public, max-age=31536000", | ||
| ); | ||
| }); | ||
| }); | ||
|
|
||
| describe("should use cacheControl number option when cacheImmutable is false without immutable", () => { | ||
| beforeEach(async () => { | ||
| const compiler = getCompiler({ | ||
| ...webpackConfigImmutable, | ||
| output: { | ||
| path: path.resolve(__dirname, "./outputs/basic"), | ||
| }, | ||
| }); | ||
|
|
||
| [server, req, instance] = await frameworkFactory( | ||
| name, | ||
| framework, | ||
| compiler, | ||
| { cacheImmutable: false, cacheControl: 5000000 }, | ||
| ); | ||
| }); | ||
|
|
||
| afterEach(async () => { | ||
| await close(server, instance); | ||
| }); | ||
|
|
||
| it('should return the "200" code for the "GET" request to the bundle file and generate `Cache-Control` header from cacheControl number option without immutable', async () => { | ||
| const response = await req.get("/main.js"); | ||
|
|
||
| expect(response.statusCode).toBe(200); | ||
| expect(response.headers["cache-control"]).toBeDefined(); | ||
| expect(response.headers["cache-control"]).toBe( | ||
| "public, max-age=5000", | ||
| ); | ||
| }); | ||
|
|
||
| it('should return the "200" code for the "GET" request to the immutable asset and generate `Cache-Control` header from cacheControl number option without immutable', async () => { | ||
| const response = await req.get("/6076fc274f403ebb2d09.svg"); | ||
|
|
||
| expect(response.statusCode).toBe(200); | ||
| expect(response.headers["cache-control"]).toBeDefined(); | ||
| expect(response.headers["cache-control"]).toBe( | ||
| "public, max-age=5000", | ||
| ); | ||
| }); | ||
| }); | ||
| }); | ||
| }); | ||
| }); | ||
Uh oh!
There was an error while loading. Please reload this page.