How to configure Vue-router when using runtime-only Vue

Viewed 1084

I'm trying to use vue-router based on the examples, such as

let routes = [
    { path: '/',  component: MainComponent },
];

let router = new VueRouter({routes});

new Vue({  router  }).$mount('#app');

but I always get this error:

vue.runtime.esm.js:619 [Vue warn]: You are using the runtime-only build of Vue where the template compiler is not available.

Can I fix this by using the render function? I tried,

let routes = [];

But still fails.

3 Answers

Ok, I spent a half day on this and I finally got it working: vue-router + webpack + runtime-only vue.

This tutorial was the most helpful. What I learned:

If you use vue-cli, the vue version is in the webpack.base.conf.js

  • vue.esm.js will include the compiler
  • vue.runtime.esm.js will NOT include the compiler

If you want to use runtime, you must change your main.js. Do NOT use this

new Vue({
    el: '#app',
    router,
    template: '<App/>',      //  <== This is bad
    components: { App }
});

and instead DO use this

Vue.use(VueRouter);          // <== very important
new Vue({
    router,
    render(createElement) {
        return createElement(App);
    }
}).$mount('#app');

You can use either $mount or the el: with runtime. Both work, but the $mount gives you more flexibility. And of course the router is created the usual way

let routes = [
    { path: '/', component: MainComponent },    
];
let router = new VueRouter({ routes }); 

And if you are still seeing the error

[Vue warn]: You are using the runtime-only build of Vue

in the console, then make double sure that you never ever in your code use any templates with strings. Even inside your *.vue files, if you try to do

const Foo = { template: '<div>foo</div>' };

it will fail. Instead you must either use <template> tags, or else you must use createElement. Good luck!

It appears to be impossible to use the runtime, based on these two MREs (one with, one without runtime). If nothing else, you can use these snippets if you choose to post an issue on their github or the vue forums, or another answer can use them as a template to prove me incorrect. This assumes you're not using vue-cli. With vue-cli you need to opt-in to including the compiler in your builds. See https://cli.vuejs.org/config/#runtimecompiler and https://v2.vuejs.org/v2/guide/installation.html#Runtime-Compiler-vs-Runtime-only

Fails (console warning - vue runtime)

let routes = [
  {
    path: "",
    component: {
      render(h) {
        return h("div", "hello world");
      }
    }
  }
];

let router = new VueRouter({ routes });

new Vue({ router }).$mount("#app");
<script src="https://unpkg.com/vue/dist/vue.runtime.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<div id="app">
  <router-view></router-view>
</div>

Works (no console warning - full vue)

let routes = [
  {
    path: "",
    component: {
      render(h) {
        return h("div", "hello world");
      }
    }
  }
];

let router = new VueRouter({ routes });

new Vue({ router }).$mount("#app");
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<div id="app">
  <router-view></router-view>
</div>

The accepted solution is right in that you cannot use string template with runtime only Vue, and you have to implement the render function. However, if you want to render components at the top level instead of using router-view, you can get the matched component and render it manually:

const routes = [
  { path: '/about', component: About },
  { path: '/index', component: App },
  { path: "*", component: App }
]

new Vue({
  router,
  render: h => {
    return h(router.getMatchedComponents()[0])
  },
}).$mount('#app')
Related