Qual é a diferença entre usar o Require.JS amd simplesmente criando um <script>
elemento no DOM?
Meu entendimento do Require.JS é que ele oferece a capacidade de carregar dependências, mas isso não pode ser feito simplesmente criando um <script>
elemento que carrega o arquivo JS externo necessário?
Por exemplo, vamos assumir que eu tenho a função doStuff()
, que requer a função needMe()
. doStuff()
está no arquivo externo do_stuff.js
, enquanto needMe()
está no arquivo externo need_me.js
.
Fazendo isso da maneira Require.JS:
define(['need_me'],function(){
function doStuff(){
//do some stuff
needMe();
//do some more stuff
}
});
Para fazer isso, basta criar um elemento de script:
function doStuff(){
var scriptElement = document.createElement('script');
scriptElement.src = 'need_me.js';
scriptElement.type = 'text/javascript';
document.getElementsByTagName('head')[0].appendChild(scriptElement);
//do some stuff
needMe();
//do some more stuff
}
Ambos funcionam. No entanto, a segunda versão não exige que eu carregue toda a biblioteca Require.js. Eu realmente não vejo nenhuma diferença funcional ...
javascript
requirejs
dynamic-script-loading
js-amd
maxedison
fonte
fonte
Respostas:
Aqui está o belo artigo no ajaxian.com sobre por que usá-lo:
RequireJS: carregamento assíncrono de JavaScript
fonte
No seu exemplo, você está criando a tag de script de forma assíncrona, o que significa que sua
needMe()
função seria invocada antes que o arquivo need_me.js conclua o carregamento. Isso resulta em exceções não capturadas onde sua função não está definida.Em vez disso, para fazer o que você está sugerindo realmente funcionar, você precisa fazer algo assim:
Pode-se argumentar que pode ou não ser melhor usar um gerenciador de pacotes como o RequireJS ou utilizar uma estratégia de JavaScript puro, como demonstrado acima. Embora o aplicativo da Web possa carregar mais rapidamente, a invocação de funcionalidades e recursos no site seria mais lenta, pois envolveria a espera do carregamento dos recursos antes que a ação pudesse ser executada.
Se um aplicativo da Web for criado como um aplicativo de página única, considere que as pessoas não recarregarão a página com muita frequência. Nesses casos, pré-carregar tudo ajudaria a tornar a experiência mais rápida ao usar o aplicativo. Nesses casos, você está certo, basta carregar todos os recursos, incluindo as tags de script no cabeçalho ou no corpo da página.
No entanto, se a construção de um site ou aplicativo da Web que segue o modelo mais tradicional em que uma pessoa faz a transição de uma página para outra, causando a recarga de recursos, uma abordagem de carregamento lento pode ajudar a acelerar essas transições.
fonte
Algumas outras razões bem apontadas para o uso do RequireJS fazem sentido:
Retirado dos comentários de rmurphey aqui nesta Gist .
Camadas de abstração podem ser um pesadelo para aprender e ajustar, mas quando serve a um propósito e o faz bem, faz sentido.
fonte
Aqui está um exemplo mais concreto.
Estou trabalhando em um projeto com 60 arquivos. Temos dois modos diferentes de executá-lo.
Carregue uma versão concatenada, 1 arquivo grande. (Produção)
Carregue todos os 60 arquivos (desenvolvimento)
Estamos usando um carregador, então temos apenas um script na página da web
O padrão é o modo 1 (carregando um arquivo concatenado grande). Para executar o modo 2 (arquivos separados), definimos alguma sinalização. Poderia ser qualquer coisa. Uma chave na string de consulta. Neste exemplo, apenas fazemos isso
loader.js tem algo parecido com isto
O script de construção é apenas um arquivo .sh que se parece com isso
etc ...
Se um novo arquivo for adicionado, provavelmente usaremos o modo 2, pois estamos desenvolvendo, temos que adicionar uma
injectScript("somenewfile.js")
linha ao loader.jsMais tarde, para produção, também precisamos adicionar somenewfile.js ao nosso script de construção. Um passo que muitas vezes esquecemos e depois recebemos mensagens de erro.
Ao mudar para a AMD, não precisamos editar 2 arquivos. O problema de manter o loader.js e o script de compilação sincronizados desaparece. Usando
r.js
ouwebpack
ele pode simplesmente ler o código para criarlarge-concantinated.js
Ele também pode lidar com dependências, por exemplo, tivemos 2 arquivos lib1.js e lib2.js carregados assim.
lib2 precisa da lib1. Tem um código dentro que faz algo como
Mas, como os scripts injetados são carregados de forma assíncrona, não há garantia de que eles serão carregados na ordem correta. Esses 2 scripts não são scripts da AMD, mas usando o require.js, podemos dizer suas dependências
I nosso módulo que usa lib1 fazemos isso
Agora, o require.js injetará os scripts para nós e não injetará a lib2 até que a lib1 seja carregada, pois informamos que a lib2 depende da lib1. Ele também não iniciará nosso módulo que usa lib1 até que ambos sejam carregados.
Isso torna o desenvolvimento agradável (sem etapa de compilação, sem se preocupar com a ordem de carregamento) e com a produção (sem a necessidade de atualizar um script de compilação para cada script adicionado).
Como um bônus adicional, podemos usar o plugin babel do webpack para executar o babel sobre o código em navegadores mais antigos e, novamente, não precisamos manter esse script de construção também.
Observe que, se o Chrome (nosso navegador preferido) começasse a oferecer suporte
import
real, provavelmente mudaríamos para isso para desenvolvimento, mas isso realmente não mudaria nada. Ainda poderíamos usar o webpack para criar um arquivo concatenado e executar o babel sobre o código para todos os navegadores.Tudo isso é obtido ao não usar tags de script e usar AMD
fonte