vuejs / vue-cli

🛠️ webpack-based tooling for Vue.js Development
https://cli.vuejs.org/
MIT License
29.76k stars 6.33k forks source link

HMR (Hot module reload) not working #6004

Open sdwru opened 4 years ago

sdwru commented 4 years ago

Version

4.5.8

The problem appears to have been introduced starting in @vue/cli-service@4.2.0. HMR still works in @vue/cli-service@4.1.2

Environment info

System:
    OS: Linux 4.18 CentOS Stream 8
    CPU: (4) x64 Intel(R) Xeon(R) CPU E3-1230 v3 @ 3.30GHz
  Binaries:
    Node: 14.11.0 - /usr/bin/node
    Yarn: 1.22.4 - /usr/local/bin/yarn
    npm: 6.14.8 - /usr/bin/npm
  Browsers:
    Chrome: Not Found
    Firefox: Not Found
  npmPackages:
    @ag-grid-community/vue: ^24.1.1 => 24.1.1
    @chenfengyuan/vue-countdown: ^1.1.2 => 1.1.5
    @fortawesome/vue-fontawesome: ^2.0.0 => 2.0.0
    @vue/babel-helper-vue-jsx-merge-props:  1.2.1
    @vue/babel-helper-vue-transform-on:  1.0.0-rc.2
    @vue/babel-plugin-jsx:  1.0.0-rc.3
    @vue/babel-plugin-transform-vue-jsx:  1.2.1
    @vue/babel-preset-app:  4.5.8
    @vue/babel-preset-jsx:  1.2.3
    @vue/babel-sugar-composition-api-inject-h:  1.2.1
    @vue/babel-sugar-composition-api-render-instance:  1.2.1
    @vue/babel-sugar-functional-vue:  1.2.2
    @vue/babel-sugar-inject-h:  1.2.2
    @vue/babel-sugar-v-model:  1.2.3
    @vue/babel-sugar-v-on:  1.2.3
    @vue/cli-overlay:  3.12.1
    @vue/cli-plugin-babel: ^4.5.8 => 4.5.8
    @vue/cli-service: ^4.5.8 => 4.5.8
    @vue/cli-shared-utils:  4.5.8 (3.12.1)
    @vue/component-compiler-utils:  3.2.0
    @vue/preload-webpack-plugin:  1.1.2
    @vue/reactivity: ^3.0.2 => 3.0.2
    @vue/shared:  3.0.2
    @vue/web-component-wrapper:  1.2.0
    babel-helper-vue-jsx-merge-props:  2.0.3
    vue: ^2.6.12 => 2.6.12 (2.3.3)
    vue-acl: 4.0.7 => 4.0.7
    vue-apexcharts: ^1.6.0 => 1.6.0
    vue-awesome-swiper: ^4.1.1 => 4.1.1
    vue-backtotop: ^1.6.1 => 1.6.1
    vue-chartjs: ^3.5.1 => 3.5.1
    vue-class-component: ^7.2.6 => 7.2.6
    vue-cli-webpack:  1.0.0
    vue-clickaway:  2.2.2
    vue-clipboard2: ^0.3.0 => 0.3.1
    vue-context: 4.0.0 => 4.0.0
    vue-e-bus:  1.0.0
    vue-echarts: ^4.0.3 => 4.1.0
    vue-feather-icons: ^5.1.0 => 5.1.0
    vue-flatpickr-component: ^8.1.6 => 8.1.6
    vue-form-wizard: ^0.8.4 => 0.8.4
    vue-fullcalendar: ^1.0.9 => 1.0.9
    vue-hot-reload-api:  2.3.4
    vue-i18n: ^8.22.1 => 8.22.1
    vue-instantsearch: ^2.7.1 => 2.7.1
    vue-loader:  15.9.3
    vue-perfect-scrollbar: ^0.1.0 => 0.1.0
    vue-prism-component: ^1.1.1 => 1.2.0
    vue-property-decorator: ^8.5.1 => 8.5.1
    vue-quill-editor: ^3.0.6 => 3.0.6
    vue-router: ^3.4.6 => 3.4.7
    vue-select: ^3.10.8 => 3.10.8
    vue-simple-calendar: ^4.4.0 => 4.4.0
    vue-simple-suggest: ^1.10.3 => 1.10.3
    vue-star-rating: ^1.7.0 => 1.7.0
    vue-style-loader:  4.1.2
    vue-template-compiler: ^2.6.12 => 2.6.12
    vue-template-es2015-compiler:  1.9.1
    vue-tour: ^1.5.0 => 1.5.0
    vue-tree-halower: ^1.8.0 => 1.8.3
    vue-video-player: ^5.0.2 => 5.0.2
    vue2-google-maps: ^0.10.6 => 0.10.7
    vue2-hammer: ^2.1.2 => 2.1.2
    vuedraggable: ^2.24.2 => 2.24.2
    vuejs-datepicker: ^1.5.4 => 1.6.2
    vuepress-plugin-container:  2.1.5
    vuepress-theme-craftdocs: ^2.0.7 => 2.0.7
    vuesax: 3.12.2 => 3.12.2
    vuex: ^3.5.1 => 3.5.1

Steps to reproduce

vue-cli-service serve

What is expected?

Changes to a File.vue file should be reflected in the browser without a reload

What is actually happening?

Changes are not shown until browser is reloaded


Downgrading to @vue/cli-service v4.1.2 resolves the problem

This is my vue.confg.js

module.exports = {
  publicPath: '/',
  transpileDependencies: [
    'vue-echarts',
    'resize-detector'
  ],
  configureWebpack: {
    optimization: {
      splitChunks: {
        chunks: 'all'
      }
    }
  },
  devServer: {
    host: '0.0.0.0',
    hot: true,
    https: false,
    allowedHosts: [
      'myhost.mydomain.com'
    ]
  }
}
fangbinwei commented 4 years ago

update: have no idea now. Also test: created vue2 project by @vue/cli@4.5.8, and run serve on my server, visited by allowedHosts.


Please provide reproducible repo. I create a new project by @vue/cli@3.12.1 which depends on @vue/cli-service@3.12.1 but can't reproduce your problem.

Did this problem appear after you upgraded any dependencies?

sdwru commented 4 years ago

I just tried devDependency @vue/cli-service@3.12.1 and HMR still works. I don't know about other versions. I just know that HMR does not work on @vue/cli-service@4.5.8.

sdwru commented 4 years ago

The problem appears to have been introduced starting in @vue/cli-service@4.2.0 and every version since then. The last version with working HMR is @vue/cli-service@4.1.2. I added this new info to my original post.

Please note that I am using a remote server with:

devServer: {
    host: '0.0.0.0',
    ...
}

I have not tested this with a server on localhost.

jonaskuske commented 4 years ago

@sdwru How is your host (myhost.mydomain.com) mapped to the dev server? Entry in your hosts file pointing at 127.0.0.1 or is there a separate server acting as a proxy?

sdwru commented 4 years ago

@sdwru How is your host (myhost.mydomain.com) mapped to the dev server? Entry in your hosts file pointing at 127.0.0.1 or is there a separate server acting as a proxy?

No mapping no proxy. No entry in hosts file. It's just a generic virtual Linux server with default settings. No firewall no selinux. I access the server at myhost.mydomain.com:8080 which is an A record that points to my IP address at my DNS provider like any other public server.

It works on @vue/cli-service@4.1.2 and does not seem to work on @vue/cli-service@4.2.0 or any version after that one.

This is my hosts file with the public ip obfuscated.

127.0.0.1 localhost.localdomain localhost localhost4.localdomain4 localhost4
# Auto-generated hostname. Please do not remove this comment.
xx.xx.xx.xx ce81test.local  ce81test
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
fangbinwei commented 4 years ago

There are some problems when using host 0.0.0.0 in remote development, will check it later

jonaskuske commented 4 years ago

Hmm, for me it fails to auto-detect the IP for the network URL on my remote server so it can't connect, but if I specify the host in devServer.public, it works.

@sdwru Mind moving your host from the allowedHosts array to the public field in devServer and check if that helps?

Edit: it does correctly detect my Server's IP, it just discards it because it's not a private one

fangbinwei commented 4 years ago

If you set host to 0.0.0.0

@vue/cli-service 4.1.2

webpack entries in development is

[
/path_to/node_modules/webpack-dev-server/client/index.js?http://`your_priviate_ip:port`/sockjs-node',
/path_to/node_modules/webpack/hot/dev-server.js',
'./src/main.js'
]

Besides, webpack-dev-server will inject entry dynamically, injected entry is /path_to/node_modules/webpack-dev-server/client/index.js?http://0.0.0.0',

Since you are using remote development server. Browser can't establish websocket connection through your_priviate_ip:port(should use your_public_ip:port or your domain:port)

However, the dynamic injected entry works. webpack-dev-server/client/index.js create socketUrl based on window.location since 0.0.0.0 was passed, so browser can establish websocket connection. HMR works.

https://github.com/webpack/webpack-dev-server/blob/4ab1f21bc85cc1695255c739160ad00dc14375f1/client-src/default/utils/createSocketUrl.js#L54-L60

@vue/cli-service 4.2.0

since webpack-dev-server/client is loaded twice, this bug was fixed by https://github.com/vuejs/vue-cli/pull/5069

So /path_to/node_modules/webpack-dev-server/client/index.js?http://your_priviate_ip:port/sockjs-node', won't let your HMR works.

solution

I believe if user set host (especially 0.0.0.0), respect it, and create entry based on it rather than private_ip.

Moreover, the public config mentioned by @jonaskuske makes the solution more complete, since it doesn't try to guess the URL of the server based on window.location. The priority of public is higher than host,

So workaround is

devServer: {
    host: '0.0.0.0',
   public: `your_domain:port`
}
sdwru commented 4 years ago

Thanks @jonaskuske @fangbinwei

Adding

public: 'mydomain.com:port' 

to devServer appears to work.