Commit 4ccd96fe authored by Evan You's avatar Evan You

fix: improve HMR reliability

parent 67a07822
const hotReloadAPIPath = JSON.stringify(require.resolve('vue-hot-reload-api')) const hotReloadAPIPath = JSON.stringify(require.resolve('vue-hot-reload-api'))
exports.genHotReloadCode = (id, functional) => { const genTemplateHotReloadCode = (id, request) => {
return wrap(` return `
if (!module.hot.data) { module.hot.accept(${request}, function () {
api.createRecord('${id}', component.options) api.rerender('${id}', {
} else {
api.${functional ? `rerender` : `reload`}('${id}', component.options)
}
`)
}
exports.genTemplateHotReloadCode = id => {
return wrap(`
if (module.hot.data) {
require(${hotReloadAPIPath}).rerender('${id}', {
render: render, render: render,
staticRenderFns: staticRenderFns staticRenderFns: staticRenderFns
}) })
} })
`) `.trim()
} }
function wrap (inner) { exports.genHotReloadCode = (id, functional, templateRequest) => {
return ` return `
/* hot reload */ /* hot reload */
if (module.hot) { if (module.hot) {
...@@ -29,7 +19,12 @@ if (module.hot) { ...@@ -29,7 +19,12 @@ if (module.hot) {
api.install(require('vue')) api.install(require('vue'))
if (api.compatible) { if (api.compatible) {
module.hot.accept() module.hot.accept()
${inner.trim()} if (!module.hot.data) {
api.createRecord('${id}', component.options)
} else {
api.${functional ? `rerender` : `reload`}('${id}', component.options)
}
${templateRequest ? genTemplateHotReloadCode(id, templateRequest) : ``}
} }
} }
`.trim() `.trim()
......
...@@ -80,13 +80,14 @@ module.exports = function (source) { ...@@ -80,13 +80,14 @@ module.exports = function (source) {
// template // template
let templateImport = `var render, staticRenderFns` let templateImport = `var render, staticRenderFns`
let templateRequest
if (descriptor.template) { if (descriptor.template) {
const src = descriptor.template.src || resourcePath const src = descriptor.template.src || resourcePath
const idQuery = `&id=${id}` const idQuery = `&id=${id}`
const scopedQuery = hasScoped ? `&scoped=true` : `` const scopedQuery = hasScoped ? `&scoped=true` : ``
const attrsQuery = attrsToQuery(descriptor.template.attrs) const attrsQuery = attrsToQuery(descriptor.template.attrs)
const query = `?vue&type=template${idQuery}${scopedQuery}${attrsQuery}` const query = `?vue&type=template${idQuery}${scopedQuery}${attrsQuery}`
const request = stringifyRequest(src + query) const request = templateRequest = stringifyRequest(src + query)
templateImport = `import { render, staticRenderFns } from ${request}` templateImport = `import { render, staticRenderFns } from ${request}`
} }
...@@ -145,7 +146,7 @@ var component = normalizer( ...@@ -145,7 +146,7 @@ var component = normalizer(
} }
if (needsHotReload) { if (needsHotReload) {
code += `\n` + genHotReloadCode(id, hasFunctional) code += `\n` + genHotReloadCode(id, hasFunctional, templateRequest)
} }
// Expose filename. This is used by the devtools and vue runtime warnings. // Expose filename. This is used by the devtools and vue runtime warnings.
......
const qs = require('querystring') const qs = require('querystring')
const loaderUtils = require('loader-utils') const loaderUtils = require('loader-utils')
const { compileTemplate } = require('@vue/component-compiler-utils') const { compileTemplate } = require('@vue/component-compiler-utils')
const { genTemplateHotReloadCode } = require('../codegen/hotReload')
// Loader that compiles raw template into JavaScript functions. // Loader that compiles raw template into JavaScript functions.
// This is injected by the global pitcher (../pitch) for template // This is injected by the global pitcher (../pitch) for template
...@@ -18,7 +17,6 @@ module.exports = function (source) { ...@@ -18,7 +17,6 @@ module.exports = function (source) {
const isServer = loaderContext.target === 'node' const isServer = loaderContext.target === 'node'
const isProduction = loaderContext.minimize || process.env.NODE_ENV === 'production' const isProduction = loaderContext.minimize || process.env.NODE_ENV === 'production'
const isFunctional = query.functional const isFunctional = query.functional
const needsHotReload = !isServer && !isProduction && options.hotReload !== false
// allow using custom compiler via options // allow using custom compiler via options
const compiler = options.compiler || require('vue-template-compiler') const compiler = options.compiler || require('vue-template-compiler')
...@@ -59,16 +57,10 @@ module.exports = function (source) { ...@@ -59,16 +57,10 @@ module.exports = function (source) {
) )
} }
let { code } = compiled const { code } = compiled
// hot-reload
if (needsHotReload) {
code += genTemplateHotReloadCode(id)
}
// finish with ESM exports // finish with ESM exports
code += `export { render, staticRenderFns }` return code + `\nexport { render, staticRenderFns }`
return code
} }
function pad (source) { function pad (source) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment