vite icon indicating copy to clipboard operation
vite copied to clipboard

Debugging vite+vue+typescript using HMR is broken. Breakpoint on incorrect line numbers

Open hspaay opened this issue 2 years ago • 17 comments

Describe the bug

Trying to debug a vite+vue+ts app doesn't work for me. As soon as HMR runs the vscode debugger no longer stops on breakpoints. Possible the sourcemap gets out of sync.

In addition, chrome devtools doesn't show the source code but the hard to read minified code.

Similar bugs:

  1. https://github.com/vitejs/vite/issues/5834 although this report mentions that "the application does indeed break at the expected moment, and both Chrome Debugger and VSCode highlight the same (correct) lines", which is different behavior than mentioned in this report.

  2. https://github.com/vitejs/vite/issues/5039 might be the same issue but uses react. It does mention that a browser refresh fixes it, but does not mention the problem that setting breakpoints elsewhere in the code is no longer always possible.

The issue at hand seems that after HMR the sourcemaps get messed up. I suspect that the issue goes deeper than that as I have a more complex app where the source map remains incorrect even after clearing the cache. Anyway lets fix get the simple case addressed.

Reproduction

  1. Create a new vite app as follows

yarn create @vitejs/app; select vue as framework and vue-ts as the variant

  1. Build and run the dev server:

yarn yarn dev

  1. start vscode (I'm using 1.62.3) and add the project folder to the workspace
  2. configure the launcher for chrome - run - add configuration - chrome; change the url port to 3000
  3. Start debugging. This should launch chrome displaying the vite demo app
  4. Open src/components/HelloWorld.vue in vscode and set a breakpoint on line 29, eg the button that has count++
  5. Click on the button: -> result vscode stops at the breakpoint as expected
  6. Edit the line to increment count by two, eg count+=2. Save
  7. Click on the button again Expected behavior: vscode stops at the breakpoint Actual behavior: breakpoint is ignored

After reloading the browser (F5) the breakpoint works again in this simple example until the code changes.

To spice it up a bit, replace the line with count++ to invoke a function 'incrementCount as follows:

  <button type="button" @click="() => incrementCount()">count is: {{ count }}</button>

and add this function in the script section:

const incrementCount = () => {
  count.value += 22
}

Repeat the test, this time setting the breakpoint in the function.-> this works as expected

Now try to set the breakpoint on the line with the button click. vscode will add a breakpoint in HelloWorld.vue?import=&t=1638336354075 (or something like it).

Hit the count button again... => expected behavior, the debugger stops. Actual behavior: the debugger does not stop. Hit F5 in the browser. => expected behavior, the browser refreshes and shows the app. Actual behavior, the debugger stops somewhere randomly.

System Info

System:
    OS: Linux 5.13 Ubuntu 21.10 21.10 (Impish Indri)
    CPU: (4) x64 Intel(R) Core(TM) i5-4570S CPU @ 2.90GHz
    Memory: 5.43 GB / 23.32 GB
    Container: Yes
    Shell: 5.1.8 - /bin/bash
  Browsers:
    Chrome: 94.0.4606.61
    Firefox: 94.0
  npmPackages:
    @vitejs/plugin-vue: ^1.9.0 => 1.10.1 
    vite: ^2.5.10 => 2.6.14

Used Package Manager

yarn

Logs

No response

Validations

hspaay avatar Dec 01 '21 05:12 hspaay

This is a very serious issue! It is not jus TS, but for JS also. My Vite + Vue + Js project is completly undebuggable.

martonx avatar Dec 19 '21 21:12 martonx

Update: In my case this is only a problem for Single File Components. Debugging in typescript files seems to have correct line numbers. It does suggest that the problem is in sourcemap generation for SFCs. Is there a way to get some more eyes on this?

hspaay avatar Jan 06 '22 01:01 hspaay

me too,I wonder how soon the author team can solve

qq1063823095 avatar Jan 25 '22 08:01 qq1063823095

Started playing around with Vite+Vue tonight - and came across this error. I just don't get it - how can anyone use Vite when it's impossible to attach a debugger (Chrome // VSCode)....? This seems like a critical show stopper bug issue to me. Hope it gets fixed soon. Will have to revert to Webpack for now.

ngjermundshaug avatar Feb 08 '22 01:02 ngjermundshaug

@ngjermundshaug yes indeed, it leads me to think that it either isn't used a lot or only hits a few people. A long shot but maybe @yyx990803 can help to give it the attention it deserves.

hspaay avatar Feb 08 '22 01:02 hspaay

me too, I can't debugging in chrome dev tool. It's a serious bug.

m430 avatar Feb 21 '22 06:02 m430

Got same issue with vite + typescript + react + mobx, but only happened in some ts file.

Cmen117696 avatar Feb 23 '22 03:02 Cmen117696

can't believe this bug has been hanging for nearly half years and nothing changed is vite just a toy or something

libgcc avatar Apr 23 '22 13:04 libgcc

Agreed, it is unfortunate as apart from debugging not working I love vite.

Maybe it is time to look at alternatives. ~~Has anyone tried snowpack? https://github.com/FredKSchott/snowpack, or maybe something else?~~
Update: 2022-05-06: snowpack is no longer updated and now recommends to use vite.

hspaay avatar Apr 24 '22 04:04 hspaay

I too am affected by this issue. I walked through the sequence below while playing around with this problem today. I was working on private code but suspect the same holds on a simpler repo.

Specific test:

  1. Baseline file = no changes - set a breakpoint at line 70 -- that line is just a console.log("test") -- this is a Typescript + React functional component = TSX file -- the breakpoint is in the middle of the function.
  2. Trigger the break point, all is good
  3. Add a single line of code at line 71 (just copy the console.log() from line 70), save the file, let the HMR trigger, breakpoint triggers -- breakpoint is still at line 70
  4. VS Code opens the ?import file which is the Vite processed version of the raw source
  5. The breakpoint triggers at line 71 in the ?import file. This is a completely different spot than intended since the file has been transformed.
  6. Remove the added line at 71, the file is now the exact same as before -- breakpoint is still at line 70 in the source file
  7. Save and trigger the breakpoint
  8. VS Code opens the ?import version of the file with the breakpoint at line 70 -- this is still nowhere near the intended spot since the ?import version is processed (not raw source)

So, between steps 1 and 9, the source code is the exact same, but the resulting breakpoint trigger location has changed when VS Code triggers. I don't know the internals well enough, but it seems that Vite is capable of handling the mapping correctly on first load, but then something changes post HMR. In particular, the thing that changes is independent of the actual source since my source files are identical at start and end.

I'm purely guessing, but it seems that the source map is missing the last hop to get from the ?import version of the page back to the raw source. This is my hunch since the triggered breakpoint is at the correct line in the wrong file. Further, it seems that the mapping is correct up until the HMR transform takes place.

If there are any pointers on how to debug these various steps, I'd give it a whirl. Unfortunately, I don't know the debugging process or source maps well enough to reason it out otherwise. That is, I'd love to help, but it's not clear how.

byronwall avatar May 02 '22 20:05 byronwall

Based on issue https://github.com/vitejs/vite/issues/673, it seems that disabling HMR works around the issue. In vite.config.ts:

export default defineConfig({
  server: {
    hmr: false
  },
  plugins: [
...

It looks like the choice is to have HMR or debugging, you cannot have both.

If you don't mind restarting the dev server after each edit, this might be a viable (although somewhat tedious) workaround.

hspaay avatar May 07 '22 01:05 hspaay

I made an attempt at upgrading from vue2 to vue3+vite a few days ago. Debugging worked fine for a few hours - until it suddenly didn't. Haven't been able to quite pinpoint what causes it yet.

BUT I have been able to make it work in Firefox (with HMR) by:

  1. Add a console.log statement somewhere in the vue file you want to debug
  2. Goto Console in Vue - click on the Filename:line that logged. This will open the correct source file that logged (Component.vue?t=123123423423)
  3. Attach debugger on given line

You can also press Ctrl-P in Debugger window in Firefox and open the component/file there - but you'll see several files (same name, different url) but make sure you take the cachebusted version (the one with ?t=123123123123).

ngjermundshaug avatar May 16 '22 07:05 ngjermundshaug

I'm having same problem with vite. Not able to debug. :(

abdulghanitech avatar May 17 '22 11:05 abdulghanitech

I have the same issue (breakpoints are off by 10-20 lines depending on the file). It's not happening on all the files which is super strange. I'm trying to find a pattern.

Disabling HRM does not solve anything, but disabling sourcemaps is the only way I can debug something.

ThePainnn avatar Jul 19 '22 22:07 ThePainnn

Update on my bug. I've analyze the sourcemaps for a simple file (http://sokra.github.io/source-map-visualization/#custom is a very awesome tool). Every file containing an import of react has bad sourcemaps, without react it's fine. Those file contains generated code to enable HMR:

let prevRefreshReg;
let prevRefreshSig;

if (import.meta.hot) {
  if (!window.__vite_plugin_react_preamble_installed__) {
    throw new Error("@vitejs/plugin-react can't detect preamble. Something is wrong. " + "See https://github.com/vitejs/vite-plugin-react/pull/11#discussion_r430879201");
  }

  prevRefreshReg = window.$RefreshReg$;
  prevRefreshSig = window.$RefreshSig$;

  window.$RefreshReg$ = (type, id) => {
    RefreshRuntime.register(type, "C:/blablabla/AttributeEditor/index.js" + " " + id);
  };

  window.$RefreshSig$ = RefreshRuntime.createSignatureFunctionForTransform;
}

var _s = $RefreshSig$();

from what I've seen sourceMaps are not taking into account those lines and it offset the sourceMaps by something like 12 to 15 lines. This is my observation, I might be wrong, but removing the generated code HMR setup fixes the source maps completely.

I'm trying to disable HMR to see source maps, but setting:

server: { hmr: false },

does not do anything. This code is still being generated and source maps are off.

ThePainnn avatar Jul 20 '22 18:07 ThePainnn

This is a major deal breaker issue for our team and is blocking our migration from Webpack.

I don't understand how such a critical bug can go unresolved for so long, did we miss a workaround or something?

Any feedback from the vite.js team would be much appreciated.

DanielLaberge avatar Jul 21 '22 17:07 DanielLaberge

Found my issue! I was using vite-plugin-require because we had a couple of them. I manage to remove all except one so I use the exclude option:

  return defineConfig({
    plugins: [
      react(),
      vitePluginRequire({
        fileRegex:/(config.js)$/
      }),

When analysing source maps with this plugin, they come out quite differently. Some newline are inserted that are messing up source maps.

You can repro with a very simple project testvite.zip

I hope this solve the issue for a bunch of you!

Cheers!

ThePainnn avatar Jul 21 '22 18:07 ThePainnn

I have exactly the same issue, I can't use debugger or breakpoints at all using Vite, any idea how to fix this?

MisaelMP avatar Aug 14 '22 10:08 MisaelMP

您的邮件已经发送,接受者表示十分感谢,他还让我告诉你以后要经常联系哦!

Cmen117696 avatar Aug 14 '22 10:08 Cmen117696

Any update on this? I can connect the debugger to the compiled JS files in vscode, but unable to link it all the way to the original TS files.

u12206050 avatar Oct 24 '22 07:10 u12206050