Skip to content
This repository has been archived by the owner on Apr 6, 2023. It is now read-only.

fix(vite): include importer in vite-node error stack #7607

Merged
merged 1 commit into from
Sep 19, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions packages/vite/src/runtime/vite-node.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,23 @@ export default async (ssrContext) => {
}

function createRunner () {
const _importers = new Map()
return new ViteNodeRunner({
root: viteNodeOptions.root, // Equals to Nuxt `srcDir`
base: viteNodeOptions.base,
resolveId (id, importer) { _importers.set(id, importer) },
async fetchModule (id) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@antfu is it possible for vite-node to directly give importer to the fetchModule? It could be useful to format errors better.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is that a module could be imported by multiple importers and vite-node caches them to reuse the existing one. That means if we could have the importer it could only be the first one hit the module and can be changed in different requests.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. Indeed makes sense. But how do you think about this solution for Nuxt to hint about error? I suppose first importer triggers the error this way.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we could update the logging message to be something like (first imported by x) to keep it accurate?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

having imported by is also accurate (it could be, also imported by y but as result of being imported by x is now being failed). Similar to other stack traces if a util is used by two functions, first function calling it shows in stack trace.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will see what I can do on the vite-node side

// TODO: fix in vite-node
id = id.replace(/\/\//g, '/')
const importer = _importers.get(id)
_importers.delete(id)
id = id.replace(/\/\//g, '/') // TODO: fix in vite-node
return await viteNodeFetch('/module/' + encodeURI(id)).catch((err) => {
const errorData = err?.data?.data
if (!errorData) {
throw err
}
let _err
try {
const { message, stack } = formatViteError(errorData)
const { message, stack } = formatViteError(errorData, id, importer)
_err = createError({
statusMessage: 'Vite Error',
message,
Expand All @@ -64,11 +67,11 @@ function createRunner () {
})
}

function formatViteError (errorData) {
function formatViteError (errorData, id, importer) {
const errorCode = errorData.name || errorData.reasonCode || errorData.code
const frame = errorData.frame || errorData.source || errorData.pluginCode

const getLocId = (locObj = {}) => locObj.file || locObj.id || locObj.url || ''
const getLocId = (locObj = {}) => locObj.file || locObj.id || locObj.url || id || ''
const getLocPos = (locObj = {}) => locObj.line ? `${locObj.line}:${locObj.column || 0}` : ''
const locId = getLocId(errorData.loc) || getLocId(errorData.location) || getLocId(errorData.input) || getLocId(errorData)
const locPos = getLocPos(errorData.loc) || getLocPos(errorData.location) || getLocPos(errorData.input) || getLocPos(errorData)
Expand All @@ -85,7 +88,7 @@ function formatViteError (errorData) {

const stack = [
message,
'at ' + loc,
`at ${loc} ${importer ? `(imported from ${importer})` : ''}`,
errorData.stack
].filter(Boolean).join('\n')

Expand Down