mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-11 08:33:53 +00:00
feat(server): timing option for Server-Timing
header (#4800)
This commit is contained in:
parent
a7ba73ed13
commit
b23f5c9b4b
@ -10,6 +10,9 @@ module.exports = {
|
||||
extends: [
|
||||
'@nuxtjs'
|
||||
],
|
||||
"globals": {
|
||||
"BigInt": true
|
||||
},
|
||||
overrides: [{
|
||||
files: [ 'test/fixtures/*/.nuxt*/**' ],
|
||||
rules: {
|
||||
|
@ -9,5 +9,6 @@ export default ({ env = {} } = {}) => ({
|
||||
env.npm_package_config_nuxt_host ||
|
||||
'localhost',
|
||||
socket: env.UNIX_SOCKET ||
|
||||
env.npm_package_config_unix_socket
|
||||
env.npm_package_config_unix_socket,
|
||||
timing: false
|
||||
})
|
||||
|
@ -306,6 +306,7 @@ Object {
|
||||
"https": false,
|
||||
"port": 3000,
|
||||
"socket": undefined,
|
||||
"timing": false,
|
||||
},
|
||||
"serverMiddleware": Array [],
|
||||
"srcDir": "/var/nuxt/test",
|
||||
|
@ -282,6 +282,7 @@ Object {
|
||||
"https": false,
|
||||
"port": 3000,
|
||||
"socket": undefined,
|
||||
"timing": false,
|
||||
},
|
||||
"serverMiddleware": Array [],
|
||||
"srcDir": undefined,
|
||||
@ -605,6 +606,7 @@ Object {
|
||||
"https": false,
|
||||
"port": "3001",
|
||||
"socket": "/var/run/nuxt.sock",
|
||||
"timing": false,
|
||||
},
|
||||
"serverMiddleware": Array [],
|
||||
"srcDir": undefined,
|
||||
|
@ -1,25 +1,17 @@
|
||||
import serverConfig from '../../src/config/server'
|
||||
|
||||
describe('config: server', () => {
|
||||
test('should return default server configurations', () => {
|
||||
expect(serverConfig()).toEqual({
|
||||
https: false,
|
||||
port: 3000,
|
||||
host: 'localhost',
|
||||
socket: undefined
|
||||
})
|
||||
})
|
||||
const serverDefaults = serverConfig()
|
||||
|
||||
describe('config: server', () => {
|
||||
test('should return server configurations with NUXT_* env', () => {
|
||||
const env = {
|
||||
NUXT_PORT: 3001,
|
||||
NUXT_HOST: '127.0.0.1'
|
||||
}
|
||||
expect(serverConfig({ env })).toEqual({
|
||||
https: false,
|
||||
...serverDefaults,
|
||||
port: env.NUXT_PORT,
|
||||
host: env.NUXT_HOST,
|
||||
socket: undefined
|
||||
host: env.NUXT_HOST
|
||||
})
|
||||
})
|
||||
|
||||
@ -30,7 +22,7 @@ describe('config: server', () => {
|
||||
UNIX_SOCKET: '/var/run/env.sock'
|
||||
}
|
||||
expect(serverConfig({ env })).toEqual({
|
||||
https: false,
|
||||
...serverDefaults,
|
||||
port: env.PORT,
|
||||
host: env.HOST,
|
||||
socket: env.UNIX_SOCKET
|
||||
@ -44,7 +36,7 @@ describe('config: server', () => {
|
||||
npm_package_config_unix_socket: '/var/run/env.npm.sock'
|
||||
}
|
||||
expect(serverConfig({ env })).toEqual({
|
||||
https: false,
|
||||
...serverDefaults,
|
||||
port: env.npm_package_config_nuxt_port,
|
||||
host: env.npm_package_config_nuxt_host,
|
||||
socket: env.npm_package_config_unix_socket
|
||||
|
@ -20,6 +20,7 @@
|
||||
"fs-extra": "^7.0.1",
|
||||
"ip": "^1.1.5",
|
||||
"launch-editor-middleware": "^2.2.1",
|
||||
"on-headers": "^1.0.1",
|
||||
"pify": "^4.0.1",
|
||||
"semver": "^5.6.0",
|
||||
"serve-placeholder": "^1.1.0",
|
||||
|
51
packages/server/src/middleware/timing.js
Normal file
51
packages/server/src/middleware/timing.js
Normal file
@ -0,0 +1,51 @@
|
||||
import consola from 'consola'
|
||||
import onHeaders from 'on-headers'
|
||||
import { Timer } from '@nuxt/utils'
|
||||
|
||||
export default options => (req, res, next) => {
|
||||
if (res.timing) {
|
||||
consola.warn('server-timing is already registered.')
|
||||
}
|
||||
res.timing = new ServerTiming()
|
||||
|
||||
if (options && options.total) {
|
||||
res.timing.start('total', 'Nuxt Server Time')
|
||||
}
|
||||
|
||||
onHeaders(res, () => {
|
||||
res.timing.end('total')
|
||||
|
||||
res.setHeader(
|
||||
'Server-Timing',
|
||||
[]
|
||||
.concat(res.getHeader('Server-Timing') || [])
|
||||
.concat(res.timing.headers)
|
||||
.join(', ')
|
||||
)
|
||||
})
|
||||
|
||||
next()
|
||||
}
|
||||
|
||||
class ServerTiming extends Timer {
|
||||
constructor(...args) {
|
||||
super(...args)
|
||||
this.headers = []
|
||||
}
|
||||
|
||||
end(...args) {
|
||||
const time = super.end(...args)
|
||||
this.headers.push(this.formatHeader(time))
|
||||
return time
|
||||
}
|
||||
|
||||
clear() {
|
||||
super.clear()
|
||||
this.headers.length = 0
|
||||
}
|
||||
|
||||
formatHeader(time) {
|
||||
const desc = time.description ? `;desc="${time.description}"` : ''
|
||||
return `${time.name};dur=${time.duration}${desc}`
|
||||
}
|
||||
}
|
@ -12,6 +12,7 @@ import nuxtMiddleware from './middleware/nuxt'
|
||||
import errorMiddleware from './middleware/error'
|
||||
import Listener from './listener'
|
||||
import createModernMiddleware from './middleware/modern'
|
||||
import createTimingMiddleware from './middleware/timing'
|
||||
|
||||
export default class Server {
|
||||
constructor(nuxt) {
|
||||
@ -75,6 +76,10 @@ export default class Server {
|
||||
}
|
||||
}
|
||||
|
||||
if (this.options.server.timing) {
|
||||
this.useMiddleware(createTimingMiddleware(this.options.server.timing))
|
||||
}
|
||||
|
||||
const modernMiddleware = createModernMiddleware({
|
||||
context: this.renderer.context
|
||||
})
|
||||
|
@ -24,3 +24,42 @@ export const timeout = function timeout(fn, ms, msg) {
|
||||
export const waitFor = function waitFor(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms || 0))
|
||||
}
|
||||
export class Timer {
|
||||
constructor() {
|
||||
this._times = new Map()
|
||||
}
|
||||
|
||||
start(name, description) {
|
||||
const time = {
|
||||
name,
|
||||
description,
|
||||
start: this.hrtime()
|
||||
}
|
||||
this._times.set(name, time)
|
||||
return time
|
||||
}
|
||||
|
||||
end(name) {
|
||||
if (this._times.has(name)) {
|
||||
const time = this._times.get(name)
|
||||
time.duration = this.hrtime(time.start)
|
||||
this._times.delete(name)
|
||||
return time
|
||||
}
|
||||
}
|
||||
|
||||
hrtime(start) {
|
||||
const useBigInt = typeof process.hrtime.bigint === 'function'
|
||||
if (start) {
|
||||
const end = useBigInt ? process.hrtime.bigint() : process.hrtime(start)
|
||||
return useBigInt
|
||||
? (end - start) / BigInt(1000000)
|
||||
: (end[0] * 1e3) + (end[1] * 1e-6)
|
||||
}
|
||||
return useBigInt ? process.hrtime.bigint() : process.hrtime()
|
||||
}
|
||||
|
||||
clear() {
|
||||
this._times.clear()
|
||||
}
|
||||
}
|
||||
|
5
test/fixtures/with-config/nuxt.config.js
vendored
5
test/fixtures/with-config/nuxt.config.js
vendored
@ -6,7 +6,10 @@ export default {
|
||||
srcDir: __dirname,
|
||||
server: {
|
||||
port: 8000,
|
||||
host: '0.0.0.0'
|
||||
host: '0.0.0.0',
|
||||
timing: {
|
||||
total: true
|
||||
}
|
||||
},
|
||||
router: {
|
||||
base: '/test/',
|
||||
|
@ -197,6 +197,13 @@ describe('with-config', () => {
|
||||
expect(fakeErrorLog).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
test('/ with Server-Timing header', async () => {
|
||||
const { headers } = await rp(url('/test'), {
|
||||
resolveWithFullResponse: true
|
||||
})
|
||||
expect(headers['server-timing']).toMatch(/total;dur=\d+;desc="Nuxt Server Time"/)
|
||||
})
|
||||
|
||||
// Close server and ask nuxt to stop listening to file changes
|
||||
afterAll(async () => {
|
||||
await nuxt.close()
|
||||
|
@ -7771,7 +7771,7 @@ on-finished@~2.3.0:
|
||||
dependencies:
|
||||
ee-first "1.1.1"
|
||||
|
||||
on-headers@~1.0.1:
|
||||
on-headers@^1.0.1, on-headers@~1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz#928f5d0f470d49342651ea6794b0857c100693f7"
|
||||
integrity sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=
|
||||
|
Loading…
Reference in New Issue
Block a user