1
0
Fork 0
mirror of https://github.com/terribleplan/next.js.git synced 2024-01-19 02:48:18 +00:00

Allow etags to be disabled with config option (#3915)

* Allow etags to be disabled with config option

- CR Change: Rename option to generateEtags
- CR Change: Add tests for etag generation
- CR Change: Refactor to use next.config.js
- Update documentation

* Use renderOpts instead of passing nextConfig
This commit is contained in:
Oscar Martinez 2018-03-13 06:18:59 -07:00 committed by Tim Neutkens
parent c5bd36e373
commit eff27bdcfb
6 changed files with 64 additions and 20 deletions

View file

@ -1047,6 +1047,17 @@ module.exports = {
} }
``` ```
#### Disabling etag generation
You can disable etag generation for HTML pages depending on your cache strategy. If no configuration is specified then Next will generate etags for every page.
```js
// next.config.js
module.exports = {
generateEtags: false
}
```
#### Configuring the onDemandEntries #### Configuring the onDemandEntries
Next exposes some options that give you some control over how the server will dispose or keep in memories pages built: Next exposes some options that give you some control over how the server will dispose or keep in memories pages built:

View file

@ -10,6 +10,7 @@ const defaultConfig = {
assetPrefix: '', assetPrefix: '',
configOrigin: 'default', configOrigin: 'default',
useFileSystemPublicRoutes: true, useFileSystemPublicRoutes: true,
generateEtags: true,
pageExtensions: ['jsx', 'js'] // jsx before js because otherwise regex matching will match js first pageExtensions: ['jsx', 'js'] // jsx before js because otherwise regex matching will match js first
} }

View file

@ -45,6 +45,10 @@ export default class Server {
updateNotifier(pkg, 'next') updateNotifier(pkg, 'next')
} }
// Only serverRuntimeConfig needs the default
// publicRuntimeConfig gets it's default in client/index.js
const {serverRuntimeConfig = {}, publicRuntimeConfig, assetPrefix, generateEtags} = this.nextConfig
if (!dev && !fs.existsSync(resolve(dir, this.dist, 'BUILD_ID'))) { if (!dev && !fs.existsSync(resolve(dir, this.dist, 'BUILD_ID'))) {
console.error(`> Could not find a valid build in the '${this.dist}' directory! Try building your app with 'next build' before starting the server.`) console.error(`> Could not find a valid build in the '${this.dist}' directory! Try building your app with 'next build' before starting the server.`)
process.exit(1) process.exit(1)
@ -57,13 +61,10 @@ export default class Server {
dist: this.dist, dist: this.dist,
hotReloader: this.hotReloader, hotReloader: this.hotReloader,
buildId: this.buildId, buildId: this.buildId,
availableChunks: dev ? {} : getAvailableChunks(this.dir, this.dist) availableChunks: dev ? {} : getAvailableChunks(this.dir, this.dist),
generateEtags
} }
// Only serverRuntimeConfig needs the default
// publicRuntimeConfig gets it's default in client/index.js
const {serverRuntimeConfig = {}, publicRuntimeConfig, assetPrefix} = this.nextConfig
// Only the `publicRuntimeConfig` key is exposed to the client side // Only the `publicRuntimeConfig` key is exposed to the client side
// It'll be rendered as part of __NEXT_DATA__ on the client side // It'll be rendered as part of __NEXT_DATA__ on the client side
if (publicRuntimeConfig) { if (publicRuntimeConfig) {

View file

@ -138,9 +138,9 @@ export async function renderScriptError (req, res, page, error) {
res.end('500 - Internal Error') res.end('500 - Internal Error')
} }
export function sendHTML (req, res, html, method, { dev }) { export function sendHTML (req, res, html, method, { dev, generateEtags }) {
if (isResSent(res)) return if (isResSent(res)) return
const etag = generateETag(html) const etag = generateEtags && generateETag(html)
if (fresh(req.headers, { etag })) { if (fresh(req.headers, { etag })) {
res.statusCode = 304 res.statusCode = 304
@ -154,7 +154,10 @@ export function sendHTML (req, res, html, method, { dev }) {
res.setHeader('Cache-Control', 'no-store, must-revalidate') res.setHeader('Cache-Control', 'no-store, must-revalidate')
} }
if (etag) {
res.setHeader('ETag', etag) res.setHeader('ETag', etag)
}
if (!res.getHeader('Content-Type')) { if (!res.getHeader('Content-Type')) {
res.setHeader('Content-Type', 'text/html; charset=utf-8') res.setHeader('Content-Type', 'text/html; charset=utf-8')
} }

View file

@ -2,5 +2,6 @@ module.exports = {
onDemandEntries: { onDemandEntries: {
// Make sure entries are not getting disposed. // Make sure entries are not getting disposed.
maxInactiveAge: 1000 * 60 * 60 maxInactiveAge: 1000 * 60 * 60
} },
generateEtags: process.env.GENERATE_ETAGS === 'true'
} }

View file

@ -7,7 +7,8 @@ import cheerio from 'cheerio'
import { import {
initNextServerScript, initNextServerScript,
killApp, killApp,
renderViaHTTP renderViaHTTP,
fetchViaHTTP
} from 'next-test-utils' } from 'next-test-utils'
import webdriver from 'next-webdriver' import webdriver from 'next-webdriver'
@ -18,18 +19,24 @@ jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000 * 60 * 2
const context = {} const context = {}
describe('Custom Server', () => { const startServer = async (optEnv = {}) => {
beforeAll(async () => {
const scriptPath = join(appDir, 'server.js') const scriptPath = join(appDir, 'server.js')
context.appPort = appPort = await getPort() context.appPort = appPort = await getPort()
const env = clone(process.env) const env = Object.assign(
env.PORT = `${appPort}` {},
clone(process.env),
{ PORT: `${appPort}` },
optEnv
)
server = await initNextServerScript(scriptPath, /Ready on/, env) server = await initNextServerScript(scriptPath, /Ready on/, env)
}) }
describe('Custom Server', () => {
describe('with dynamic assetPrefix', () => {
beforeAll(() => startServer())
afterAll(() => killApp(server)) afterAll(() => killApp(server))
describe('with dynamic assetPrefix', () => {
it('should set the assetPrefix dynamically', async () => { it('should set the assetPrefix dynamically', async () => {
const normalUsage = await renderViaHTTP(appPort, '/asset') const normalUsage = await renderViaHTTP(appPort, '/asset')
expect(normalUsage).not.toMatch(/127\.0\.0\.1/) expect(normalUsage).not.toMatch(/127\.0\.0\.1/)
@ -83,4 +90,24 @@ describe('Custom Server', () => {
browser2.close() browser2.close()
}) })
}) })
describe('with generateEtags enabled', () => {
beforeAll(() => startServer({ GENERATE_ETAGS: 'true' }))
afterAll(() => killApp(server))
it('response includes etag header', async () => {
const response = await fetchViaHTTP(appPort, '/')
expect(response.headers.get('etag')).toBeTruthy()
})
})
describe('with generateEtags disabled', () => {
beforeAll(() => startServer({ GENERATE_ETAGS: 'false' }))
afterAll(() => killApp(server))
it('response does not include etag header', async () => {
const response = await fetchViaHTTP(appPort, '/')
expect(response.headers.get('etag')).toBeNull()
})
})
}) })