Philip F.
Philip F.

Reputation: 1237

Vue 3 with Vite rendering blank page when not using App.vue

Setup

I've initialized a new project using vite on an Arch based operating system.

When I try to create the simple counter from the vue docs, the elemet doesn't render.

Code

index.html:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" href="/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite App</title>
  </head>
  <body>
    <div id="counter">
      Counter: {{ counter }}
    </div>
    
    <script type="module" src="/src/main.js"></script>
  </body>
</html>

main.js

import { createApp } from 'vue'

var CounterApp = {
    data() {
      return {
        counter: 0
      }
    },
    mounted() {
      setInterval(() => {
        this.counter++
      }, 1000)
    }
  }
  
  
createApp(CounterApp).mount('#counter')

When I inspect the element it is commented out:

console

Question

Why is that? And how to resolve the error?

Upvotes: 8

Views: 11095

Answers (2)

schettino72
schettino72

Reputation: 3170

By default the runtime compiler is not included in the Vue build. To include it, add the following resolve.alias configuration:

vite.config.js

export default defineConfig({
  plugins: [vue()],
  resolve: {
      alias: {
        vue: 'vue/dist/vue.esm-bundler.js',
      },
    },
})

Docs https://vitejs.dev/config/#resolve-alias

Upvotes: 15

Dan
Dan

Reputation: 63059

Doing that replaces the normal mounting process, and treats the root element like a template string for the App component. Since template strings require the runtime compiler, you would need to use a full build. There should be a console warning about that.

To avoid increasing the size of your app (by ~30%) with the full build, it's recommended to leave the mounting point untouched, and give the App component its own proper template:

index.html

<body>
  <div id="app"></div>
  <script type="module" src="/src/main.js"></script>
</body>

main.js

import { createApp } from 'vue'
import App from './App.vue'

createApp(App).mount('#app')

App.vue

<template>
  <div id="counter">
    Counter: {{ counter }}
  </div>
</template>
<script>
export default {
  name: 'App',
  data() {
    return {
      counter: 0
    }
  },
  mounted() {
    setInterval(() => {
      this.counter++
    }, 1000)
  }
}
</script>

Upvotes: 7

Related Questions