Vue.js - 模块构建失败:SyntaxError:意外的令牌

时间:2017-07-03 08:31:43

标签: vue.js vue-loader

我有一个Vue.js项目,它在几分钟前正常工作。当npm run build停止工作时,我正在尝试添加一小段新功能,您将在下面看到Syntax Error。我花了很多时间阅读它,但在我看来,没有给出Unexpected token实际上在哪里的线索,除了它在App.vue中。

我怀疑我最终可能只是通过取出代码直到我弄清楚它在窒息的方式才能正常工作,但是处理这些错误消息的首选方法是什么?它们似乎没有帮助,每次得到Syntax Error时拉出代码要比知道错误的位置要快得多。

| building for production...
Starting to optimize CSS...
Processing css/app.b78de1b1e52d045850f3f8ef25eab789.css...
Processed css/app.b78de1b1e52d045850f3f8ef25eab789.css, before: 2077, after: 2009, ratio: 96.73%
Hash: 463db738399a4df0bc89
Version: webpack 2.6.1
Time: 7211ms
                                           Asset       Size  Chunks             Chunk Names
                  js/app.46d986e313fa2c015cd0.js    5.62 kB       0  [emitted]  app
               js/vendor.bf7e840e23d2fcdbebe0.js     141 kB       1  [emitted]  vendor
             js/manifest.c323c0be7462a1c8da87.js    1.51 kB       2  [emitted]  manifest
    css/app.b78de1b1e52d045850f3f8ef25eab789.css    2.01 kB       0  [emitted]  app
              js/app.46d986e313fa2c015cd0.js.map      26 kB       0  [emitted]  app
css/app.b78de1b1e52d045850f3f8ef25eab789.css.map    4.13 kB       0  [emitted]  app
           js/vendor.bf7e840e23d2fcdbebe0.js.map     974 kB       1  [emitted]  vendor
         js/manifest.c323c0be7462a1c8da87.js.map    14.6 kB       2  [emitted]  manifest
                        ..\..\templates\app.html  598 bytes          [emitted]

ERROR in ./~/vue-loader/lib/template-compiler?{"id":"data-v-59c95520"}!./~/vue-loader/lib/selector.js?type=template&index=0!./src/App.vue
Module build failed: SyntaxError: Unexpected token (72:13)
    at Parser.pp$4.raise (C:\path_to_project\client\node_modules\vue-template-es2015-compiler\buble.js:2231:15)
    at Parser.pp.unexpected (C:\path_to_project\client\node_modules\vue-template-es2015-compiler\buble.js:613:10)
    at Parser.pp.expect (C:\path_to_project\client\node_modules\vue-template-es2015-compiler\buble.js:607:28)
    at Parser.parseObj (C:\path_to_project\client\node_modules\vue-template-es2015-compiler\buble.js:3871:16)
    at Parser.pp$3.parseExprAtom (C:\path_to_project\client\node_modules\vue-template-es2015-compiler\buble.js:1815:19)
    at Parser.parseExprAtom (C:\path_to_project\client\node_modules\vue-template-es2015-compiler\buble.js:3800:24)
    at Parser.pp$3.parseExprSubscripts (C:\path_to_project\client\node_modules\vue-template-es2015-compiler\buble.js:1725:21)
    at Parser.pp$3.parseMaybeUnary (C:\path_to_project\client\node_modules\vue-template-es2015-compiler\buble.js:1702:19)
    at Parser.pp$3.parseExprOps (C:\path_to_project\client\node_modules\vue-template-es2015-compiler\buble.js:1647:21)
    at Parser.pp$3.parseMaybeConditional (C:\path_to_project\client\node_modules\vue-template-es2015-compiler\buble.js:1630:21)
    at Parser.pp$3.parseMaybeAssign (C:\path_to_project\client\node_modules\vue-template-es2015-compiler\buble.js:1607:21)
    at Parser.pp$3.parsePropertyValue (C:\path_to_project\client\node_modules\vue-template-es2015-compiler\buble.js:2008:89)
    at Parser.parseObj (C:\path_to_project\client\node_modules\vue-template-es2015-compiler\buble.js:3895:14)
    at Parser.pp$3.parseExprAtom (C:\path_to_project\client\node_modules\vue-template-es2015-compiler\buble.js:1815:19)
    at Parser.parseExprAtom (C:\path_to_project\client\node_modules\vue-template-es2015-compiler\buble.js:3800:24)
    at Parser.pp$3.parseExprSubscripts (C:\path_to_project\client\node_modules\vue-template-es2015-compiler\buble.js:1725:21)
    at Parser.pp$3.parseMaybeUnary (C:\path_to_project\client\node_modules\vue-template-es2015-compiler\buble.js:1702:19)
    at Parser.pp$3.parseExprOps (C:\path_to_project\client\node_modules\vue-template-es2015-compiler\buble.js:1647:21)
    at Parser.pp$3.parseMaybeConditional (C:\path_to_project\client\node_modules\vue-template-es2015-compiler\buble.js:1630:21)
    at Parser.pp$3.parseMaybeAssign (C:\path_to_project\client\node_modules\vue-template-es2015-compiler\buble.js:1607:21)
    at Parser.pp$3.parseExprList (C:\path_to_project\client\node_modules\vue-template-es2015-compiler\buble.js:2175:22)
    at Parser.pp$3.parseSubscripts (C:\path_to_project\client\node_modules\vue-template-es2015-compiler\buble.js:1751:35)
 @ ./src/App.vue 8:2-170
 @ ./src/main.js

这是App.vue:

<template>
  <div id="app">
    <div id="toolbar" v-on-clickaway="disableSongToolbar">
      <div id="toolbar__left">
        <a class="ui-text toolbar__option" href="/">Rhymecraft</a>
        <div class="ui-text toolbar__option"
             :class="{ toolbar__option_active: songToolbarActive }"
             @click="toggleSongToolbarDropdown()">
          Song
        </div>
        <div class="ui-text toolbar__option">Line</div>
        <div class="ui-text toolbar__option">Help</div>
      </div>
      <div id="toolbar__right">
        <a class="ui-text toolbar__option" href="/logout">Log out</a>
      </div>
    </div>
    <div id="toolbar-dropdowns">
      <div id="toolbar-dropdowns__song" v-show="songToolbarActive">
        <div class="ui-text toolbar__option toolbar-dropdown-option toolbar-dropdown-not-last-option"
             @click="createNewSong">Create new song</div>
        <div class="ui-text toolbar__option toolbar-dropdown-option"
            @click="displayListOfUsersSongs">Load song</div>
        <div class="ui-text toolbar__option toolbar-dropdown-option"
             v-if="song.hasOwnProperty('id')"
            @click="displayConfirmDeleteSong = true">Delete current song</div>
      </div>
    </div>
    <div id="modals" :class="{ modals-active: modalActive }">
      <div id="song-loader" v-show="displaySongLoader">
        <div id="song-loader-header" class="ui-text">Load Song</div>
        <div class="ui-text song-loader__item song-loader__selectable-item" v-for="song in songs" @click="loadSong(song.id)">{{ song.name }}</div>
        <div class="ui-text song-loader__item" v-if="songs.length === 0 || !songs[0].hasOwnProperty('id')">You do not have any songs.</div>
        <div id="song-loader__cancel" class="ui-text" @click="displaySongLoader = false">Cancel</div>
      </div>
      <div id="confirm-delete-song" v-show="displayConfirmDeleteSong">
        <div id="confirm-delete-song__header" class="ui-text">Delete Song</div>
        <div id="confirm-delete-song__cancel" class="ui-text" @click="displayConfirmDeleteSong = false">Cancel</div>
        <div id="confirm-delete-song__spacer"></div>
        <div id="confirm-delete-song__confirm" class="ui-text" @click="deleteCurrentSong">Confirm</div>
      </div>
    </div>
    <div id="song-area">
      <div id="song">
        <div v-for="line in song.lines" class="song-line">
          <div v-for="spanOfTime in line.spansOfTime"
               class="ui-text span-of-time span-of-time--4"
               :id="spanOfTime.id"
               @click="currentlySelectedSpanOfTime = spanOfTime.id; console.log(spanOfTime.id)">&nbsp;</div>
        </div>
      </div>
    </div>
    <router-view></router-view>
  </div>
</template>

<script>
import { mixin as clickaway } from 'vue-clickaway'

export default {
  name: 'app',
  mixins: [ clickaway ],
  data: function () {
    return {
      songToolbarActive: false,
      displaySongLoader: false,
      song: [],
      songs: [],
      displayConfirmDeleteSong: false,
      currentlySelectedSpanOfTime: -1
    }
  },
  computed: {
    modalActive: function () {
      if (this.displaySongLoader) {
        return true
      }
    }
  },
  methods: {
    toggleSongToolbarDropdown: function () {
      this.songToolbarActive = !this.songToolbarActive
    },
    disableSongToolbar: function () {
      if (this.songToolbarActive) {
        this.songToolbarActive = false
      }
    },
    createNewSong: function () {
      this.$http.post('/song/create').then(response => {
        this.song = response.data.song
      }, response => {
        // error callback
      })
    },
    displayListOfUsersSongs: function () {
      this.$http.get('/songs').then(response => {
        this.songs = response.data.songs
        this.displaySongLoader = true
      }, response => {
        // error callback
      })
    },
    loadSong: function (songId) {
      this.displaySongLoader = false
      this.$http.get('/song/' + songId).then(response => {
        this.song = response.data.song
      }, response => {
        this.song = []
      })
    },
    deleteCurrentSong: function () {
      this.displayConfirmDeleteSong = false
      this.$http.post('/song/' + this.song.id + '/delete').then(response => {
        this.song = []
      }, response => {
      })
    }
  }
}
</script>

<style>
html, body {
  height: 100%;
}
div#modals {
  position: absolute;
  text-align: center;
  width: 100%;
  height: 100%;
  display: flex;
}
div.modals-active {
  z-index: 1;
}
div#song-loader {
  width: 300px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  margin: auto;
  border: 1px solid rgb(85, 85, 85);
}
div#song-loader-header {
  padding: 5px 0px;
  background-color:rgb(60,63,65);
}
div.song-loader__item {
  background-color: beige;
  padding: 10px;
  color: rgb(60, 60, 60);
}
div.song-loader__selectable-item:hover {
  background-color: rgb(230, 230, 190);
}
div#song-loader__cancel {
  padding: 5px 0px;
}
div#song-area {
  height: 100%;
}
div#song {
  width: 608px;
  height: 30px;
  margin: auto;
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
}
div.span-of-time {
  background-color: white;
  min-height: 29px;
  display: inline-block;
  border-right: 1px solid rgb(200,200,200);
}
div.span-of-time--4 {
  width: 37px;
}
div#app {
  height: 100%
}
div#toolbar {
  border-bottom: 1px solid #282828;
  box-shadow: 0px 1px 1px rgb(85,85,85);
}
div#toolbar__left {
  display: inline-block;
}
div#toolbar__right {
  display: inline-block;
  float: right;
}
.ui-text {
  color: #BBBBBB;
  font-size: 13px;
  text-decoration: none;
  font-family: 'Martel Sans', sans-serif;
  cursor: default;

  /* noselect */
    -webkit-touch-callout: none; /* iOS Safari */
    -webkit-user-select: none; /* Safari */
     -khtml-user-select: none; /* Konqueror HTML */
       -moz-user-select: none; /* Firefox */
        -ms-user-select: none; /* Internet Explorer/Edge */
            user-select: none; /* Non-prefixed version, currently
                                  supported by Chrome and Opera */
}
div#toolbar-dropdowns {
  position: absolute;
  z-index: 2;
}
.toolbar__option {
  display: inline-block;
  height: 25px;
  padding: 2px 5px 0px 5px;
}
.toolbar__option:hover {
  color: rgb(225,225,225);
  cursor: pointer;
}
div.toolbar__option_active {
  background-color: rgb(75,110,175);
}
div#toolbar-dropdowns__song {
  margin-left: 86px;
  width: 190px;
  border: 1px solid dimgray;
}
div.toolbar-dropdown-not-last-option {
  border-bottom: 1px solid dimgray;
}
div.toolbar-dropdown-option {
  cursor: default;
  width: 181px;
  display: inline-block;
  font-size: 12px;
}
div.toolbar-dropdown-option:hover {
  background-color: rgb(75,110,175);
}
.noselect {
  -webkit-touch-callout: none; /* iOS Safari */
    -webkit-user-select: none; /* Safari */
     -khtml-user-select: none; /* Konqueror HTML */
       -moz-user-select: none; /* Firefox */
        -ms-user-select: none; /* Internet Explorer/Edge */
            user-select: none; /* Non-prefixed version, currently
                                  supported by Chrome and Opera */
}
</style>

更新:我通过删除代码直到npm run build再次工作才发现错误。问题是我创建了一个条件类,其名称中包含一个破折号,但没有用单引号包围类名。所以我没有:class="{ 'modals-active': modalActive }"而是:class="{ modals-active: modalActive }"

但是,我没有问这个问题来解决这个特殊问题,而是知道是否有任何方法可以使用这些错误消息来更快地解决问题。实际问题出现在.vue模板文件的第29行,但错误消息似乎表明错误在第72行。

1 个答案:

答案 0 :(得分:0)

我遇到了类似的问题,结果是这个小代码片段:

item = {
  ...item,
  ...this.files[file]
};

我最好的猜测是 webpack 不喜欢 ES2018 中引入的对象扩展运算符。