{"record":{"id":"f21f3a244cbbd352","repo":"Meituan-Dianping/mpvue","slug":"do-not-mount-vue-to-html-or-body-mount-to-no","errorCode":null,"errorMessage":"Do not mount Vue to <html> or <body> - mount to normal elements instead.","messagePattern":"Do not mount Vue to <html> or <body> - mount to normal elements instead\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/platforms/web/entry-runtime-with-compiler.js","lineNumber":26,"sourceCode":"import { query } from './util/index'\nimport { shouldDecodeNewlines } from './util/compat'\nimport { compileToFunctions } from './compiler/index'\n\nconst idToTemplate = cached(id => {\n  const el = query(id)\n  return el && el.innerHTML\n})\n\nconst mount = Vue.prototype.$mount\nVue.prototype.$mount = function (\n  el?: string | Element,\n  hydrating?: boolean\n): Component {\n  el = el && query(el)\n\n  /* istanbul ignore if */\n  if (el === document.body || el === document.documentElement) {\n    process.env.NODE_ENV !== 'production' && warn(\n      `Do not mount Vue to <html> or <body> - mount to normal elements instead.`\n    )\n    return this\n  }\n\n  const options = this.$options\n  // resolve template/el and convert to render function\n  if (!options.render) {\n    let template = options.template\n    if (template) {\n      if (typeof template === 'string') {\n        if (template.charAt(0) === '#') {\n          template = idToTemplate(template)\n          /* istanbul ignore if */\n          if (process.env.NODE_ENV !== 'production' && !template) {\n            warn(\n              `Template element not found or is empty: ${options.template}`,\n              this","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/Meituan-Dianping/mpvue/blob/6c5d78ee04f58c6d782c456dfcf0fe63c0b7f89b/src/platforms/web/entry-runtime-with-compiler.js#L8-L44","documentation":"Vue refuses to mount an application instance onto <body> or <html>, because these elements host framework internals and external scripts; mounting would destroy/replace unrelated DOM. The instance init aborts (returns early) and a dev-mode warning is emitted.","triggerScenarios":"Calling new Vue({ el: 'body' }) / new Vue({ el: 'html' }) or vm.$mount('body') / $mount('html') — query(el) resolves to document.body or document.documentElement.","commonSituations":"Beginners targeting 'body' as the app root; boilerplate written against older patterns; dynamically calling $mount on document.body.","solutions":["Mount to a normal container element: <div id=\"app\"></div> with el: '#app'.","If you need to render into body, append and mount a child wrapper element instead.","Use render functions with a proper container rather than body/html."],"exampleFix":"// before\nnew Vue({ el: 'body', render: h => h(App) })\n// after\nnew Vue({ el: '#app', render: h => h(App) })\n// with <div id=\"app\"></div> in the HTML","handlingStrategy":"validation","validationCode":"function assertSafeMountTarget (el) {\n  const resolved = typeof el === 'string' ? document.querySelector(el) : el\n  if (resolved === document.body || resolved === document.documentElement) {\n    throw new Error('Do not mount Vue to <html> or <body>; use a normal element')\n  }\n}\nassertSafeMountTarget('#app')","typeGuard":"const isSafeMountEl = (el) => {\n  const e = typeof el === 'string' ? document.querySelector(el) : el\n  return !!e && e !== document.body && e !== document.documentElement\n};","tryCatchPattern":null,"preventionTips":["Always mount to a dedicated container like <div id=\"app\">","Never pass 'body' or 'html' to el/$mount","Check querySelector result is not body/html before mounting","Add an app bootstrap assertion in dev"],"tags":["vue","mounting","dom"],"backgroundTag":"vue-mount-to-body-or-html","analyzedSha":"6c5d78ee04f58c6d782c456dfcf0fe63c0b7f89b","analyzedAt":"2026-09-02T05:17:40.946Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T11:17:12.671Z"}