【问题标题】:SyntaxError: 'import' and 'export' may appear only with 'sourceType: module' - GulpSyntaxError: 'import' 和 'export' 可能只出现在 'sourceType: module' 中 - Gulp
【发布时间】:2017-02-23 01:21:24
【问题描述】:

考虑以下两个文件:

app.js

import Game       from './game/game';
import React      from 'react';
import ReactDOM   from 'react-dom';

export default (absPath) => {
  let gameElement = document.getElementById("container");

  if (gameElement !== null) {
      ReactDOM.render(
          <Game mainPath={absPath} />,
          gameElement
      );
  }
}

index.js

import App from './src/app';

gulpfile.js

var gulp        = require('gulp');
var source      = require('vinyl-source-stream');
var browserify  = require('browserify');
var babelify    = require("babelify");
var watch       = require('gulp-watch');

gulp.task('make:game', function(){
  return browserify({
    entries: [
      'index.js'
    ]
  })
  .transform('babelify')
  .bundle()
  .pipe(source('index.js'))
  .pipe(gulp.dest('app/'));
});

错误:

gulp make:game
[13:09:48] Using gulpfile ~/Documents/ice-cream/gulpfile.js
[13:09:48] Starting 'make:game'...

events.js:154
      throw er; // Unhandled 'error' event
      ^
SyntaxError: 'import' and 'export' may appear only with 'sourceType: module'

这是什么错误?我做错了什么?

【问题讨论】:

  • this issue on GitHub. 使用 babelify 的较新版本的 Babel 似乎是个问题。
  • 就我而言,我没有使用 babelify,但仍然出现此错误。
  • 在我的例子中,当我尝试编译导入 TypeScript 文件的 JS 文件时,我在 browserify 和 babelify 中遇到了这个错误,例如从 "./foo" (foo.ts) 导入 * as Foo。修复方法是将 --extensions ".ts,.js" 传递给 babelify 转换(因此 babel 将在编译中包含 TS 文件)并将 --extension=.js --extension=.ts 传递给 browserify(因此 browserify 可以解析导入语句的文件路径)。请注意,babel --extensions 选项似乎没有记录在 babel 选项中 - 我发现了它here

标签: javascript gulp ecmascript-6 browserify babeljs


【解决方案1】:
    return browserify(jsConfig.src)
  .transform(babelify.configure({
    presets: ["@babel/preset-env"]
  }))
  .bundle()
  .on('error', function (e) {
    console.log(e.message);

    this.emit('end');
  })

为我工作。

【讨论】:

    【解决方案2】:

    ESLint 本身不支持这一点,因为这违反了规范。但是如果你使用 babel-eslint 解析器,那么在你的 eslint 配置文件中你可以这样做:

    {
        "parser": "babel-eslint",
        "parserOptions": {
            "sourceType": "module",
            "allowImportExportEverywhere": true
        }
    }
    
    

    文档参考:https://github.com/babel/babel-eslint#configuration

    从这里引用的答案:ignore eslint error: 'import' and 'export' may only appear at the top level

    【讨论】:

      【解决方案3】:

      我尝试了上述所有答案,但没有一个对我有用,我什至尝试使用 gulp-include / require syntax,它们既不是解决方案也不足以解决我的要求。

      这是我的要求。

      1. 将所有模块/文件打包成一个
      2. 保留所有 cmets/JSDocs
      3. 保留所有类型(如const example = (parameter: string) =&gt; {}
      4. 使用导入/导出语法

      列出要求的原因是因为我们需要一个存储库来将我们的共享功能、共享配置、共享类型和共享常量存储为 npm 包(使用 URL 安装)。在这种情况下,我们已经知道我们的项目都在使用 TypeScript,所以不需要将我们的共享模块编译成.js,我们还需要像其他包一样保留所有描述(JSDoc 和 Type 真的很有帮助)。

      到目前为止,我能做的最好的事情是使用browserifytsify。我无意中从here 找到了这个解决方法。

      browserify()
          .plugin(tsify, { target: 'es6' })
          .transform(babelify, { extensions: [ '.tsx', '.ts' ] })
      

      我仍在寻找一种方法来保留我们的内联类型和 cmets/JSDocs,但我相信这足以满足您的需要。

      【讨论】:

        【解决方案4】:

        如果你想在 npm 中通过 importrequire 方法使用任何东西到客户端,只需执行以下步骤

        1. 运行 npm install browserify babelify @babel/preset-env @babel/preset-react @babel/core es2015 --save-dev 安装所需的预设
        2. 将此代码添加到您的package.json
        "babel": {
          "presets": [
            "@babel/preset-env",
            "@babel/preset-react"
          ] 
        }
        
        1. /app 文件夹内创建一个名为dom_front.js 的文件,该文件要转换为客户端js。
        const ReactDOM  = require('react-dom')
        import React, {Component} from 'react' 
        export {Component,React,ReactDOM};
        

        这是模块和需求文件的混合导出数据。

        注意:别忘了安装 react-dom 和 react

        1. 使用browserify api-创建js文件如browserifyload.js和assets文件夹
        const browserify = require("browserify")
        const fs = require('fs')
        browserify("./dom_front.js", {
          debug : true,
          standalone: "util"
        }).transform(['babelify', { compact: false }], {
          global: true,                                  
          ignore: [/\/node_modules\/(?!@vizuaalog\/)/],     
          presets: [ 
            "@babel/preset-env",
            "@babel/preset-react"] 
          }).bundle().on('error', function (err) {
            console.log(err);  
          }).pipe(fs.createWriteStream('assets/mynpmmodule.js')).on('end', function(){
            console.log( 'finished writing the browserify file' );
          });
        
        1. 现在文件夹结构是
        app
        --dom_front.js
        --browserifyload.js
        --assets(folder)
        
        1. 运行/node_proj/app$ node browserifyload.js 或运行/node_proj/app$ browserify dom_front.js --transform babelify --standalone util &gt; ./assets/mynpmmodule.js
        2. 检查 assets 文件夹,它现在创建名为 mynpmmodule.js 的文件
        3. 将此文件添加到您的 HTML &lt;script src="assets/mynpmmodule.js"&gt;&lt;/script&gt;
        4. 现在您可以使用导出的 npm 模块/类或使用上面提到的独立密钥 util like 所需的文件
        <script>
          const Component = util.Component;
          console.log(Component);
          const ReactDOM = util.ReactDOM;
        </script>
        

        【讨论】:

          【解决方案5】:

          为了正确编译 es2015-react 代码,你应该安装一些节点模块:

          全球

          npm install -g browserify
          

          在您的应用目录中:

          npm install --save-dev browserify babelify babel-preset-es2015 babel-preset-stage-0 babel-preset-react
          

          然后创建 gulp 任务:

              var browserify = require("browserify");
              var babelify = require("babelify");
          
              gulp.task('es6-compile', function() {
                browserify({ debug: true })
                  .transform(babelify.configure({ presets: ["es2015","react", "stage-0"] }))
                  .require("./public/src/javascripts/app.js", { entry: true })
                  .bundle()
                  .pipe(gulp.dest('./public/dest/javascripts'));
              });
          

          在 ./public/dest/javascripts 目录下你会找到编译后的 es5 app.js 文件。

          【讨论】:

          • 我不使用 babel,我只是想使用 browserify 来捆绑模块。导入/导出有可能吗?
          【解决方案6】:

          我在尝试从node_modules 导入一个以 ES6 样式导出的模块时遇到了同样的错误。 SO上没有任何建议对我有用。然后我在babelify repo 上找到了常见问题解答部分。根据那里的见解,出现错误是因为来自 node_modules 的模块默认情况下不会被转译,并且由 Common.js 样式模块提供支持的节点无法理解其中的 ES6 声明(如 export default ModuleName)。

          所以,我更新了我的包,然后使用 global 选项将 babelify 作为全局转换运行,不包括所有节点模块,但我感兴趣的模块在 babelify 存储库页面上显示:

          ...    
          browserify.transform("babelify", 
              {
                  presets: ["@babel/preset-env"], 
                  sourceMaps: true, 
                  global: true, 
                  ignore: [/\/node_modules\/(?!your module folder\/)/]
              }).bundle()
          ...
          

          希望对你有帮助。

          【讨论】:

          • 拯救了这一天。这是正确的答案,因为您应该使用 preset-env 而不是 es2015
          • 你能解释一下“你的模块文件夹”应该在 node_modules 中吗?我查看了 repo 自述文件,但也没有说清楚。
          • @NikolayDyankov 它实际上是所需包的文件夹,通常位于其中某种入口点(导出您需要的东西)。通常,它是放置 index.js 等的文件夹。包的根类型。希望你能明白。
          • 我尝试了上述方法,但对我不起作用。你能看看这个question
          【解决方案7】:

          .eslintrc 中您可能需要指定解析器选项,例如:

          {
          "rules": {
              "indent": [
                  2,
                  4
              ],
              "linebreak-style": [
                  2,
                  "unix"
              ],
              "semi": [
                  2,
                  "always"
              ]
          },
          "env": {
              "es6": true,
              "browser": true,
              "node": true,
              "mocha": true
          },
          "extends": "eslint:recommended",
          "parserOptions": {
              "ecmaVersion": 6,
              "sourceType": "module",
              "ecmaFeatures": {
                  "jsx": true
              }
          }
          

          }

          请查看eslint的文档指南。

          【讨论】:

            【解决方案8】:

            在我的例子中,我使用 export 而不是 exports

            export 更改为 exports

            【讨论】:

            • 很多有用的东西都不是正确的答案。删除所有 js,并用一堆静态 img 和 onclick 页面更改替换网站也可以“工作”,但不是问题的答案。
            【解决方案9】:

            出于某种原因,babelify 8.0.0 不适用于我的 es2015 或 env 礼物。但是,as of 2018-07-10esmify 插件 mattdesl 确实对我有用。我的测试用例将Spinnerspin.js 导出为全局窗口。我的示例仓库是here;关键细节如下。

            main.js

            import {Spinner} from 'spin.js';
            window.Spinner = Spinner;
            

            测试

            在一个空目录中:

            npm init
            

            并接受所有默认值,然后:

            npm install --save spin.js
            npm install --save-dev browserify esmify
            npx browserify -p esmify main.js -o main-packed.js
            

            测试 HTML 文件

            <html><head>
                <link rel="stylesheet" href="node_modules/spin.js/spin.css" />
                <script src="main-packed.js"></script>    <!-- <== the browserify output -->
            </head>
            <body>
                <div id="x"></div>
                <script>
                var target = document.getElementById('x');
                var spin = new Spinner().spin(target);
                </script>
            </body></html>
            

            加载后,它会在页面中心显示一个微调器。

            注意:我不隶属于 mattdesl 或 esmify。

            【讨论】:

            • esmify 完成这项工作!
            【解决方案10】:

            此错误可能是由于在 gulp 任务中未包含用于编译 typescript 的 tsify 插件。

            例子

                var tsify = require('tsify');
            
                return browserify({ ... })
                  .plugin(tsify)
                  .transform(babelify.configure({
                    presets: ["es2015"]
                  }))
                  ...
            

            在此处查看安装和使用: https://www.npmjs.com/package/tsify

            【讨论】:

              【解决方案11】:

              旧版本的 Babel 提供了开箱即用的一切。较新的版本要求您安装安装所需的任何插件。首先,您需要安装 ES2015 预设。

              npm install babel-preset-es2015 --save-dev
              

              接下来,你需要告诉 babelify 使用你安装的预设。

              return browserify({ ... })
                .transform(babelify.configure({
                  presets: ["es2015"]
                }))
                ...
              

              Source

              【讨论】:

              • 我完全删除了这个包,不知道我需要它用于 babel 6.17。有趣。谢谢。
              • 你能用 Angular 2 的 webpack 展示这个例子吗
              • @sainu 关于如何开始使用 Angular 有一个 full-fledged tutorial,它将为您提供一个支持 importexport 的开发环境。更不用说这个问题是关于使用 Browserify,而不是 Webpack。
              • 我还需要 -- npm install babel-preset-env 然后,从命令行,做了: browserify src/app.js -t [ stringify --extensions [ .bpmn ] -g [ babelify --presets [ "es2015" ] ] -o src/app.bundled.js
              • @MikeCluck 你能澄清一下 babelify.configure 步骤吗?您的代码 sn-p 说它返回 browserify,但从什么函数返回?如何全局使我的 typescript 在 ES6 中运行?
              猜你喜欢
              • 2017-05-16
              • 1970-01-01
              • 2017-04-23
              • 1970-01-01
              • 1970-01-01
              • 2018-05-28
              • 1970-01-01
              • 2017-10-06
              • 1970-01-01
              相关资源
              最近更新 更多