vue-loader/next registerHMR(instance)的bug

Created on 9 Jan 2020  ·  2Comments  ·  Source: vuejs/vue-loader

Version

16.0.0-alpha.1

Reproduction link

https://github.com/doter1995/vue3-test/tree/vue-loader_bug_demo

Steps to reproduce

在webpack中devServer.hot没有开启时。运行webpack-dev-server。
由于vue-loader对vue转换后,生成下面代码。

/* hot reload */
if (module.hot) {
  const api = __VUE_HMR_RUNTIME__
  module.hot.accept()
  if (!api.createRecord('7ba5bd90', script)) {
    api.reload('7ba5bd90', script)
  }

  module.hot.accept("./App.vue?vue&type=template&id=7ba5bd90&scoped=true", () => {
    api.rerender('7ba5bd90', render)
  })
}

从而不会createRecord
在页面加载时报错:Uncaught TypeError: Cannot read property 'instances' of undefined

定位源码:

function mountComponent(initialVNode, container, anchor, parentComponent, parentSuspense, isSVG) {
        const instance = (initialVNode.component = defineComponentInstance(initialVNode, parentComponent));
        //这里并没有判断webpack是否配置hot,从而直接调用registerHMR
        if (__HMR__ && instance.type.__hmrId != null) {
            registerHMR(instance);
        }

````
同时`map.get(instance.type.__hmrId)`由于没有调用过createRecord从而返回null。如下代码机会报错:
```js
function registerHMR(instance) {
    map.get(instance.type.__hmrId).instances.add(instance);
}
function unregisterHMR(instance) {
    map.get(instance.type.__hmrId).instances.delete(instance);
}

此处

What is expected?

export function registerHMR(instance: ComponentInternalInstance) {
  const record = map.get(instance.type.__hmrId!)
  if (record && record.instances){
    record.instances.add(instance)
  }
}

export function unregisterHMR(instance: ComponentInternalInstance) {
  const record = map.get(instance.type.__hmrId!)
  if (record && record.instances){
    record.instances.delete(instance)
  }
}

What is actually happening?

/packages/runtime-core/src/hmr.ts

export function registerHMR(instance: ComponentInternalInstance) {
  map.get(instance.type.__hmrId!)!.instances.add(instance)
}

export function unregisterHMR(instance: ComponentInternalInstance) {
  map.get(instance.type.__hmrId!)!.instances.delete(instance)
}

不确定是否应该这样修复

Most helpful comment

这个问题依旧存在啊~ 就算用了v16.0.0-alpha.2的版本依旧报错,改至16.0.0-beta.7也一样
`Uncaught ReferenceError: __VUE_HMR_RUNTIME__ is not defined

"vue": "^2.6.11"
"vue-router": "^3.4.3"
"vue-template-compiler": "^2.6.11"
"vue-loader": "^16.0.0-beta.7",
`

All 2 comments

fix

这个问题依旧存在啊~ 就算用了v16.0.0-alpha.2的版本依旧报错,改至16.0.0-beta.7也一样
`Uncaught ReferenceError: __VUE_HMR_RUNTIME__ is not defined

"vue": "^2.6.11"
"vue-router": "^3.4.3"
"vue-template-compiler": "^2.6.11"
"vue-loader": "^16.0.0-beta.7",
`

Was this page helpful?
0 / 5 - 0 ratings