Skip to content
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

Incorrect HMR behavior with webpack 5 and enabled source maps #1795

Open
yura3d opened this issue Feb 16, 2021 · 18 comments
Open

Incorrect HMR behavior with webpack 5 and enabled source maps #1795

yura3d opened this issue Feb 16, 2021 · 18 comments

Comments

@yura3d
Copy link

yura3d commented Feb 16, 2021

Version

16.1.2

Reproduction link

https://github.com/yura3d/vue3-webpack5

Steps to reproduce

  1. Clone GitHub repo.
  2. Run yarn and yarn dev.
  3. Browse localhost:8080, type some symbols to input field and/or press counter button to change component's state.
  4. Open src/App.vue and change something in <template> section.

What is expected?

HMR applies, input field and counter still contain their values as state shouldn't be changed according to docs: https://vue-loader.vuejs.org/guide/hot-reload.html#state-preservation-rules

What is actually happening?

HMR applies.

State is lost when bundling with webpack 5 if devtool is set to something with source maps (source-map, eval-source-map, etc).

State is preserved when devtool doesn't set source maps (false, eval), or when bundling with webpack 4 (even with source maps) and almost the same webpack.config.js.


I see this console output on HMR with webpack 5 and source maps:

log.js:24 [HMR] Updated modules:
log.js:16 [HMR]  - ./src/App.vue?vue&type=script&lang=js
log.js:24 [HMR]  - ./src/App.vue?vue&type=script&lang=js
log.js:24 [HMR]  - ./src/App.vue
log.js:16 [HMR]  - ./src/App.vue?vue&type=template&id=7ba5bd90&scoped=true
log.js:24 [HMR]  - ./src/App.vue?vue&type=template&id=7ba5bd90&scoped=true
log.js:16 [HMR]  - ./src/App.vue?vue&type=style&index=0&id=7ba5bd90&lang=scss&scoped=true
log.js:24 [HMR] App is up to date.
hotModuleReplacement.js:215 [HMR] Reload all css

And this on HMR without source maps:

log.js:24 [HMR] Updated modules:
log.js:16 [HMR]  - ./src/App.vue?vue&type=template&id=7ba5bd90&scoped=true
log.js:24 [HMR]  - ./src/App.vue?vue&type=template&id=7ba5bd90&scoped=true
log.js:16 [HMR]  - ./src/App.vue?vue&type=style&index=0&id=7ba5bd90&lang=scss&scoped=true
log.js:24 [HMR] App is up to date.
hotModuleReplacement.js:215 [HMR] Reload all css

It seems component's JS recompiles even when there are no changes in <script> section if source maps are enabled.

@ThakurKarthik
Copy link

Same issue is happening for my sample project too

const path = require('path');
const { VueLoaderPlugin } = require('vue-loader');
module.exports = {
  mode: 'development',
  // devtool: 'inline-source-map',
  entry: './src/index.ts',
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader'
      },
      {
        test: /\.tsx?$/,
        use: 'ts-loader',
        exclude: /node_modules/,
      },
      {
        test: /\.css$/,
        use: [
          'vue-style-loader',
          'css-loader'
        ]
      }
    ],
  },
  plugins: [
    new VueLoaderPlugin()
  ],
  resolve: {
    extensions: ['.tsx', '.ts', '.js', '.vue'],
    alias: {
      vue: 'vue/dist/vue.js'
    },
  },
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
  devServer: {
    contentBase: './dist',
    hot: true
  },
};

If I uncomment the devtool part, and I change in template / style part the whole component is replaced thus losing the component state.

@yura3d
Copy link
Author

yura3d commented Jul 2, 2021

This behavior reproduces even with projects created by official Vue CLI 5 (@vue/cli@next, currently in beta), which uses webpack 5 under the hood.

@bobvandevijver
Copy link

This also happens with vue-loader 15.9.6 on webpack 5. My reproducer is this repository, which uses Webpack Encore as wrapper in a Symfony project.

@hputzek
Copy link

hputzek commented Aug 23, 2021

Same issue here. I can reproduce this:

State is preserved when devtool doesn't set source maps (false, eval), or when bundling with webpack 4 (even with source maps) and almost the same webpack.config.js.

@Imabigcookie
Copy link

Imabigcookie commented Dec 1, 2021

Is there any workaround except disabling devtool options so far?

@nerdoza
Copy link

nerdoza commented Dec 1, 2021

@Imabigcookie, you don't need to completely disable devtools, but you do need to set it to source-map and make sure the target is set to web.

@Imabigcookie
Copy link

Imabigcookie commented Dec 1, 2021

@bayssmekanique, i've already tried and it doesn't help

const path = require('path');

const HtmlWebpackPlugin = require('html-webpack-plugin');
const { VueLoaderPlugin } = require('vue-loader');

module.exports = (env = {}) => ({
  mode: 'development',
  entry: "./src/index.js",
  devtool: 'source-map',
  target: 'web',
  output: {
    publicPath: 'auto',
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        use: 'vue-loader',
      },
    ],
  },
  plugins: [
    new VueLoaderPlugin(),
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, './public/index.html'),
    })
  ],
  devServer: {
    static: {
      directory: path.join(__dirname, 'public'),
    },
    port: 3000,
    hot: true,
    headers: {
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
      'Access-Control-Allow-Headers': 'X-Requested-With, content-type, Authorization',
    },
  },
});
{
  "name": "core",
  "version": "1.0.0",
  "description": "",
  "scripts": {
    "dev": "webpack serve --mode development",
    "build": "webpack --mode production"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "html-webpack-plugin": "^5.5.0",
    "vue-loader": "^15.9.8",
    "vue-template-compiler": "^2.6.14",
    "webpack": "^5.64.4",
    "webpack-cli": "^4.9.1",
    "webpack-dev-server": "^4.6.0"
  },
  "dependencies": {
    "vue": "^2.6.14",
    "vue-router": "^3.5.3",
    "vuex": "^3.6.2"
  }
}

@yura3d
Copy link
Author

yura3d commented Mar 3, 2022

The bug is still reproducible in 17.0.0, even on fresh setup using the newest @vue/cli 5

@felipecarrillo100
Copy link

any solution to this? I'm having the same issue. Hot reload only works with devTool=false.

using this combination:

"typescript": "^4.7.4",
"vue-loader": "^17.0.0",
"vue-style-loader": "^4.1.3",
"webpack": "^5.74.0",
"webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.9.3"

@tmcdos
Copy link

tmcdos commented Aug 10, 2022

15 months and no fix :(

@tmcdos
Copy link

tmcdos commented Nov 10, 2022

This nasty bug forces me to revert back to Vue 2 and Webpack 4.

@meduzen-immoweb
Copy link

This nasty bug forces me to revert back to Vue 2 and Webpack 4.

If you have the opportunity to try ViteJS, you might never go back to Webpack.

@tmcdos
Copy link

tmcdos commented Nov 10, 2022

This nasty bug forces me to revert back to Vue 2 and Webpack 4.

If you have the opportunity to try ViteJS, you might never go back to Webpack.

Vite has issues, too - it does not allow me to put breakpoints inside my .vue files. I have to add/remove debugger statements. HMR in Vite is not perfect, too - sometimes it just does not notice that I've changed something in my code and I have to reload the page.

@underfin
Copy link
Member

underfin commented Mar 21, 2023

@sodatea I debug this today, it caused by select script block return sourcemap at https://github.com/vuejs/vue-loader/blob/next/src/select.ts#L33. The sourcemap which include all content of a vue file, it is different after code change, it will generate different hash at webpack5(used webpack-source at https://github.com/webpack/webpack-sources/blob/main/lib/SourceMapSource.js#L233), so i change template block will caused script block change. The webpack4 worked fine, becasue it is not calculate hash for sourcemap at [email protected], see https://github.com/webpack/webpack-sources/blob/v1.4.3/lib/SourceMapSource.js#L50.

@tmcdos
Copy link

tmcdos commented Mar 21, 2023

@underfin So, do you have any ideas how to fix this bug?

@underfin
Copy link
Member

underfin commented Apr 4, 2023

@tmcdos Maybe you can use patch-package to remove https://github.com/webpack/webpack-sources/blob/main/lib/SourceMapSource.js#L233 this line, but might meet sourcemap line error...

@a298003154
Copy link

@tmcdos Maybe you can use patch-package to remove https://github.com/webpack/webpack-sources/blob/main/lib/SourceMapSource.js#L233 this line, but might meet sourcemap line error...

没有别的办法了吗,看上面只能设置 devtool: false 激活热更

@tmcdos
Copy link

tmcdos commented Oct 24, 2023

It looks like I found a workaround - if I move https://github.com/webpack/webpack-sources/blob/main/lib/SourceMapSource.js#L233 between https://github.com/webpack/webpack-sources/blob/9f98066311d53a153fdc7c633422a1d086528027/lib/SourceMapSource.js#L235 and https://github.com/webpack/webpack-sources/blob/9f98066311d53a153fdc7c633422a1d086528027/lib/SourceMapSource.js#L236
so it looks like

if (this._hasOriginalSource) 
{
  hash.update(this._sourceMapAsBuffer); // originally this was outside of the IF block
  hash.update(this._originalSourceAsBuffer);
}

then if I only change something in the component template (e.g. a CSS class) - the script section of the component is not reloaded.
I do not know if this is a proper fix because I am totally clueless about the inner workings of Webpack and Webpack-Sources package in particular.
I use custompatch to patch webpack-sources in my project.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests