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'))
exports.genHotReloadCode = (id, functional) => {
return wrap(`
if (!module.hot.data) {
api.createRecord('${id}', component.options)
} else {
api.${functional ? `rerender` : `reload`}('${id}', component.options)
}
`)
}
exports.genTemplateHotReloadCode = id => {
return wrap(`
if (module.hot.data) {
require(${hotReloadAPIPath}).rerender('${id}', {
const genTemplateHotReloadCode = (id, request) => {
return `
module.hot.accept(${request}, function () {
api.rerender('${id}', {
render: render,
staticRenderFns: staticRenderFns
})
}
`)
})
`.trim()
}
function wrap (inner) {
exports.genHotReloadCode = (id, functional, templateRequest) => {
return `
/* hot reload */
if (module.hot) {
......@@ -29,7 +19,12 @@ if (module.hot) {
api.install(require('vue'))
if (api.compatible) {
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()
......
......@@ -80,13 +80,14 @@ module.exports = function (source) {
// template
let templateImport = `var render, staticRenderFns`
let templateRequest
if (descriptor.template) {
const src = descriptor.template.src || resourcePath
const idQuery = `&id=${id}`
const scopedQuery = hasScoped ? `&scoped=true` : ``
const attrsQuery = attrsToQuery(descriptor.template.attrs)
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}`
}
......@@ -145,7 +146,7 @@ var component = normalizer(
}
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.
......
const qs = require('querystring')
const loaderUtils = require('loader-utils')
const { compileTemplate } = require('@vue/component-compiler-utils')
const { genTemplateHotReloadCode } = require('../codegen/hotReload')
// Loader that compiles raw template into JavaScript functions.
// This is injected by the global pitcher (../pitch) for template
......@@ -18,7 +17,6 @@ module.exports = function (source) {
const isServer = loaderContext.target === 'node'
const isProduction = loaderContext.minimize || process.env.NODE_ENV === 'production'
const isFunctional = query.functional
const needsHotReload = !isServer && !isProduction && options.hotReload !== false
// allow using custom compiler via options
const compiler = options.compiler || require('vue-template-compiler')
......@@ -59,16 +57,10 @@ module.exports = function (source) {
)
}
let { code } = compiled
// hot-reload
if (needsHotReload) {
code += genTemplateHotReloadCode(id)
}
const { code } = compiled
// finish with ESM exports
code += `export { render, staticRenderFns }`
return code
return code + `\nexport { render, staticRenderFns }`
}
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