Módulo anônimo define () incompatível

129

Estou recebendo esse erro quando navego no meu aplicativo da web pela primeira vez (geralmente em um navegador com cache desativado).

Erro: módulo define () anônimo incompatível: function (require) {

HTML :

<html>
   .
   .
   .
   <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
   <script> var require = { urlArgs: "v=0.4.1.32" }; </script>
   <script data-main="assets/js/main" src="assets/js/libs/require.js"></script>
   <script src="assets/js/ace/ace.js?v=0.4.1.32"></script>
   </body>
</html>

JS :

$(function () {
    define(function (require) {
        // do something
    });
});

Alguém sabe exatamente o que esse erro significa e por que está acontecendo?

arquivo de origem , uma breve discussão sobre ele na página de problemas do github

Adonis K. Kakoulidis
fonte

Respostas:

142

Como o AlienWebguy disse, de acordo com os documentos, o require.js pode explodir se

  • Você tem um define anônimo (" módulos que chamam define () sem ID de cadeia ") em sua própria tag de script (presumo que eles realmente signifiquem em qualquer lugar do escopo global)
  • Você possui módulos com nomes conflitantes
  • Você usa plug-ins de carregador ou módulos anônimos, mas não usa o otimizador do require.js para agrupá-los

Eu tive esse problema ao incluir pacotes criados com o browserify ao lado dos módulos require.js. A solução foi:

A. carregue os pacotes autônomos non-require.js nas tags de script antes que o require.js seja carregado ou

B. carregue-os usando require.js (em vez de uma tag de script)

BT
fonte
2
conflitantes nomes é comum
Julio Marins
1
Outra solução possível, em alguns casos especiais com módulos anônimos, é sobrescrever a função requirejs.onError para impedir que a exceção de erro padrão seja lançada pelo requirejs, que interrompe a execução de módulos ou códigos sucessivos.
xtrm
1
Acabei de adicionar uma solicitação pull ( github.com/requirejs/requirejs/pull/1763 ) para relaxar o caso exato. Eu acho que é um problema muito comum nos dias de hoje.
Bob S
1
Obrigado por me dizer para carregá-los antes! Eu não sei por que essa dica não está na documentação do requirejs ... É aí que a pilha é útil
Tobias Feil 04/03
14

Eu tive esse erro porque incluí o arquivo requirejs juntamente com outras bibliotecas incluídas diretamente em uma tag de script. Essas bibliotecas (como lodash) usavam uma função de definição que estava em conflito com a definição de require. O arquivo requirejs estava carregando de forma assíncrona, então eu suspeito que a definição de require foi definida depois que as outras bibliotecas definem, daí o conflito.

Para se livrar do erro, inclua todos os seus outros arquivos js usando requirejs.

eloone
fonte
Acabou que muitas bibliotecas fazem isso, ou pelo menos usam / exportam essa função. Vou recomendar a todos - se eles usam exigem - importação tudo com exigem :)
Andrey Popov
12

Ao iniciar o reactjs, deparei-me com o problema e, como iniciante, os documentos podem ser escritos em grego.

O problema que encontrei foi que a maioria dos exemplos para iniciantes usa "define anônimo" quando você deve usar um "ID de string".

anônimo define

define(function() {
        return { helloWorld: function() { console.log('hello world!') } };
 })


define(function() {
        return { helloWorld2: function() { console.log('hello world again!') } };
 })

definir com o ID da string

define('moduleOne',function() {
    return { helloWorld: function() { console.log('hello world!') } };
})

 define('moduleTwo', function() {
      return { helloWorld2: function() { console.log('hello world again!') } };
})

Quando você usa define com um ID de string , evita esse erro ao tentar usar os módulos da seguinte maneira:

require([ "moduleOne", "moduleTwo" ], function(moduleOne, moduleTwo) {
    moduleOne.helloWorld();
    moduleTwo.helloWorld2();
});
P.Brian.Mackey
fonte
(Apenas uma nota para a posteridade) Não são algumas desvantagens para esta abordagem, descrita na documentação : “definem () chama que incluem um nome para o módulo ... são normalmente gerado pela ferramenta de otimização ... nam [ndo] módulos de si mesmo ... faz com que o módulos menos portáteis ... Normalmente, é melhor evitar codificar um nome para o módulo e deixar a ferramenta de otimização queimar nos nomes dos módulos. ” ... bem como neste segmento do GitHub . Esta parece ser a razão pela qual a listagem do nome é excluída nos exemplos iniciantes.
Mark G.
10

De acordo com os documentos :

Se você codificar manualmente uma tag de script em HTML para carregar um script com uma chamada define () anônima, esse erro poderá ocorrer.

Também é visto se você codifica manualmente uma tag de script em HTML para carregar um script que possui alguns módulos nomeados, mas tenta carregar um módulo anônimo que acaba tendo o mesmo nome que um dos módulos nomeados no script carregado manualmente. tag de script codificado.

Por fim, se você usar os plug-ins do carregador ou módulos anônimos (módulos que chamam define () sem ID da cadeia), mas não usar o otimizador RequireJS para combinar arquivos, esse erro poderá ocorrer. O otimizador sabe como nomear módulos anônimos corretamente, para que possam ser combinados com outros módulos em um arquivo otimizado.

Para evitar o erro:

  • Certifique-se de carregar todos os scripts que chamam define () por meio da API RequireJS. Não codifique manualmente as tags de script em HTML para carregar scripts que tenham chamadas de define ().

  • Se você codificar manualmente uma tag de script HTML, verifique se ela inclui apenas módulos nomeados e se um módulo anônimo que terá o mesmo nome que um dos módulos desse arquivo não está carregado.

  • Se o problema for o uso de plug-ins de carregador ou módulos anônimos, mas o otimizador RequireJS não for usado para o empacotamento de arquivos, use o otimizador RequireJS.

AlienWebguy
fonte
3
Este é um módulo definido anonimamente? github.com/requirejs/example-multipage/blob/master/www/js/app/…
streetlight
5

Esteja ciente de que algumas extensões do navegador podem adicionar código às páginas. No meu caso, eu tinha um plug-in "Emmet em todas as áreas de texto" que mexia com os meus requireJs. Certifique-se de que nenhum código extra seja adicionado ao seu documento, inspecionando-o no navegador.

Vetor
fonte
5

As respostas existentes explicam bem o problema, mas se a inclusão de seus arquivos de script usando ou antes do requireJS não é uma opção fácil, devido ao código legado, uma solução alternativa para hackers é remover o require do escopo da janela antes da tag do script e depois restabelecê-lo depois. Em nosso projeto, isso está envolvido por uma chamada de função do servidor, mas efetivamente o navegador vê o seguinte:

    <script>
        window.__define = window.define;
        window.__require = window.require;
        window.define = undefined;
        window.require = undefined;
    </script>
    <script src="your-script-file.js"></script>        
    <script>
        window.define = window.__define;
        window.require = window.__require;
        window.__define = undefined;
        window.__require = undefined;
    </script>

Não é o mais arrumado, mas parece funcionar e economizou bastante refração.

jcbdrn
fonte
5
Na verdade, nunca faça isso. Não funciona corretamente no IE.
jcbdrn
2
Intermitentemente, no IE, os scripts incluídos no requireJS definiriam a falta do escopo da janela, mesmo quando o comando require veio após a restauração dessas variáveis. Nós nunca conseguimos descobrir por que isso ocorreu, então abandonamos essa solução hacky.
Jcbdrn
2
@jcbdrn Não é apenas no IE. Eu já vi isso acontecer em outra plataforma. O motivo é que a especificação HTML oferece garantias em relação à ordem de execução de scripts síncronos, mas apenas em relação a outros scripts síncronos . Não garante a execução de scripts assíncronos em relação a um síncrono (ou vice-versa). Portanto, no código mostrado na resposta aqui, é possível executar um script assíncrono entre dois scriptelementos.
Louis
Se você tem a capacidade de editar o pacote js que você está importando, basta agrupar a coisa toda desta maneira: #(function(){ var define = undefined; // the UMD registration code won't find the global 'define' anymore! // generated content goes here })()
Pete Thorne
2

Ou você pode usar essa abordagem.

  • Adicione o arquivo require.js na sua base de código
  • então carregue seu script através desse código

<script data-main="js/app.js" src="js/require.js"></script>

O que ele fará irá carregar seu script após o carregamento do require.js .

Umar Asghar
fonte