19

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项目也遇到类似的错误,可以试试这样解决。

感慨一下:

了解问题的本质比知道问题的答案重要
遇到问题需要抽丝剥茧地逐层分析


煲煲菜
1.5k 声望155 粉丝

世上本没有bug,坑的人多了,也便成了bug