Robert C. Holland
Robert C. Holland

Reputation: 1813

Nuxt.js dynamic component error "Either pre-compile the templates into render functions, or use the compiler-included build"

I'm getting the following error in Nuxt.js:

[Vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.

found in

---> <Anonymous>
       <RenderPost> at components/RenderPost.vue
         <Pages/post/Id.vue> at pages/post/_id.vue
           <Nuxt>
             <Layouts/default.vue> at layouts/default.vue
               <Root>

I was following the examples here: https://stackoverflow.com/a/39519105 and my RenderPost.vue roughly looks like this:

<template>
    <client-only>
        <component :is="dynamicComponent" />
    </client-only>
</template>

<script>
export default {
    methods:
    {
        linkedView()
        {
            return `<a href="#" @click.prevent="runSomething">Click me</a>`;
        },

    },
    computed :
    {
        dynamicComponent() {
            return {
                data() { return { foo : null }},
                template : `<div>${this.linkedView()}<br>{{ foo }}</div>`,
                methods :
                {
                    runSomething()
                    {
                        this.foo = 'ran something!'
                    }
                }
            }
        }
    }
}
</script>

I added the <client-only> because I was also getting error about server and client not matching up. Without it, I get an additional error that says:

[Vue warn]: The client-side rendered virtual DOM tree is not matching server-rendered content. This is likely caused by incorrect HTML markup, for example nesting block-level elements inside <p>, or missing <tbody>. Bailing hydration and performing full client-side render.

Upvotes: 2

Views: 2575

Answers (2)

tony19
tony19

Reputation: 138286

Nuxt normally includes the Vue runtime only (excludes the compiler) as an optimization that reduces the build size by ~10KB, as most users employ precompiled templates (e.g., via single file components). The Vue runtime-only build emits the warning you're observing when in-DOM or string templates are used at runtime.

Since your app requires string templates at runtime, you'll need to configure Nuxt to use the Vue build that includes the compiler:

// nuxt.config.js
export default {
  build: {
    extend(config) {
      config.resolve.alias.vue = 'vue/dist/vue.common'
    }
  },
}

Upvotes: 3

muka.gergely
muka.gergely

Reputation: 8329

The snippet below shows how <component :is="dynamicComponent"></component> works.

  • 2 components are registered to Vue (globally)
  • on the click of a button, the :is binding is updated with one of the registered component names
  • the components themselves are emitting an event back to the parent on the click of a button

Vue.component('Comp1', {
  template: `
    <div>
      COMPONENT 1<br />
      <button
        @click="() => $emit('clicked', 1)"
      >
        Click 1
      </button>
    </div>
  `
})

Vue.component('Comp2', {
  template: `
    <div>
      COMPONENT 2<br />
      <button
        @click="() => $emit('clicked', 2)"
      >
        Click 2
      </button>
    </div>
  `
})

new Vue({
  el: "#app",
  data() {
    return {
      dynamicComponent: 'Comp1'
    }
  },
  methods: {
    toggleComponent() {
      if (this.dynamicComponent === 'Comp1') {
        this.dynamicComponent = 'Comp2'
      } else {
        this.dynamicComponent = 'Comp1'
      }
    },
    handleClicked(id) {
      console.log('click in comp', id)
    }
  },
  template: `
    <div>
      <button
        @click="toggleComponent"
      >
        SWITCH COMPONENT
      </button>
      <br />
      <component
        :is="dynamicComponent"
        @clicked="(id) => handleClicked(id)"
      ></component>
    </div>
  `
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app"></div>

Upvotes: 0

Related Questions