A importação ES2015 não funciona (mesmo no nível superior) no Firefox

94

Estes são meus arquivos de amostra:

<!DOCTYPE html>
<html>
<head>
  <title>Test</title>
  <script src="t1.js"></script>
</head>
<body></body>
</html>

t1.js:

import Test from 't2.js';

t2.js:

export const Test = console.log("Hello world");

Quando carrego a página no Firefox 46, ele retorna "SyntaxError: declarações de importação podem aparecer apenas no nível superior de um módulo" - mas não tenho certeza de quanto mais nível superior a instrução de importação pode chegar aqui. Este erro é uma pista falsa e a importação / exportação ainda não é suportada?

Christoph Burschka
fonte
2
Módulos ES6 ainda não são suportados em navegadores.
Felix Kling
2
Não é verdade Felix. Nem mesmo em 2016. Não compatível com 'Todos' os navegadores seria mais preciso.
Andrew S

Respostas:

133

Na verdade, o erro que você obteve foi porque você precisa declarar explicitamente que está carregando um módulo - só então o uso de módulos é permitido:

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

Eu encontrei neste documento sobre como usar a importação ES6 no navegador . Leitura recomendada.

Totalmente compatível com essas versões de navegador (e posteriores; lista completa em caniuse.com ):

  • Firefox 60
  • Chrome (desktop) 65
  • Chrome (Android) 66
  • Safari 1.1

Em navegadores mais antigos, pode ser necessário habilitar alguns sinalizadores em navegadores:

  • Chrome Canary 60 - por trás da bandeira da Plataforma Web Experimental em chrome:flags.
  • Firefox 54 - dom.moduleScripts.enabledconfiguração em about:config.
  • Edge 15 - por trás da configuração de recursos experimentais de JavaScript em about:flags.
Tomáš Zato - Reintegrar Monica
fonte
1
Obrigado; esta parece ser uma informação nova (compare a tabela de suporte do navegador da resposta anterior com developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… ), então estou mudando para sua resposta, pois importnão é mais compatível.
Christoph Burschka
1
trabalhando agora sem sinalizadores / configurações no edge 16299 e no Chrome 64. Uma advertência precisa importar o caminho, não o arquivo, então em t1.js: import Test from './t2.js';
Catweazle
@Catweazle Tem certeza que é './t2.js'e não './t2'sem o .js?
fredoverflow de
@fredoverflow Sim, o nome completo deve ser especificado, ao contrário do Node.js.
Tomáš Zato - Reintegrar Monica
precisa de um exemplo completo, não apenas a importação
bharal
14

Isso não é mais preciso. Todos os navegadores atuais agora suportam módulos ES6

Resposta original abaixo

De importem MDN :

Este recurso não está implementado em nenhum navegador nativamente no momento. Ele é implementado em muitos transpiladores, como o Compilador Traceur, Babel ou Rollup.

Os navegadores não são compatíveis import.

Aqui está a tabela de suporte do navegador:

insira a descrição da imagem aqui

Se você deseja importar módulos ES6, sugiro o uso de um transpiler (por exemplo, babel ).

Josh Beam
fonte
Você pode ativar esses recursos usando um sinalizador (como no Chrome)?
evolutionxbox
4
@evolutionxbox: Se os recursos não forem implementados , então não há sinalização também.
Bergi
1
Se os recursos não forem implementados, por que não obtenho um erro de sintaxe ou um erro informando que eles não foram implementados? Isso não faz sentido.
Tomáš Zato - Reintegração de Monica em
@ TomášZato, depende de como o navegador que você está usando decidiu lidar com isso
Josh Beam
1
Na verdade, ocorreu um erro no meu código e funciona muito bem. Não sei por que sua resposta foi votada. Navegadores que não oferecem suporte a importações relatam isso. Erros como esse em questão são erros reais usando importações.
Tomáš Zato - Reintegração de Monica
2

Apenas usar a extensão de arquivo .js durante a importação de arquivos resolveu o mesmo problema (não se esqueça de definir type="modulena tag do script).

Basta escrever:

import foo from 'foo.js';

ao invés de

import foo from 'foo';
krmld
fonte
1

Adicionar type=moduleos scripts que importam e exportam os módulos resolveria este problema.

Abhishek Khatri
fonte
0

você tem que especificar seu tipo no script e exportar tem que ser o padrão .. por exemplo, no seu caso deveria ser,

<script src='t1.js' type='module'>

para t2.js use default após exportar assim, export default 'aqui vai sua expressão' (você não pode usar variável aqui) . você pode usar uma função como esta,

export default function print(){ return console.log('hello world');}

e para importação, sua sintaxe de importação deve ser assim, import print from './t2.js' (use a extensão de arquivo e ./ para o mesmo diretório) ..Espero que seja útil para você!

SK Biswas
fonte
0

Por uma questão de argumento ...

Pode-se adicionar uma interface de módulo personalizado ao objeto de janela global. Embora não seja recomendado. Por outro lado, o DOM já está quebrado e nada persiste. Eu uso isso o tempo todo para carregar módulos dinâmicos e inscrever ouvintes personalizados. Provavelmente não é uma resposta, mas funciona. Stack overflow agora tem um module.export que chama um evento chamado 'Spork' - pelo menos até a atualização ...

//  spam the global window with a custom method with a private get/set-interface and     error handler... 

window.modules = function(){
  window.exports = {
    get(modName) {
      return window.exports[modName] ? window.exports[modName] : new Error(`ERRMODGLOBALNOTFOUND [${modName}]`)
    },
    set(type, modDeclaration){
      window.exports[type] = window.exports[type] || []
      window.exports[type].push(modDeclaration)

    }
  }

}

//  Call the method
window.modules()

//  assign a custom type and function
window.exports.set('Spork', () => console.log('SporkSporSpork!!!'))


// Give your export a ridiculous event subscription chain type...
const foofaalala = window.exports.get('Spork')

// Iterate and call (for a mock-event chain)
foofaalala.forEach(m => m.apply(this))

//  Show and tell...
window
Paul Fabing
fonte