-
-
Notifications
You must be signed in to change notification settings - Fork 33.7k
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
Generate distinct paths for supporting .vue files in sourcemaps #11023
Comments
This happens in vue-loader, right now I don’t have bandwidth to take it but I can guide if someone is interested. |
I could probably find some time to help out. Code pointers or guidance would be appreciated 🙂 |
This is turning out to be a little more tricky than I thought. Convincing webpack to resolve paths that don't actually exist on the filesystem is difficult; I've made some headway with the virtual-module-webpack-plugin, though it's somewhat dangerous and there's more work to do to have imports from adjusted modules resolve correctly, I'm not really happy with this solution. Maybe there's a way to tweak change the locations in the sourcemaps for these files without needing to ask Webpack to treat them as entirely different disk files. I've pushed some ugly scratch work to https://github.com/connor4312/vue-loader |
> Observed + tested with Vue CLI 3 and 4 Vue does two weird things: 1. For each .vue file, they flatten directory structure and only output `webpack:///foo.vue`, for instance. 2. They have generated code in the sourcemaps, which do things like create CSS and DOM. Ironically, these files _are_ structured correctly (e.g. `webpack:///component/foo.vue`) but we don't want to break in them. This PR introduces some special handling those. Since the directory structure needs to be restored, that entails we have to do some kind of re-mapping back to files on disk. I've made the search classes we use for breakpoint prediction reusable for this: the first time we get a Vue file that needs remapping, we'll scan the workspace and create the appropriate mapping. I have added two regexes that, as precisely as I can, target the build outputs from the Vue CLI to trigger this remapping when necessary, and to ignore the nested generated Vue files. Fixes #239 Refs vuejs/vue#11023
In microsoft/vscode-js-debug@2f3c93a I introduced a heuristic that seems to work very well for plain Vue with JS files, where the path is different (as in the screenshot above). However, with E.g., only one of these is the right one: Without doing some kind of source code analysis, which is complex and fragile, I can't deterministically tell which one is the 'right' script to map back to the file. |
Would be neat to see this fixed as well. It's difficult to know which one is correct even as a human looking at Chrome Devtools 🤷 |
@znck let me know what you think a good solution is. We've gotten continued reports of people running into this with VS Code 🙂 |
Looking forward to the fix |
It's been almost 10 months with no indication of it being fixed... |
@znck I would appreciate your input here. This continues to be a pain point for Vue users on VS Code. (most recently in microsoft/vscode-js-debug#754) |
It is quite tricky to make source maps and hot reload work simultaneously. I understand it's a huge pain point and I'll revisit it (hopefully coming weekend). |
Awesome, let me know if I can help with anything |
@znck @connor4312 Any movement on this issue? I can provide a project in early days that you can debug against |
I've found a workaround which is to provide a custom function to webpack's The following is only tested with output: {
devtoolModuleFilenameTemplate: info => {
if (info.allLoaders === '') {
// when allLoaders is an empty string the file is the original source
// file and will be prefixed with src:// to provide separation from
// modules transpiled via webpack
const filenameParts = ['src://']
if (info.namespace) {
filenameParts.push(info.namespace + '/')
}
filenameParts.push(info.resourcePath.replace(/^\.\//, ''))
return filenameParts.join('')
} else {
// otherwise we have a webpack module
const filenameParts = ['webpack://']
if (info.namespace) {
filenameParts.push(info.namespace + '/')
}
filenameParts.push(info.resourcePath.replace(/^\.\//, ''))
const isVueScript = info.resourcePath.match(/\.vue$/) &&
info.query.match(/\btype=script\b/) &&
!info.allLoaders.match(/\bts-loader\b/)
if (!isVueScript) {
filenameParts.push('?' + info.hash)
}
return filenameParts.join('')
}
},
} This assumes that a Additionally, for const CompilerSfc = require('@vue/compiler-sfc')
const parse = CompilerSfc.parse
CompilerSfc.parse = (source, options) => {
return parse(source, Object.assign({ pad: true }, options))
} I explain the reasoning behind the latter in a bit more detail in vuejs/vue-cli#2897 (comment). With those 2 changes, I'm able to set breakpoints in vscode and have execution pause at the correct place, including in async functions and timer callbacks, e.g. I've created a minimal ts + vue 3 project to test with: https://github.com/andrewmackrodt/vue3-ide-breakpoint-test |
@andrewmackrodt Thank you! For anyone using vscode's debugger with this solution, you should also remember that to update the sourceMapPathOverrides in their launch config correspondingly. "sourceMapPathOverrides": {
"webpack://src/*": "${webRoot}/src/*",
"src://src/*": "${webRoot}/src/*"
} |
@znck let me know what you think a good solution is. We've gotten continued reports of people running into this with VS Code and I remain more than happy to help get this fixed 🙂 |
Beware that this code const CompilerSfc = require('@vue/compiler-sfc')
const parse = CompilerSfc.parse
CompilerSfc.parse = (source, options) => {
return parse(source, Object.assign({ pad: true }, options))
} leads to huge bugs with latest versions of vue-loader (currently |
Well, spend 4 hours trying to resolve this vue-sfc-debug-typescript issue. Finally only this helped #11023 (comment)
@andrewmackrodt you are genius, respect and many thanks for work done! |
Thanks to everybody here, especially @andrewmackrodt -- I owe you a beer (or beverage of your choice). Your Just a few notes to help anybody else in my position. I'm working on a containerized project with Vue 2, manually configured (i.e. without vue-cli), using docker-compose and HMR. Also:
We have one repo, with the frontend in a subdirectory of the project root, and a
When generating pathnames in the source map, vue-loader uses the package name (I think) at the root. After including the
As a result, my path override is just:
I recommend right-clicking on a filename in Chrome devtools (in the Sources tab's directory tree) and using Copy link address to see what you need for your sourceMapPathOverrides. Without this information I would have been lost. Also, my vscode debug config is setup to attach to an already running chrome, launched from the command line with the
One final note: My webpack |
Hello All, |
Connor Peet indicated I was experiencing this issue when he researched why I cannot set breakpoints in VS Code for my Vue3 app. [https://github.com/microsoft/vscode-js-debug/issues/1799] I just wanted to sound off here and say I spent many hours over several days trying to get breakpoint setting to work in VS Code. It gave me a pretty negative impression of the IDE. I'm glad I stuck with it and submitted the issue to you guys and learned that VS Code did indeed have an issue. I subsequently have migrated my project to Vite and as a result, no longer have the breakpoint setting issue. Apparently Vue3 with Vite does not suffer from the same issue. It took a few hours to migrate my project but it was worth it. Vite is fast! John |
What problem does this feature solve?
Hello Vue 👋
I'm working on our new JavaScript debugger for VS Code, and ran into some problems when trying out Vue. The default vue-cli setup creates several supporting .vue scripts. For instance, open the Chrome devtools and ctrl p for "App.vue" in a new project. The top entry is the correct Vue file, the others aren't.
From the VS Code perspective, the user might ask us to set a breakpoint in a Vue file. We know which file the breakpoint is attached to on disk, and we need to figure out which loaded file that breakpoint gets mapped to. However, because all these paths are quite similar and all (in the context of a generic web app) possibly the file we want, we end up putting the breakpoint in the wrong file and breaking in the incorrect place. And often the supporting scripts evaluate before the 'real' script does, so we can't, for example, wait and pick the best match from the possible candidates.
What does the proposed API look like?
The simplest solution would be to prefix the supporting files with some path like
__vue__
, or something along those lines. This would prevent the paths from incorrectly mapping to files that exist on disk.The text was updated successfully, but these errors were encountered: