Obtendo exportação inesperada de tokens

220

Estou tentando executar algum código ES6 no meu projeto, mas estou recebendo um erro inesperado de exportação de token.

export class MyClass {
  constructor() {
    console.log("es6");
  }
}
Jason
fonte
5
não há informações suficientes sobre seu ambiente ou configuração para oferecer assistência. Esse erro sugere que o webpack ou o babel não estão funcionando corretamente, como exportestá disponível apenas no ES6, e são esses módulos que fornecem suporte ao ES6.
Claies
24
Você deve usar module.exports = MyClass, nãoexport class MyClass
onmyway133

Respostas:

249

Você está usando a sintaxe do módulo ES6.

Isso significa que seu ambiente (por exemplo, node.js) deve suportar a sintaxe do módulo ES6.

O NodeJS usa a sintaxe do módulo CommonJS ( module.exports) e não a sintaxe do módulo ES6 (export palavra-chave).

Solução:

  • Use o babelpacote npm para transpilar seu ES6 para um commonjsdestino

ou

  • Refatorar com sintaxe CommonJS.

Exemplos de sintaxe CommonJS são (de flaviocopes.com/commonjs/ ):

  • exports.uppercase = str => str.toUpperCase()
  • exports.a = 1
Phil Ricketts
fonte
15
Quando o nodejs suportará importnativamente? Eu pensei que v10.0.0 teria, mas aparentemente não.
Chovy
4
O suporte experimental @chovy está disponível com o sinalizador "--experimental-modules". Arquivos precisa ter uma extensão .mjs
Giovanni P.
1
Estou recebendo esse erro usando o Chrome 66 com suporte nativo para módulos.
Tom Russell
BTW: observe que, enquanto o node10 / node12 suporta módulos atrás do sinalizador, eles não o suportam no modo REPL - no entanto, ele é suportado no modo de avaliação no node12 .
Jkub.g 17/07/19
2
Para alguém ainda não está claro sobre a sintaxe do CommonJs. confira este link, pode ajudar um pouco. flaviocopes.com/commonjs
LT
142

Caso você receba esse erro, ele também pode estar relacionado à forma como você incluiu o arquivo javascript na sua página html. Ao carregar os módulos, você deve declarar explicitamente esses arquivos como tal. Aqui está um exemplo:

//module.js:
function foo(){
   return "foo";
}

var bar = "bar";

export { foo, bar };

Quando você inclui o script assim:

<script src="module.js"></script>

Você receberá o erro:

SyntaxError não capturado: exportação inesperada de tokens

Você precisa incluir o arquivo com um atributo de tipo definido como "módulo":

<script type="module" src="module.js"></script>

E então funcionará conforme o esperado e você estará pronto para importar seu módulo em outro módulo:

import { foo, bar } from  "./module.js";

console.log( foo() );
console.log( bar );
Wilt
fonte
37
diferente da resposta "mais votada", isso realmente resolve o problema e explica por que está acontecendo sem sugerir que a única opção é aproveitar um método CommonJS, o método APM ou transpilar nosso código ... Isso também seria uma exceção para o padrão w3c, onde typese espera que seja um tipo mime válido (também conhecido como tipo de mídia), portanto, essa foi uma descoberta inesperada. Obrigado!
Shaun Wilson
4
Isso corrige o erro, mas eu, em seguida, obter "símbolo inesperado {" na linha da declaração de importação no Chrome 67 com script que está em linha eg <script> import ... </ script>
PandaWood
1
@PandaWood Você precisa usar <script type="module">import ...</script>quando importar do módulo. Eu testei na versão recente do Chromium.
Vladimir S.
Este fixa o meu problema :)
user3651476
O JS puro (ES6) suportou a importação e isso explica exatamente por que eu o conheci #
Eric
15

Meus dois centavos

Exportar

ES6

myClass.js

export class MyClass1 {
}
export class MyClass2 {
}

other.js

import { MyClass1, MyClass2 } from './myClass';

CommonJS Alternative

myClass.js

class MyClass1 {
}
class MyClass2 {
}
module.exports = { MyClass1, MyClass2 }
// or
// exports = { MyClass1, MyClass2 };

other.js

const { MyClass1, MyClass2 } = require('./myClass');

Padrão de exportação

ES6

myClass.js

export default class MyClass {
}

other.js

import MyClass from './myClass';

CommonJS Alternative

myClass.js

module.exports = class MyClass1 {
}

other.js

const MyClass = require('./myClass');

Espero que isto ajude

Barnstokkr
fonte
No exemplo de exportação padrão do ES6, você escreveu "exportação padrão", mas deve ser "padrão de exportação".
IAM_AL_X 29/03
@IAM_AL_X Obrigado pela captura :-)
Barnstokkr
10

Para usar o ES6, adicione babel-preset-env

e no seu .babelrc:

{
  "presets": ["@babel/preset-env"]
}

Resposta atualizada graças ao comentário @ghanbari para aplicar babel 7.

Jalal
fonte
8
sua pergunta não é sobre explicar babel. Então, por que responder a algo não necessário, que pode confundir outro?
Jalal
7
@ monsto esta pergunta já foi marcada babelpelo autor. Enquanto a resposta de Phil Ricketts esclarece o problema, o que é bom, essa resposta é uma solução direta para o problema do autor.
boycy
"@ babel / preset-env"
ghanbari 16/06/19
6

Não há necessidade de usar o Babel neste momento (o JS se tornou muito poderoso) quando você pode simplesmente usar as exportações padrão do módulo JavaScript. Veja o tutorial completo

Message.js

module.exports = 'Hello world';

app.js

var msg = require('./Messages.js');

console.log(msg); // Hello World
Alvin Konda
fonte
2
Bem, como você exportaria uma classe então?
Sherwin Ablaña Dapito
1
Estou excluindo minha resposta, pois a pergunta era de fato para o ES6 e não o CommonJS usado pelo NodeJS. Verifique acima para obter uma resposta.
Alvin Konda
@ SherwinAblañaDapito module.exports = class MyClass {} funciona
Marian Klühspies
3

Instale os pacotes babel @babel/coree @babel/presetque converterão o ES6 em um destino commonjs, já que o nó js não entende os destinos do ES6 diretamente

npm install --save-dev @babel/core @babel/preset-env

Em seguida, você precisa criar um arquivo de configuração com o nome .babelrcno diretório raiz do seu projeto e adicionar esse código lá

{ "presets": ["@babel/preset-env"] }

YouBee
fonte
Eu também precisava instalar o @ babel / register, caso contrário, ainda receberia "SyntaxError: Não é possível usar a declaração de importação fora de um módulo"
molecular
3

Corrigi isso criando um arquivo de ponto de entrada como.

// index.js
require = require('esm')(module)
module.exports = require('./app.js')

e qualquer arquivo que eu importei dentro app.jse além trabalhou comimports/exports agora você apenas executa comonode index.js

Nota: se app.jsusado export default, isso se torna require('./app.js').defaultao usar o arquivo do ponto de entrada.

Alex Cory
fonte
1
Melhor resposta para projetos simples que não precisam de babel, webpack, parcel etc ... Eu usei no projeto monorepo com simple / server express para o projeto. Trabalhou como um encanto ...
mattdlockyer 5/03
-3

O uso da sintaxe do ES6 não funciona no nó, infelizmente, você precisa ter o babel aparentemente para fazer o compilador entender a sintaxe, como exportação ou importação.

npm install babel-cli --save

Agora precisamos criar um arquivo .babelrc. No arquivo babelrc, definiremos o babel para usar a predefinição es2015 que instalamos como predefinição ao compilar no ES5.

Na raiz do nosso aplicativo, criaremos um arquivo .babelrc. $ npm install babel-preset-es2015 --save

Na raiz do nosso aplicativo, criaremos um arquivo .babelrc.

{  "presets": ["es2015"] }

Espero que funcione ... :)

purushottam banerjee
fonte