Vue-loader: Vue fails after build: cannot find module vue-html-loader

Created on 15 Feb 2016  路  7Comments  路  Source: vuejs/vue-loader

Just upgraded to the latest version of the webpack build template (generated using vue-cli). Building doesn't seem to work anymore: after i run npm run build and test the generated html/css/javascript, I get this error in console:

Cannot find module "-!vue-html-loader!./../../node_modules/vue-loader/lib/selector.js?type=template&index=0!./Booking.vue"

All 7 comments

The error always seems to occur in the file that is the last entry in my routes file. Files below:

_routes.js_

import Vue from 'vue'
import Home from './content/Home.vue'
import Klimhal from './content/Klimhal.vue'
import About from './content/About.vue'
import Contact from './content/Contact.vue'
import Bedrijven from './content/Bedrijven.vue'
import Booking from './content/Booking.vue'
import Arrangementen from './overviews/Arrangementen.vue'
import Arrangement from './content/Arrangement.vue'
import Activities from './overviews/Activities.vue'
import Activity from './content/Activity.vue'


export default {
  '/': { 
    name: 'home',
    component: Home
  },

  '/over-ons': { 
    name: 'about',
    component: About 
  },

  '/contact': { 
    name: 'contact',
    component: Contact 
  },

  '/klimhal': { 
    name: 'klimhal',
    component: Klimhal 
  },

  '/bedrijven': { 
    name: 'bedrijven',
    component: Bedrijven 
  },

  '/activiteiten': { 
    name: 'activities',
    component: Activities 
  },

  '/activiteit/:name': { 
    name: 'activity',
    component: Activity 
  },

  '/arrangementen': { 
    name: 'arrangementen',
    component: Arrangementen 
  },

  '/arrangementen/:filter': { 
    name: 'arrangementen',
    component: Arrangementen 
  },

  '/arrangement/:name': { 
    name: 'arrangement',
    component: Arrangement 
  },

  '/boeken': {
    name: 'booking-home',
    component: Booking 
  },

  '/boeken/:step': {
    name: 'booking-step',
    component: Booking 
  }
}

_The offending file, content/Booking.vue:_

<template>
  <ar-carousel height-xs="40%" height-sm="40%" height="80%" :bg="banner"></ar-carousel>
  <div class="zone-bottom-edge"></div>

  <article class="shopping-cart">
    <h1 class="shelton">Jouw Ayers adventure!</h1>
    <p class="description">
      Hieronder een overzicht van jouw Ayers Rock Adventure. 
      Kies nu voordelig voor onze Combi Deals en profiteer van interessante kortingen!
    </p>

    <div class="steps">
      <a class="step" :class="{ 'step-active': (step === 1) }" v-link="{ path: '/boeken/1' }">1</a>
      <a class="step" :class="{ 'step-active': (step === 2) }" v-link="{ path: '/boeken/2' }">2</a>
      <a class="step" :class="{ 'step-active': (step === 3) }" v-link="{ path: '/boeken/3' }">3</a>
      <a class="step" :class="{ 'step-active': (step === 4) }" v-link="{ path: '/boeken/4' }">4</a>
    </div>

    <div class="cart-activities" v-if="(cartTotal === 0)">
      <div class="cart-empty" v-if="cartTotal === 0">
        Je hebt nog niks in je buidel. 
        <a v-link="{ path: '/arrangementen' }">Klik hier!</a>
      </div>
    </div>

    <div class="cart-activities" v-if="(cartTotal > 0 && step === 1)">
      <h3 class="shelton">Gekozen activiteiten</h3>

      <div class="cart-activity" v-for="activity in cartItems">
        <div class="row">
          <div class="no-padding-right col-xs-8">
            <span class="shelton cart-activity-title">{{ activity.item.title }}</span>
          </div>
          <div class="no-padding-left col-xs-4">
            <div class="shelton cart-activity-price">
              &euro; {{ activity.item._meta.price.value[0] }}<sup>{{ activity.item._meta.price.value[1] }}</sup>
            </div>
          </div>
        </div>
      </div>

      <div class="cart-activity no-bg">
        <div class="row">
          <div class="no-padding-right col-xs-10">
            <span class="shelton cart-activity-title">Aantal personen:</span>
          </div>
          <div class="no-padding-left col-xs-2">
            <input class="form-element" type="number" v-model="participants">
          </div>
        </div>
      </div>

      <div class="cart-activity no-margin-bottom">
        <div class="row">
          <div class="no-padding-right col-xs-6">
            <span class="shelton cart-activity-title">Activiteiten:</span>
          </div>
          <div class="no-padding-right col-xs-2">
            <div class="shelton cart-activity-price" style="color: #999">
              {{ participants }} &times;
            </div> 
          </div>
          <div class="no-padding-left col-xs-4">
            <div class="shelton cart-activity-price">
              &euro; {{ subtotal[0] }}<sup>{{ subtotal[1] }}</sup>
            </div>
          </div>
        </div>
      </div>

      <div class="cart-activity no-margin-top">
        <div class="row">
          <div class="no-padding-right col-xs-8">
            <span class="shelton cart-activity-title">Totaal:</span>
          </div>
          <div class="no-padding-left col-xs-4">
            <div class="shelton cart-activity-price">
              &euro; {{ total[0] }}<sup>{{ total[1] }}</sup>
            </div>
          </div>
        </div>
      </div>

      <div style="text-align: center; padding: 2em 0;">
        <a class="shelton alt-button" style="font-size: 1em; padding: .5em" @click="next">Stap 2 - kies datum &amp; tijd &raquo;</a>
      </div>
    </div>

    <div class="cart-datetime" v-if="(cartTotal > 0 && step === 2)">
      <h3 class="shelton">Datum &amp; tijd</h3>

      <div class="cart-date">
        <div class="row">
          <div class="col-xs-6">
            <select v-model="day" class="form-control" style="display: block">
              <option :value="day.value" v-for="day in days">{{ day.day }} {{ day.value }}</option>
            </select>
          </div>

          <div class="col-xs-6">
            <select v-model="month" class="form-control" style="display: block">
              <option value="1">januari</option>
              <option value="2">februari</option>
              <option value="3">maart</option>
              <option value="4">april</option>
              <option value="5">mei</option>
              <option value="6">juni</option>
              <option value="7">juli</option>
              <option value="8">augustus</option>
              <option value="9">september</option>
              <option value="10">oktober</option>
              <option value="11">november</option>
              <option value="12">december</option>
            </select>
          </div>
        </div>
      </div>

      <div class="cart-time">
        <div class="row" style="margin-top: 1em">
          <div class="col-xs-6">
            <select class="form-control" v-model="hour" style="display: block">
              <option :value="hrs" v-for="hrs in hours">{{ hrs }} uur</option>
            </select>
          </div>

          <div class="col-xs-6">
            <select class="form-control" v-model="minute" style="display: block">
              <option :value="min" v-for="min in minutes">{{ min }}</option>
            </select>
          </div>
        </div>
      </div>

      <div style="text-align: center; padding: 2em 0;">
        <a class="shelton alt-button" style="font-size: 1em; padding: .5em" @click="next">Stap 3 - Je gegevens &raquo;</a>
      </div>
    </div>

    <div class="cart-information" v-if="(cartTotal > 0 && step === 3)">
      <h3 class="shelton">Jouw gegevens</h3>

      <form class="form">
        <div class="form-group">
          <input type="text" class="form-control" v-model="info.name" placeholder="Naam">
        </div>

        <div class="form-group">
          <input type="email" class="form-control" v-model="info.emailAddress" placeholder="E-mailadres">
        </div>

        <div class="form-group">
          <input type="number" class="form-control" v-model="info.phoneNumber" placeholder="Telefoonnummer">
        </div>

        <div class="form-group">
          <input type="text" class="form-control" v-model="info.address1" placeholder="Adres">
        </div>

        <div class="form-group">
          <input type="text" class="form-control" v-model="info.postcode" placeholder="Postcode">
        </div>

        <div class="form-group">
          <input type="text" class="form-control" v-model="info.city" placeholder="Plaats">
        </div>

        <div class="form-group">
          <input type="text" class="form-control" v-model="info.companyName" placeholder="Bedrijf">
        </div>

        <div class="form-group">
          <textarea class="form-control" v-model="info.comments" placeholder="Opmerkingen" style="height: 80px"></textarea>
        </div>
      </form>

      <div style="text-align: center; padding: 2em 0;">
        <a class="shelton alt-button" style="font-size: 1em; padding: .5em" @click="next">Stap 4 - Overzicht &raquo;</a>
      </div>
    </div>

    <div class="cart-overview" v-if="(cartTotal > 0 && step === 4)">
      <h3 class="shelton">Overzicht van je boeking</h3>

      <div class="row">
        <div class="col-xs-4" style="font-weight: bold">Datum:</div>
        <div class="col-xs-8">{{ day }}-{{ month }}-{{ year }}</div>
      </div>

      <div class="row" style="margin-top: .5em">
        <div class="col-xs-4" style="font-weight: bold">Tijd:</div>
        <div class="col-xs-8">{{ hour }}:{{ (minute < 10 ? '0' + minute : minute) }}</div>
      </div>

      <div class="row" style="margin-top: .5em">
        <div class="col-xs-4" style="font-weight: bold">Deelnemers:</div>
        <div class="col-xs-8">{{ participants }}</div>
      </div>

      <div style="text-align: center; padding: 2em 0;">
        <a class="shelton alt-button" style="font-size: 1em; padding: .5em" @click="next">Direct boeken &raquo;</a>
      </div>

      <div class="row">
        <div class="col-xs-4" style="font-weight: bold">Naam:</div>
        <div class="col-xs-8">{{ info.name }}</div>
      </div>

      <div class="row" style="margin-top: .5em">
        <div class="col-xs-4" style="font-weight: bold">Adres:</div>
        <div class="col-xs-8">{{ info.address1 }}</div>
      </div>

      <div class="row" style="margin-top: .5em">
        <div class="col-xs-4" style="font-weight: bold">Postcode:</div>
        <div class="col-xs-8">{{ info.postcode }}</div>
      </div>

      <div class="row" style="margin-top: .5em">
        <div class="col-xs-4" style="font-weight: bold">Plaats:</div>
        <div class="col-xs-8">{{ info.city }}</div>
      </div>

      <div class="row" style="margin-top: .5em">
        <div class="col-xs-4" style="font-weight: bold">E-mailadres:</div>
        <div class="col-xs-8">{{ info.emailAddress }}</div>
      </div>

      <div class="row" style="margin-top: .5em; margin-bottom: 2em;">
        <div class="col-xs-4" style="font-weight: bold">Telefoon:</div>
        <div class="col-xs-8">{{ info.phoneNumber }}</div>
      </div>

      <div class="cart-activity" v-for="activity in cartItems">
        <div class="row">
          <div class="no-padding-right col-xs-8">
            <span class="shelton cart-activity-title">{{ activity.item.title }}</span>
          </div>
          <div class="no-padding-left col-xs-4">
            <div class="shelton cart-activity-price">
              &euro; {{ activity.item._meta.price.value[0] }}<sup>{{ activity.item._meta.price.value[1] }}</sup>
            </div>
          </div>
        </div>
      </div>

      <div class="cart-activity no-margin-bottom">
        <div class="row">
          <div class="no-padding-right col-xs-6">
            <span class="shelton cart-activity-title">Subtotaal:</span>
          </div>
          <div class="no-padding-right col-xs-2">
            <div class="shelton cart-activity-price" style="color: #999">
              {{ participants }} &times;
            </div> 
          </div>
          <div class="no-padding-left col-xs-4">
            <div class="shelton cart-activity-price">
              &euro; {{ subtotal[0] }}<sup>{{ subtotal[1] }}</sup>
            </div>
          </div>
        </div>
      </div>

      <div class="cart-activity no-margin-top">
        <div class="row">
          <div class="no-padding-right col-xs-8">
            <span class="shelton cart-activity-title">Totaal:</span>
          </div>
          <div class="no-padding-left col-xs-4">
            <div class="shelton cart-activity-price">
              &euro; {{ total[0] }}<sup>{{ total[1] }}</sup>
            </div>
          </div>
        </div>
      </div>

      <div style="text-align: center; padding: 2em 0;">
        <a class="shelton alt-button" style="font-size: 1em; padding: .5em" @click="next">Boek nu! &raquo;</a>
      </div>
    </div>

    <div class="cart-information" v-if="(cartTotal > 0 && step === 5)">
      <h3 class="shelton">Bedankt!</h3>

      <div style="text-align: center">
        <p>Hartelijk dank voor uw boeking. Binnen 24 uur ontvangt u per email een boekingsbevestiging van ons.</p>
      </div>

      <div style="text-align: center; padding: 2em 0">
        <a class="shelton alt-button" style="font-size: 1em; padding: .5em" @click="next">&laquo; Terug</a>
      </div>
    </div>
  </article>
</template>

<script>
  import arCarousel from '../components/ar-carousel.vue'
  import arSlider from '../components/ar-slider.vue'
  import arSlide from '../components/ar-slide.vue'
  import arMenu from '../components/ar-menu.vue'
  import arBanner from '../components/ar-banner.vue'
  import arButton from '../components/ar-button.vue'

  function valid(value) {
    return ((typeof value === 'string' && value.length > 0) || (typeof value === 'number' && !isNaN(value) && value > 0))
  }

  export default {
    methods: {
      next() {
        switch (this.step) {
          case 1:
            this.$cart.participants(this.participants)
            this.$route.router.go('/boeken/2')
            break;

          case 2:
            this.$cart.month(this.month)
            this.$cart.day(this.day)
            this.$cart.hour(this.hour)
            this.$cart.minutes(this.minutes)
            this.$route.router.go('/boeken/3')
            break;

          case 3:
            let err = false

            if (!valid(this.info.name)) {
              err = 'Gelieve uw naam in te vullen.'
            }

            if (err === false && !valid(this.info.address1)) {
              err = 'Gelieve uw adres in te vullen.'
            }

            if (err === false && !valid(this.info.postcode)) {
              err = 'Gelieve uw postcode in te vullen.'
            }

            if (err === false && !valid(this.info.city)) {
              err = 'Gelieve uw woonplaats in te vullen.'
            }

            if (err === false && !valid(this.info.emailAddress)) {
              err = 'Gelieve uw e-mailadres in te vullen.'
            }

            if (err === false && !valid(this.info.phoneNumber)) {
              err = 'Gelieve uw telefoonnummer in te vullen.'
            }

            if(err !== false) {
              return alert(err)
            }

            this.$cart.info(this.info)
            this.$route.router.go('/boeken/4')
            break;

          case 4:
            console.log('CART', this.$cart.json())
            this.$route.router.go('/boeken/5')
            break;

          case 5: 
            this.$cart.clear()
            this.$route.router.go('/')
            break;
        }
      }
    },

    computed: {
      json() {
        return this.$cart.json()
      },

      step() {
        return parseInt(this.$route.params.step || 1)
      },

      cartTotal() {
        return this.$cart.total()
      },

      cartItems() {
        return this.$cart.get()
      },

      subtotal() {
        let total = 0

        this.$cart.get().forEach((item) => {
          total += (parseInt(item.item._meta.price.value[0], 10) * 100)
          total += parseInt(item.item._meta.price.value[1], 10)
        })

        return total > 0 ? (total / 100).toFixed(2).split('.') : ['0', '00']
      },

      total() {
        let total = 0

        this.$cart.get().forEach((item) => {
          total += (parseInt(item.item._meta.price.value[0], 10) * 100)
          total += parseInt(item.item._meta.price.value[1], 10)
        })

        return total > 0 ? ( (total * this.participants) / 100).toFixed(2).split('.') : ['0', '00']
      },

      days() {
        const year = this.$cart.year()
        const start = new Date(year, (this.month - 1), 1)
        const end = new Date(year, this.month, 1)
        const length = Math.floor( (end - start) / 86400000 )
        const days = []

        for (let i = 1; i <= length; i++) {
          let weekday = new Date(year, this.month, i).getDay()

          switch (weekday) {
            case 0: weekday = 'Zondag'; break;
            case 1: weekday = 'Maandag'; break;
            case 2: weekday = 'Dinsdag'; break;
            case 3: weekday = 'Woensdag'; break;
            case 4: weekday = 'Donderdag'; break;
            case 5: weekday = 'Vrijdag'; break;
            case 6: weekday = 'Zaterdag'; break;
          }

          days.push({
            value: i,
            day: weekday
          })
        }

        return days
      },

      hours() {
        const hours = []
        for (let i = 10; i <= 22; i++) {
          hours.push( i )
        }

        return hours
      }
    },

    data() {
      return {
        banner: require('../images/banner-survival.png'),

        participants: JSON.stringify(JSON.parse(this.$cart.participants())),
        year: this.$cart.year(),
        month: this.$cart.month(),
        day: this.$cart.day(),
        hour: this.$cart.hour(),
        minute: this.$cart.minutes(),
        minutes: [ '00', '15', '30', '45' ],
        info: {
          name: this.$cart.info().name || '',
          address1: this.$cart.info().address1 || '',
          postcode: this.$cart.info().postcode || '',
          city: this.$cart.info().city || '',
          comments: this.$cart.info().comments || '',
          emailAddress: this.$cart.info().emailAddress || '',
          phoneNumber: this.$cart.info().phoneNumber || '',
          companyName: this.$cart.info().companyName || ''
        }
      }
    },

    components: {
      'ar-carousel': arCarousel,
      'ar-menu': arMenu,
      'ar-slider': arSlider,
      'ar-slide': arSlide,
      'ar-banner': arBanner,
      'ar-button': arButton
    }
  }
</script>

<style lang="stylus">
  .shopping-cart
    padding 10px 2em 100px 2em

    h1, h2, h3, h4 
      margin 0
      padding 0

    h1
      color #d73427
      font-size 1.8em
      text-align center
      margin-bottom .5em

    h3
      color #d73427
      font-size 1.3em
      margin 2em 0 1em 0
      text-align center

    p.description 
      color #441625
      text-align center
      line-height 1.5
      margin .1em 0
      padding 0
      font-size .9em

    div.steps
      display block 
      width 100%
      margin 1.5em 0
      text-align center
      position relative 
      z-index 10

      &:after 
        content ''
        display block 
        height 0 
        width 80%
        border-bottom 2px dotted #666
        position absolute
        top 15px
        left 10%
        z-index -1

      a.step 
        display inline-block
        width 30px
        height 30px
        line-height 30px
        border-radius 15px
        background-color #d67f78
        color white
        text-align center 
        margin 0 1.5em
        opacity 1
        position relative

        &.step-active 
          background-color #d73427

    .cart-activities
      display block 

    .cart-empty
      text-align center 
      font-size .9em 
      font-weight bold
      color #999

    .cart-activity
      display block
      margin-bottom .5em 
      background-color white
      border-radius 5px
      padding .5em 1em
      height auto

      &.no-bg
        margin 1em 0 0 0
        background-color #eee

      &.no-margin-top 
        margin 0 0 .5em 0
        border-top-left-radius 0
        border-top-right-radius 0

      &.no-margin-bottom 
        margin .5em 0 1px 0
        border-bottom-left-radius 0
        border-bottom-right-radius 0

      .cart-activity-price
        display block 
        height 28px 
        line-height 28px
        color #d73427
        font-size 1.2em
        text-align right

      .cart-activity-title
        display block 
        height auto 
        line-height 28px

      .form-element 
        display block
        border 2px solid #ccc
        border-radius 3px
        width 100%
        line-height 22px
        font-weight bold 
        text-align right
        outline none
        color #666
        padding 0 0
        background-color #eee


  .cart-bottom-edge
    display: block
    width: 110%
    height: 10px
    background-color: #efefef
    position: relative
    transform: rotate(-2deg)
    margin-left: -5%

    &:before
      position: absolute
      height: 22px
      width: 100%
      top: -21px
      left: 0
      background-image: url(../images/edge-grey-top.png)
      content: ''

  .no-padding 
    padding-left 0
    padding-right 0

  .no-padding-left 
    padding-left 0

  .no-padding-right
    padding-right 0
</style>

_Webpack config:_

var path = require('path')

module.exports = {
  entry: {
    app: [ 'bootstrap-loader', './src/main.js' ]
  },

  output: {
    path: path.resolve(__dirname, '../dist/static'),
    publicPath: '/static/',
    filename: '[name].js'
  },
  resolve: {
    extensions: ['', '.js', '.vue'],
    alias: {
      'src': path.resolve(__dirname, '../src')
    }
  },
  resolveLoader: {
    root: path.join(__dirname, 'node_modules')
  },
  module: {
    loaders: [
      { 
        test: /bootstrap-sass\/assets\/javascripts\//, 
        loader: 'imports?jQuery=jquery' 
      },

      {
        test: /\.vue$/,
        loader: 'vue'
      },
      {
        test: /\.js$/,
        loader: 'babel!eslint',
        exclude: /node_modules/
      },
      {
        test: /\.json$/,
        loader: 'json'
      },
      {
        test: /\.(png|jpg|gif|svg|woff2?|svg)$/,
        loader: 'url',
        query: {
          limit: 10000,
          name: '[name].[ext]?[hash:7]'
        }
      },
      { 
        test: /\.(ttf|eot)$/, 
        loader: 'file' 
      },
    ]
  },
  vue: {
    loaders: {
      js: 'babel!eslint'
    }
  },
  eslint: {
    formatter: require('eslint-friendly-formatter')
  }
}

@yyx990803 any suggestions? It's preventing me from shipping...

ping @yyx990803 ?

Have you tried doing a fresh npm install? This could be related to https://github.com/vuejs-templates/webpack/issues/41 which is fixed in the latest version of vue-loader.

I just did, even tried initiating a new project with vue-cli and copying all the source files.. I even tried building the thing on a different machine with a different OS (Ubuntu instead of OS X).

Closing (outdated)

Came here because I had somewhat the same issue after switching branches.. resolved it using npm install :sweat_smile: .

Was this page helpful?
0 / 5 - 0 ratings