SyntaxError: "import" и "export" могут появляться только с "sourceType: module" - подождите что?

Итак, рассмотрим следующие два файла:

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'

Извините, что? Что это за ошибка? Что я делаю неправильно?

12 ответов

Решение

Старые версии Babel поставлялись со всем из коробки. Более новая версия требует, чтобы вы установили те плагины, которые нужны вашей установке. Во-первых, вам нужно установить предустановку ES2015.

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

Далее вам нужно указать babelify, чтобы использовать установленный вами пресет.

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

Источник

ESLint изначально не поддерживает это, потому что это противоречит спецификации. Но если вы используете анализатор babel-eslint, то внутри вашего конфигурационного файла eslint вы можете сделать это:

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

Ссылка на документ: https://github.com/babel/babel-eslint

Ответ отсюда: игнорировать ошибку eslint: "import" и "export" могут появляться только на верхнем уровне

Я столкнулся с той же ошибкой при попытке импортировать модуль из node_modulesкоторый экспортируется в стиле ES6. Ничего из того, что было предложено на SO, не сработало для меня. Затем я нашел раздел часто задаваемых вопросов о репозитории babelify. Согласно инсайту оттуда, ошибка появляется, поскольку модули изnode_modules не передаются по умолчанию, а объявления ES6, такие как export default ModuleName в них не понимаются узлы, работающие на модулях в стиле Common.js.

Итак, я обновил свои пакеты, а затем использовал global возможность запустить babelify как глобальное преобразование, исключая все модули узлов, кроме того, который меня интересовал, как указано на странице репозитория babelify:

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

Надеюсь, это поможет.

По какой-то причине babelify 8.0.0 не работает для меня ни с подарками es2015, ни с env. Однако по состоянию на 2018-07-10 esmify Плагин от Mattdesl работал на меня. Мой тестовый случай был экспорт Spinner от spin.js как окно глобальное. Мой пример репо здесь; ключевые детали следуют.

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.

В .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.

Для корректной компиляции кода es2015-response вам необходимо установить несколько узловых модулей:

глобально

  1. npm install -g browserify

в каталоге вашего приложения:

  1. npm установить browserify --save
  2. npm установить babelify --save
  3. npm установить babel-preset-es2015 - сохранить
  4. npm установить babel-preset-stage-0 - сохранить
  5. npm install babel-preset-реакции --save Затем создайте задание 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.

Если вы хотите использовать что-нибудь import или require метод в npm на стороне клиента просто выполните следующие шаги

  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. Создайте файл с именем dom_front.js Внутри /app папку файл, который вы хотите преобразовать как клиентский js.
const ReactDOM  = require('react-dom')
import React, {Component} from 'react' 
export {Component,React,ReactDOM};

Это смешанные данные экспорта модулей и требуемых файлов.

Примечание: не забудьте установить react-dom & react

  1. Использование browserify api - создайте файл js, такой как browserifyload.js и папку с ресурсами
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 > ./assets/mynpmmodule.js
  2. Проверьте папку с ресурсами, где теперь создается файл с именем mynpmmodule.js
  3. Добавьте этот файл в свой HTML <script src="assets/mynpmmodule.js"></script>
  4. Теперь вы можете использовать экспортированные модули / классы npm или необходимые файлы, используя автономный ключ, упомянутый выше. util нравиться
<script>
  const Component = util.Component;
  console.log(Component);
  const ReactDOM = util.ReactDOM;
</script>
          return browserify(jsConfig.src)
  .transform(babelify.configure({
    presets: ["@babel/preset-env"]
  }))
  .bundle()
  .on('error', function (e) {
    console.log(e.message);

    this.emit('end');
  })

Работает на меня.

Я попробовал все ответы выше, ни один из них не работал у меня, я даже пытался использовать синтаксис gulp-include / require, они не были ни решением, ни достаточным для моих требований.

Вот мое требование.

  1. Объедините все модули / файлы в один
  2. Сохраняйте все комментарии /JSDocs
  3. Храните все типы (например, const example = (parameter: string) => {})
  4. Использовать синтаксис импорта / экспорта

Причина перечисленных требований заключается в том, что нам нужен репозиторий для хранения наших общих функций, общих конфигураций, общих типов и общих констант в виде пакета npm (установка с URL-адресом). В этом случае мы уже знаем, что все наши проекты используют TypeScript, поэтому нет необходимости компилировать наш общий модуль в.js, и нам также необходимо сохранить все описания, как это делают другие пакеты (действительно помогают JSDoc и Type).

Пока лучшее, что я могу сделать, это использовать browserify с участием tsify. Я случайно нашел обходной путь от сюда.

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

Я все еще ищу способ сохранить наши встроенные типы и комментарии /JSDocs, но я считаю, что этого достаточно для ваших нужд.

Запретите всем, кто дергает себя за волосы, пытаясь заставить машинописный текст работать в Babelify. Как оказалось,'import' and 'export' may appear only with 'sourceType: module'ошибка также имеет место, если вы не добавили.tsк расширениям опций Babelify. Обратите внимание, что вам, возможно, придется указатьextensionsкак в браузера , так и в Babelify :параметрах параметрах

      ...
const babelify = require('babelify');

var appBundler = browserify({
  entries: ["./index.ts"],
  debug: true,
  extensions: [".js", ".jsx", ".ts", ".tsx"],
})
  .transform(babelify.configure({
    "presets": [
      "@babel/preset-env",
      "@babel/preset-react",
      ["@babel/preset-typescript", { isTSX: true, allExtensions: true }],
    ],
    extensions: [".js", ".jsx", ".ts", ".tsx"], // <============= fix here
  }))
  .bundle()
  .pipe(source("index.js"))
  .pipe(gulp.dest('app/'));

Эта ошибка может быть вызвана отсутствием подключаемого модуля tsify для компиляции машинописи в задаче gulp.

пример

    var tsify = require('tsify');

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

Смотрите установку и использование здесь: https://www.npmjs.com/package/tsify

В моем случае я использовал экспорт вместо экспорта.

изменить экспорт на экспорт.

Другие вопросы по тегам