解決vue-cli element-ui打包報錯Unexpected token: operator (>)

煲煲菜發表於2017-06-20

1.問題描述

我vue-cli寫了專案,介面都是用element-ui寫的,打包時報錯:

ERROR in assets/js/0.498ce690b229694d8858.js from UglifyJs
Unexpected token: operator (>) [./~/element-ui/src/mixins/emitter.js:2,0][assets/js/0.498ce690b229694d8858.js:3947,32]

2.問題理解

我理解了一下報錯資訊:

報錯說有一個錯誤在打包後的檔案中:assets/js/0.498ce690b229694d8858.js
錯誤的原因是:Unexpected token: operator (>),即:不能識別操作符(”>”大於號)
原始檔出錯地方是:element-ui/src/mixins/emitter.js2行第0
打包檔案出錯地方:assets/js/0.498ce690b229694d8858.js3947行第32

於是我找到兩個檔案出錯的程式碼一看,發現程式碼是一樣的!

//element-ui/src/mixins/emitter.js
function broadcast(componentName, eventName, params) {
  this.$children.forEach(child => {//第2行
    var name = child.$options.componentName;

    if (name === componentName) {
      child.$emit.apply(child, [eventName].concat(params));
    } else {
      broadcast.apply(child, [componentName, eventName].concat([params]));
    }
  });
}
//assets/js/0.498ce690b229694d8858.js : 
function broadcast(componentName, eventName, params) {
  this.$children.forEach(child => {//第3947行,第32列是“=”
    var name = child.$options.componentName;

    if (name === componentName) {
      child.$emit.apply(child, [eventName].concat(params));
    } else {
      broadcast.apply(child, [componentName, eventName].concat([params]));
    }
  });
}

this.$children.forEach(child => {});中的=>是es6的語法。但是現在很多瀏覽器不完成支援es6語法,所以才需要在打包過程中轉換成es5語法。

assets/js/0.498ce690b229694d8858.js是打包的結果,這個檔案是會放在瀏覽器執行的,如果瀏覽器不支援es6語法,那程式碼就會出錯。

所以npm run build報出錯誤資訊,也是合理的,如果你不理會這個報錯資訊,把程式碼拿取瀏覽器執行,就會出錯。

3.解決案例:vue-select

於是我很清楚,需要找到一種辦法,能夠把原始檔的es6語法的程式碼轉換成es5語法的程式碼。最後我找到了vue-select的一個issue討論是比較有幫助的:https://github.com/sagalbot/v…

This is a bug (#57, #69) that will be fixed in the next release – essentially babel doesn`t get applied to the mixins in src/mixins/, so they are not transpiled to ES5. The next release will be precompiled so that dev`s don`t have to modify the build process.

What`s your build process? If you are using webpack, you can configure babel-loader to run >on the files.

{

   test: /.js$/,
   loader: `babel`,
   include: [
     projectRoot + `/src`,
     projectRoot + `/test`,
     projectRoot + `/node_modules/vue-select`
   ]

}

I`m using the latest webpack template for vue-cli. In case anyone else wants to know >exactly where I put that, I updated the webpack.base.config.js file, this way:

{

   test: /.js$/,
   loader: `babel`,
   include: [
       path.resolve(__dirname, `../config`),
       path.resolve(__dirname, `../build`),
       path.resolve(__dirname, `../src`),
       path.resolve(__dirname, `../node_modules/vue-select`),
     ]

}

原文大概意思是:在一個專案中依賴了vue-select庫,打包時會報錯:Unexpected token punc «(», expected punc «:»,原因是babel沒有把node_modules/vue-select目錄下的js檔案轉換成es5語法。於是就配置了一下,就解決了。

3.參考解決自己的問題

我在自己專案中的webpack.base.conf.js找到了類似的地方,並加入配置:

//webpack.base.conf.js:

var path = require(`path`)
var utils = require(`./utils`)
var config = require(`../config`)
var vueLoaderConfig = require(`./vue-loader.conf`)

function resolve (dir) {
  return path.join(__dirname, `..`, dir)
}

module.exports = {
  entry: {
    app: `./src/main.js`
  },
  output: {
    path: config.build.assetsRoot,
    filename: `[name].js`,
    publicPath: process.env.NODE_ENV === `production`
      ? config.build.assetsPublicPath
      : config.dev.assetsPublicPath
  },
  resolve: {
    extensions: [`.js`, `.vue`, `.json`],
    alias: {
      `vue$`: `vue/dist/vue.esm.js`,
      `@`: resolve(`src`)
    }
  },
  module: {
    rules: [
      {
        test: /.vue$/,
        loader: `vue-loader`,
        options: vueLoaderConfig
      },
      {
        test: /.js$/,
        loader: `babel-loader`,
        include: [
          resolve(`src`),
          resolve(`test`),
          resolve(`node_modules/element-ui/src/mixins/emitter.js`),//<------add
        ]
      },
      {
        test: /.(png|jpe?g|gif|svg)(?.*)?$/,
        loader: `url-loader`,
        options: {
          limit: 10000,
          name: utils.assetsPath(`img/[name].[hash:7].[ext]`)
        }
      },
      {
        test: /.(woff2?|eot|ttf|otf)(?.*)?$/,
        loader: `url-loader`,
        options: {
          limit: 10000,
          name: utils.assetsPath(`fonts/[name].[hash:7].[ext]`)
        }
      }
    ]
  }
}

如果您的vue-cli專案或webpack專案也遇到類似的錯誤,可以試試這樣解決。

感慨一下:

瞭解問題的本質比知道問題的答案重要
遇到問題需要抽絲剝繭地逐層分析

相關文章