vuejs / vue-loader

📦 Webpack loader for Vue.js components
MIT License
4.99k stars 915 forks source link

HMR partially ignores changes in Vue2 components when sideEffect=false is used #1929

Open nskazki opened 2 years ago

nskazki commented 2 years ago

Version

15.9.8

Reproduction link

https://github.com/nskazki/vue-loader-wont-hot-reload-text-nodes

Steps to reproduce

  1. Run npm run build and check dist/main.js. You shouldn't find the UsedComponent in there.
  2. Run npm start
  3. Apply a few changes to the src/RootComponent.vue. Changes applied to the templates or script sections won't be reflected. Changes applied to the style section will be reflected.
  4. Apply a few changes to the src/Namespace/UsedComponent.vue. Changes applied to the template section will be partially reflected. Changes appllied to the script and style sections will be fully reflected.
  5. Run npm start and try updating the RootComponent.vue or src/Namespace/UsedComponent.vue. HMR will ignore changes applied to the root component and only partially update the child component.
  6. Open the webpack.config.js and comment out the sideEffects option.
  7. Run npm run build and check dist/main.js again. You should find the UsedComponent in there this time.
  8. Run npm start and try updating the RootComponent.vue or src/Namespace/UsedComponent.vue. HRM should pick up any changes made to these components.

What is expected?

Whether the sideEffects is set or not, HMR should pick up changes applied to any components.

What is actually happening?

HMR partially ignores changes applied to SFC compiled with vue-loader@15.9.8 when sideEffect=false is used.

module.exports = {
  module: {
    rules: [{
      test: /\.vue$/,
      loader: 'vue-loader',
      sideEffects: false
    }]
  }
}
  1. HMR won't apply changes made to a root component.
  2. HMR won't apply changes applied to existing lines of text, tags, and components of a child Vue components. However, new lines, tags, and components as well as removed ones will be reflected. Changes to the script and style section will always be reflected.

What is so special about sideEffect=false?

Without this option, Webpack would include into a bundle unused components should they be re-exported along with the used components via a common proxy.

// Namespace/index.js - a common proxy

export { default as UsedComponent } from './UsedComponent.vue'
export { default as UnusedComponent } from './UnusedComponent.vue'
// RootComponent.vue

<script>
import { UsedComponent } from './Namespace'

export default {
  components: {
    UsedComponent
  }
}
</script>

It works just fine with Vue@3 and VueLoader@16, but I'm still on Vue@2 and VueLoader@15.9.8 and it would mean a world to me if you could fix the problem in that old and dusty v15!

nskazki commented 2 years ago

The problem is identical to https://github.com/vuejs/vue-loader/issues/1931 but is happening under different conditions.