SyntaxError: Unexpected token 'const' (with Vue, Karma, Webpack, PhantomJS)

Posted

技术标签:

【中文标题】SyntaxError: Unexpected token \'const\' (with Vue, Karma, Webpack, PhantomJS)【英文标题】:SyntaxError: Unexpected token 'const' (with Vue, Karma, Webpack, PhantomJS)SyntaxError: Unexpected token 'const' (with Vue, Karma, Webpack, PhantomJS) 【发布时间】:2017-04-06 10:32:15 【问题描述】:

我有一个或多或少的香草 Laravel + Vue.js 应用程序,我正在尝试做一些 JS testing with Karma and Jasmine。如果我尝试在测试中使用 () => 样式函数或 const 之类的关键字,它们会因 Unexpected token 错误而失败,但是,我使用 import 关键字没有问题,我能够毫无问题地转译和处理 .vue 文件。

一个微不足道的断言,如

expect(true).toBe(true);

似乎工作正常(见最后一行)

$ ./node_modules/karma/bin/karma start
22 11 2016 11:09:23.250:INFO [karma]: Karma v1.3.0 server started at http://localhost:9876/
22 11 2016 11:09:23.254:INFO [launcher]: Launching browser PhantomJS with unlimited concurrency
22 11 2016 11:09:23.263:INFO [launcher]: Starting browser PhantomJS
22 11 2016 11:09:24.025:INFO [PhantomJS 2.1.1 (Mac OS X 0.0.0)]: Connected on socket /#U1dCZ7i3UtsC-M3_AAAA with id 84458811
PhantomJS 2.1.1 (Mac OS X 0.0.0): Executed 1 of 1 SUCCESS (0.004 secs / 0.002 secs)

那么,如果我在我的测试函数中添加一个简单的const 声明

const myVar = 1
expect(true).toBe(true);

我收到一个错误:

$ ./node_modules/karma/bin/karma start
22 11 2016 11:10:00.741:INFO [karma]: Karma v1.3.0 server started at http://localhost:9876/
22 11 2016 11:10:00.745:INFO [launcher]: Launching browser PhantomJS with unlimited concurrency
22 11 2016 11:10:00.752:INFO [launcher]: Starting browser PhantomJS
22 11 2016 11:10:01.659:INFO [PhantomJS 2.1.1 (Mac OS X 0.0.0)]: Connected on socket /#Gwh8ywcLStrKf-ljAAAA with id 78654911
PhantomJS 2.1.1 (Mac OS X 0.0.0) ERROR
  SyntaxError: Unexpected token 'const'
  at tests/unit/Example.spec.js:165

改为,如果我尝试导致语法错误

const  = 1   // syntax error
expect(true).toBe(true);

然后 Babel 抱怨(在第一行,在 Karma 或 PhantomJS 启动之前)

22 11 2016 11:07:00.079:ERROR [preprocessor.babel]: /Users/crcarter/Software/CropPlanning/cps-php/resources/assets/js/tests/unit/Example.spec.js: Unexpected token (8:15)
 at /Users/crcarter/Software/CropPlanning/cps-php/resources/assets/js/tests/unit/Example.spec.js
22 11 2016 11:07:00.090:INFO [karma]: Karma v1.3.0 server started at http://localhost:9876/
22 11 2016 11:07:00.091:INFO [launcher]: Launching browser PhantomJS with unlimited concurrency
22 11 2016 11:07:00.101:INFO [launcher]: Starting browser PhantomJS
22 11 2016 11:07:00.986:INFO [PhantomJS 2.1.1 (Mac OS X 0.0.0)]: Connected on socket /#9Y6QLVxtJ57qRrgDAAAA with id 56249014
PhantomJS 2.1.1 (Mac OS X 0.0.0) ERROR
  You need to include some adapter that implements __karma__.start method!

这似乎暗示 Example.spec.js 文件正在被 Babel 解析/转译,但转译后的版本并未正确传送到浏览器,即使 Example.vue 文件似乎已正确传送。

我该怎么做才能让const() => 之类的东西在我的测试中起作用?谢谢。

以下是相关文件:

resources/assets/js/components/Example.vue
resources/assets/js/tests/unit/Example.spec.js
karma.conf.js                             
package.json

// Example.vue
<template>
    <div class="container">
    </div>
</template>

<script>
    export default 
        mounted() 
            console.log('Component ready.')
        ,
        data() 
            return  input: '# Hello!' 
        
    
</script>

// Example.spec.js
import Example from '../../components/Example.vue';

describe('Example', function () 
    it('should set correct default data', function () 

        const myVar = 1

        // trivial assertions
        expect(true).toBe(true);
    );
);

// karma.conf.js
var path = require('path')
var basePath = './resources/assets/js/';

module.exports = function(config) 
    config.set(

        frameworks: ['jasmine'],
        port: 9876,
        logLevel: config.LOG_INFO,
        autoWatch: true,
        browsers: ['PhantomJS'],
        singleRun: true,
        basePath: basePath,

        webpack: 
            resolve: 
                extensions: ['', '.js', '.vue'],
                fallback: [path.join(__dirname, 'node_modules')],
            ,
            resolveLoader: 
                fallback: [path.join(__dirname, 'node_modules')]
            ,
            module: 
                loaders: [
                   test: /\.vue$/, loader: 'vue' ,
                   test: /\.js$/,  loader: 'babel',
                    include: basePath,
                  
                ]
            
        ,

        webpackMiddleware: 
            noInfo: true,
            stats: 'errors-only'
        ,

        files: [
             pattern: 'tests/**/*.spec.js', watched: false ,
        ],

        exclude: [],

        preprocessors: 
            'app.js': ['webpack', 'babel'],
            'tests/**/*.spec.js': [ 'babel', 'webpack' ]
        ,

    )


还有package.json


  "private": true,
  "scripts": 
    "prod": "gulp --production",
    "dev": "gulp watch"
  ,
  "devDependencies": 
    "bootstrap-sass": "^3.3.7",
    "gulp": "^3.9.1",
    "jquery": "^3.1.0",
    "laravel-elixir": "^6.0.0-11",
    "laravel-elixir-vue-2": "^0.2.0",
    "laravel-elixir-webpack-official": "^1.0.2",
    "lodash": "^4.16.2",
    "vue": "^2.0.1",
    "vue-resource": "^1.0.3"
  ,
  "dependencies": 
    "jasmine-core": "^2.5.2",
    "karma": "^1.3.0",
    "karma-babel-preprocessor": "^6.0.1",
    "karma-chrome-launcher": "^2.0.0",
    "karma-firefox-launcher": "^1.0.0",
    "karma-jasmine": "^1.0.2",
    "karma-phantomjs-launcher": "^1.0.2",
    "karma-webpack": "^1.8.0"
  

【问题讨论】:

请尝试expect(true).to.equal(true); 在karma-babel-preprocessor docs 中它说:“从 Babel 6.0 开始,你需要告诉 Babel 要使用哪些功能”我不使用 webpack,但我看不到你在任何地方设置预设在您显示的代码中。 就像 craig 说的,babel 有不同阶段的 es6 支持,尝试在你的 .babelrc 中使用 es2015+stage-3,这种组合在我的情况下可以很好地转换。 感谢 cmets @craig_h 和 PanJunjie。我最终能够创建一个工作配置。如果您好奇,请参阅我的答案以了解详细信息。 【参考方案1】:

@craig_h 和 @PanJunjie 的 cmets 让我走上了查看 karma-babel-preprocessor 配置的轨道,这让我找到了 karma-webpack 的配置。我仍然不确定是什么导致了最初的问题,但我的 Karma 的 webpack 配置似乎不正确或不完整,并且默默地失败了。我通过

添加了babel-loaderbabel-preset-es2015
yarn add babel-loader babel-preset-es2015

然后我重新整理并清理了我的karma.conf.js

module.exports = function(config) 

    config.set(

        singleRun: false, // false => watch for changes and rerun tests
        autoWatch: true, // enable / disable watching files & then run tests

        frameworks: ['jasmine'],
        browsers: ['PhantomJS'],

        // Options: LOG_DISABLE, LOG_ERROR, LOG_WARN, LOG_INFO, LOG_DEBUG
        logLevel: config.LOG_INFO,

        basePath: './resources/assets/js/',

        files: [
             pattern: 'tests/**/*.spec.js', watched: false ,
        ],

        // how to process files before serving them to the browser for testing
        preprocessors: 
            'app.js': ['webpack'],
            'tests/**/*.spec.js': ['webpack'],
        ,

        webpack: 
            module: 
                loaders: [
                     test: /\.vue$/, loader: 'vue' ,
                     test: /\.js$/,
                      loader: 'babel-loader',
                      exclude: /node_modules/,
                      query:  presets: ['es2015'] 
                    
                ]
            ,
            // make sure to use the stand-alone version of Vue
            resolve: 
                alias: vue: 'vue/dist/vue.js'
            
        ,

        webpackMiddleware: 
          noInfo: true,
          stats: 'errors-only'
        
    );
;

我的package.json 现在看起来像这样:


  "private": true,
  "scripts": 
    "prod": "gulp --production",
    "dev": "gulp watch"
  ,
  "devDependencies": 
    "bootstrap-sass": "^3.3.7",
    "gulp": "^3.9.1",
    "jquery": "^3.1.0",
    "laravel-elixir": "^6.0.0-11",
    "laravel-elixir-vue-2": "^0.2.0",
    "laravel-elixir-webpack-official": "^1.0.2",
    "lodash": "^4.16.2",
    "vue": "^2.0.1",
    "vue-resource": "^1.0.3"
  ,
  "dependencies": 
    "babel-loader": "^6.2.8",
    "babel-preset-es2015": "^6.18.0",
    "jasmine-core": "^2.5.2",
    "karma": "^1.3.0",
    "karma-babel-preprocessor": "^6.0.1",
    "karma-chrome-launcher": "^2.0.0",
    "karma-firefox-launcher": "^1.0.0",
    "karma-jasmine": "^1.0.2",
    "karma-phantomjs-launcher": "^1.0.2",
    "karma-webpack": "^1.8.0"
  

有了这些,我现在可以使用 ES2015 的所有优点,例如 const() =&gt; 。很抱歉回答我自己的问题,但我希望这可以帮助遇到类似问题的其他人。

【讨论】:

您可以随时回答自己的问题!这有点晚了,但我怀疑这是因为 const 是 ES2015,而 PhantomJS 还不支持这一点(github.com/ariya/phantomjs/issues/14506)。在被 PhantomJS 执行之前,Babel 可能会将其编译为更兼容的 javascript【参考方案2】:

我遇到了类似的问题(虽然不完全相同;您的配置非常具体)。我还使用了 Vue、karma、webpack 和 phantomjs(在 vue-Webpack 模板中配置)。

但是,我的问题是我在导入到我的应用程序的帮助文件中定义了const。当我在该文件中将const 更改为var 时,测试能够运行。(const 是否用于已经在src 目录中的其他文件并不重要)。

当我将此帮助文件移动到我的 src 文件夹或其子目录之一时,此问题已得到解决。我太新手了,不知道为什么这解决了问题,但我猜 babel 没有配置为在根文件夹中工作,并且只指向 src 文件夹。

希望这对其他人也有帮助。

【讨论】:

【参考方案3】:

除了 RyanQuey 的评论:他是对的。默认的 Vue + Webpack CLI 设置仅包括某些要由 babel-loader 处理的上下文。查看 build/webpack.base.conf.js ,然后查看 JS 文件的模块规则。您可以看到仅包含 src、test 和 node_modules/webpack-dev-server/client 路径(在撰写本文时)。

【讨论】:

以上是关于SyntaxError: Unexpected token 'const' (with Vue, Karma, Webpack, PhantomJS)的主要内容,如果未能解决你的问题,请参考以下文章

求教php运行时出错:Parse error: syntax error, unexpected T_STRING, expecting T_FUNCTION 。。。

Import Unexpected identifier + SyntaxError: Unexpected string

js动态加载的a标签的onclick事件参数传递,一直报Uncaught SyntaxError: Invalid or unexpected token

解析错误:语法错误,意外的“未设置”(T_UNSET)

SyntaxError: unexpected EOF while parsing

获取 MongoDB 错误 - SyntaxError: Unexpected token?