Separating script, style and template in Vue.js and Webpack

3.3k Views Asked by At

I'm creating a large scale application with amazing Vue and Webpack. I don't want to have .vue files since I want to separate them to something like comp.js, comp.pug and comp.styl

my comp.js will be:

export default {
    template: require('./comp.pug'),
    data: () => {
        return {
            compStyle: require('./comp.styl');
            message: 'Hello World!'
        }
    // ...
    },
}

my com.pug will be:

div#comp(v-bind:style="compStyle")
    h1.heading {{ message }}

And finally my comp.styl will be:

.heading
    color: #6E6E6E;
    background-color: #E6E6E6
    text-align: center

In first glance everything seems fine till I try using VueRouter and of course elements like <router-link /> or <router-view />!

Since I wont have any .vue file, I'd assume having alias: { 'vue$': 'vue/dist/vue.common.js' } in Webpack wont help me!

How can I overcome this issue?

BTW, that the error I get in the console is:

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


Update

Worth to mention that I have two entry files: One for whole application

import MainComp from './comp/main';

Vue.use(VueRouter);

new Vue(MainComp).$mount('#app');

And one for components (sub components are as above):

import Router from './route';
import SubComp1 from './sub1.comp'
import SubComp2 from './sub2.comp'

export default {
  template: require('./main.pug'),
  router: Router,
  components: {
    SubComp1,
    SubComp2
  }
}

My main.pug:

div
    | here goes the views
    router-view

And here is my route.js:

export const Router = new VueRouter({
  mode: 'history',
  routes: [
    { path: '/three', component: SubComp3 },
    { path: '/Four', component: SubComp4 },
    { path: '/', redirect: '/' }
  ]
})

So when I have alias: { 'vue$': 'vue/dist/vue.common.js' } added to my webpack, error(s) will be something else:

[Vue warn]: Error when rendering root instance

Uncaught TypeError: Cannot read property 'matched' of undefined

2

There are 2 best solutions below

1
On

Vue-loader compiles .vue files into render functions, if you are not using them then you are going to need to use the standalone-build which includes the template compiler. As far as I'm aware that is the only difference between the runtime and standalone builds, so I see no reason why using the alias for the standalone build would not work in your case.

Incidentally, .vue files can be split into multiple files. Take a look at the src imports section on this page, to see if it's something that would suit the requirements of your project

3
On

component.vue (with vue-loader):

<style src='./style.styl'></style>
<template src='./template.pug'></template>

Make sure, that loaders for *.styl, *.pug exist.

UPDATE: I'm forget, than you can do it like this (without vue-loader): component.js

import './style.styl'
import tmpl from './template.pug' // may be it will work

// if import doesn't work, then do it with string variable in this file or import
const tmpl = `
   h1 Hello world
`

export default {
   template: tmpl,
   data() {
      return {}
   }
}