Search code examples
vue.jswebpack-4ts-loader

How to properly inject app element in webpack? - Receiving [Vue warn]: Cannot find element: #app


Here is my code code example

I am trying to learn webpack 4 and am setting up a test project.

Traditionally I have built vuejs app inside Asp.net websites. So I always know the entry html point and can put the element on the page.

From all the blog post I have seen for vue this seems to be all they do to setup their app.

App.Vue

<template>
    <div id='app'>
        <router-view></router-view>
    </div>
</template>

<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';

@Component
export default class App extends Vue {

}
</script>

index.ts

import Vue from 'vue';
import App from './App.vue';
import router from './router';

Vue.config.productionTip = false;

new Vue({
  el: '#app',
  render: (h) => h(App),
  router
}).$mount('#app');

When I run this I get [Vue warn]: Cannot find element: #app. If I add

 document.write('<div id="app"><router-view></router-view></div>');

The code runs fine. Since I am using vue-router, I don't think I actually need the App.vue file, but I still need someplace to mount the vue object too.

So looking at my github link, what would be the correct way to get this working?


Solution

  • This is a chicken-and-egg problem. You're trying to amount the root component to the #app div, but the #app div exists inside the App component. At the time when you call new Vue the #app div doesn't exist because the App component hasn't mounted!

    Most Vue apps have an empty <div id="app"></div> in the index.html file so that the root Vue component has somewhere to mount to when the page has loaded.

    If you don't want to do it that way then you can mount it manually instead:

    const root = new Vue({
      render: (h) => h(App),
      router
    }).$mount()
    
    document.body.appendChild(root.$el)