mirror of
https://github.com/nuxt/nuxt.git
synced 2025-01-31 07:40:33 +00:00
refactor(nuxt): use errx
to handle dev log traces (#28027)
This commit is contained in:
parent
11264adda7
commit
1843ffa328
@ -78,6 +78,7 @@
|
|||||||
"defu": "^6.1.4",
|
"defu": "^6.1.4",
|
||||||
"destr": "^2.0.3",
|
"destr": "^2.0.3",
|
||||||
"devalue": "^5.0.0",
|
"devalue": "^5.0.0",
|
||||||
|
"errx": "^0.1.0",
|
||||||
"esbuild": "^0.23.0",
|
"esbuild": "^0.23.0",
|
||||||
"escape-string-regexp": "^5.0.0",
|
"escape-string-regexp": "^5.0.0",
|
||||||
"estree-walker": "^3.0.3",
|
"estree-walker": "^3.0.3",
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { createConsola } from 'consola'
|
import { createConsola } from 'consola'
|
||||||
import type { LogObject } from 'consola'
|
import type { LogObject } from 'consola'
|
||||||
import { parse } from 'devalue'
|
import { parse } from 'devalue'
|
||||||
|
import type { ParsedTrace } from 'errx'
|
||||||
|
|
||||||
import { h } from 'vue'
|
import { h } from 'vue'
|
||||||
import { defineNuxtPlugin } from '../nuxt'
|
import { defineNuxtPlugin } from '../nuxt'
|
||||||
@ -45,15 +46,24 @@ export default defineNuxtPlugin(async (nuxtApp) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
function normalizeFilenames (stack?: string) {
|
function normalizeFilenames (stack?: ParsedTrace[]) {
|
||||||
stack = stack?.split('\n')[0] || ''
|
if (!stack) {
|
||||||
stack = stack.replace(`${devRootDir}/`, '')
|
return ''
|
||||||
stack = stack.replace(/:\d+:\d+\)?$/, '')
|
}
|
||||||
return stack
|
let message = ''
|
||||||
|
for (const item of stack) {
|
||||||
|
const source = item.source.replace(`${devRootDir}/`, '')
|
||||||
|
if (item.function) {
|
||||||
|
message += ` at ${item.function} (${source})\n`
|
||||||
|
} else {
|
||||||
|
message += ` at ${source}\n`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return message
|
||||||
}
|
}
|
||||||
|
|
||||||
function normalizeServerLog (log: LogObject) {
|
function normalizeServerLog (log: LogObject) {
|
||||||
log.additional = normalizeFilenames(log.stack as string)
|
log.additional = normalizeFilenames(log.stack as ParsedTrace[])
|
||||||
log.tag = 'ssr'
|
log.tag = 'ssr'
|
||||||
delete log.stack
|
delete log.stack
|
||||||
return log
|
return log
|
||||||
|
@ -5,6 +5,8 @@ import { stringify } from 'devalue'
|
|||||||
import type { H3Event } from 'h3'
|
import type { H3Event } from 'h3'
|
||||||
import { withTrailingSlash } from 'ufo'
|
import { withTrailingSlash } from 'ufo'
|
||||||
import { getContext } from 'unctx'
|
import { getContext } from 'unctx'
|
||||||
|
import { captureRawStackTrace, parseRawStackTrace } from 'errx'
|
||||||
|
import type { ParsedTrace } from 'errx'
|
||||||
|
|
||||||
import { isVNode } from 'vue'
|
import { isVNode } from 'vue'
|
||||||
import type { NitroApp } from '#internal/nitro/app'
|
import type { NitroApp } from '#internal/nitro/app'
|
||||||
@ -34,15 +36,28 @@ export default (nitroApp: NitroApp) => {
|
|||||||
const ctx = asyncContext.tryUse()
|
const ctx = asyncContext.tryUse()
|
||||||
if (!ctx) { return }
|
if (!ctx) { return }
|
||||||
|
|
||||||
const stack = getStack()
|
const rawStack = captureRawStackTrace()
|
||||||
if (stack.includes('runtime/vite-node.mjs')) { return }
|
if (!rawStack || rawStack.includes('runtime/vite-node.mjs')) { return }
|
||||||
|
|
||||||
|
const trace: ParsedTrace[] = []
|
||||||
|
let filename = ''
|
||||||
|
for (const entry of parseRawStackTrace(rawStack)) {
|
||||||
|
if (entry.source === import.meta.url) { continue }
|
||||||
|
if (EXCLUDE_TRACE_RE.test(entry.source)) { continue }
|
||||||
|
|
||||||
|
filename ||= entry.source.replace(withTrailingSlash(rootDir), '')
|
||||||
|
trace.push({
|
||||||
|
...entry,
|
||||||
|
source: entry.source.startsWith('file://') ? entry.source.replace('file://', '') : entry.source,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const log = {
|
const log = {
|
||||||
..._log,
|
..._log,
|
||||||
// Pass along filename to allow the client to display more info about where log comes from
|
// Pass along filename to allow the client to display more info about where log comes from
|
||||||
filename: extractFilenameFromStack(stack),
|
filename,
|
||||||
// Clean up file names in stack trace
|
// Clean up file names in stack trace
|
||||||
stack: normalizeFilenames(stack),
|
stack: trace,
|
||||||
}
|
}
|
||||||
|
|
||||||
// retain log to be include in the next render
|
// retain log to be include in the next render
|
||||||
@ -68,24 +83,7 @@ export default (nitroApp: NitroApp) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const EXCLUDE_TRACE_RE = /^.*at.*(\/node_modules\/(.*\/)?(nuxt|nuxt-nightly|nuxt-edge|nuxt3|consola|@vue)\/.*|core\/runtime\/nitro.*)$\n?/gm
|
const EXCLUDE_TRACE_RE = /\/node_modules\/(?:.*\/)?(?:nuxt|nuxt-nightly|nuxt-edge|nuxt3|consola|@vue)\/|core\/runtime\/nitro/
|
||||||
function getStack () {
|
|
||||||
// Pass along stack traces if needed (for error and warns)
|
|
||||||
// eslint-disable-next-line unicorn/error-message
|
|
||||||
const stack = new Error()
|
|
||||||
Error.captureStackTrace(stack)
|
|
||||||
return stack.stack?.replace(EXCLUDE_TRACE_RE, '').replace(/^Error.*\n/, '') || ''
|
|
||||||
}
|
|
||||||
|
|
||||||
const FILENAME_RE = /at[^(]*\(([^:)]+)[):]/
|
|
||||||
const FILENAME_RE_GLOBAL = /at[^(]*\(([^)]+)\)/g
|
|
||||||
function extractFilenameFromStack (stacktrace: string) {
|
|
||||||
return stacktrace.match(FILENAME_RE)?.[1].replace(withTrailingSlash(rootDir), '')
|
|
||||||
}
|
|
||||||
function normalizeFilenames (stacktrace: string) {
|
|
||||||
// remove line numbers and file: protocol - TODO: sourcemap support for line numbers
|
|
||||||
return stacktrace.replace(FILENAME_RE_GLOBAL, (match, filename) => match.replace(filename, filename.replace('file:///', '/').replace(/:.*$/, '')))
|
|
||||||
}
|
|
||||||
|
|
||||||
function onConsoleLog (callback: (log: LogObject) => void) {
|
function onConsoleLog (callback: (log: LogObject) => void) {
|
||||||
consola.addReporter({
|
consola.addReporter({
|
||||||
|
@ -312,6 +312,9 @@ importers:
|
|||||||
devalue:
|
devalue:
|
||||||
specifier: ^5.0.0
|
specifier: ^5.0.0
|
||||||
version: 5.0.0
|
version: 5.0.0
|
||||||
|
errx:
|
||||||
|
specifier: ^0.1.0
|
||||||
|
version: 0.1.0
|
||||||
esbuild:
|
esbuild:
|
||||||
specifier: ^0.23.0
|
specifier: ^0.23.0
|
||||||
version: 0.23.0
|
version: 0.23.0
|
||||||
@ -3771,7 +3774,7 @@ packages:
|
|||||||
resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==}
|
resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==}
|
||||||
engines: {node: '>=14'}
|
engines: {node: '>=14'}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
typescript: 5.5.3
|
typescript: '>=4.9.5'
|
||||||
peerDependenciesMeta:
|
peerDependenciesMeta:
|
||||||
typescript:
|
typescript:
|
||||||
optional: true
|
optional: true
|
||||||
@ -3780,7 +3783,7 @@ packages:
|
|||||||
resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==}
|
resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==}
|
||||||
engines: {node: '>=14'}
|
engines: {node: '>=14'}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
typescript: 5.5.3
|
typescript: '>=4.9.5'
|
||||||
peerDependenciesMeta:
|
peerDependenciesMeta:
|
||||||
typescript:
|
typescript:
|
||||||
optional: true
|
optional: true
|
||||||
@ -4169,6 +4172,9 @@ packages:
|
|||||||
error-stack-parser@2.1.4:
|
error-stack-parser@2.1.4:
|
||||||
resolution: {integrity: sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==}
|
resolution: {integrity: sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==}
|
||||||
|
|
||||||
|
errx@0.1.0:
|
||||||
|
resolution: {integrity: sha512-fZmsRiDNv07K6s2KkKFTiD2aIvECa7++PKyD5NC32tpRw46qZA3sOz+aM+/V9V0GDHxVTKLziveV4JhzBHDp9Q==}
|
||||||
|
|
||||||
es-define-property@1.0.0:
|
es-define-property@1.0.0:
|
||||||
resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==}
|
resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
@ -11021,6 +11027,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
stackframe: 1.3.4
|
stackframe: 1.3.4
|
||||||
|
|
||||||
|
errx@0.1.0: {}
|
||||||
|
|
||||||
es-define-property@1.0.0:
|
es-define-property@1.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
get-intrinsic: 1.2.4
|
get-intrinsic: 1.2.4
|
||||||
|
Loading…
Reference in New Issue
Block a user