Faz sentido usar o Require.js com o Angular.js? [fechadas]

443

Sou iniciante no Angular.js e estou tentando entender como é diferente do Backbone.js ... Costumávamos gerenciar nossas dependências de pacotes com o Require.js enquanto utilizávamos o Backbone. Faz sentido fazer o mesmo com o Angular.js?

Franck
fonte
Outro projeto de blog e de semente: startersquad.com/blog/angularjs-requirejs
iwein
19
Não - não use require.js OU navegue com o Angular.JS, simplesmente não há necessidade de fazer isso - o AngularJS possui um sistema de módulos e o uso de outro sistema de módulos acima dele tornará sua vida desnecessariamente difícil. Eu segui as respostas neste tópico e perdi muitas horas em algo que era completamente desnecessário. Leia este artigo que explica por que não: medium.com/@dickeyxxx/…
VitalyB
Leia isto para entender a diferença entre os módulos angular e de exigência juristr.com/blog/2014/07/lazy-angular-modules
pilavdzice
1
aqui é um grande vídeo que explica por que é uma boa idéia e mostra como usar RequireJS com AngularJS youtube.com/watch?v=4yulGISBF8w#t=142
gskalinskii
2
@VitalyB Nice article! Sou a favor de carregar aplicativos em pedaços pequenos. Custará nada em breve . Caramba, não custa nada para mim agora.
dsign

Respostas:

224

Sim, faz sentido usar angular.jsjunto com o require.jsqual você pode usar require.jspara modularizar componentes.

Existe um projeto de semente que usa both angular.js and require.js.

Anshu
fonte
108
O projeto inicial mencionado acima não foi tocado por um ano, por isso criei um novo usando o AngularJS e o RequireJS mais recentes, com suporte total para testes orientados a testículos.
23413 t135:
2
@tnajdek, atualizei o link na resposta de Anshu para apontar para o que você sugere.
David Rivers
7
Observe que nenhum desses projetos de sementes é endossado pela equipe Angular. Exigir é um padrão que fez mais sentido em outros contextos, e usá-lo no Angular não é, IMHO, uma prática recomendada.
XML
2
O livro O'Reilly AngularJS de Brad Green & Shyam Seshadri (lançado em abril deste ano) também recomenda adicionar o RequireJS no início do crescimento de um projeto Angular e apresenta detalhes com muita clareza.
Bjørke
1
Eu prefiro fazer tudo em tempo de compilação 1. browserify.org 2. npmjs.org/package/gulp-angular-filesort
A-Dubb
150

Para reafirmar o que eu acho que a pergunta do OP realmente é:

Se estou construindo um aplicativo principalmente no Angular 1.x e (implicitamente) na era do Grunt / Gulp / Broccoli e Bower / NPM, e talvez eu tenha algumas dependências adicionais de biblioteca, é necessário adicionar informações claras e específicas valor além do que recebo usando Angular sem exigir?

Ou, de outra forma:

"O Angular de baunilha precisa exigir o gerenciamento eficaz do carregamento básico de componentes Angular, se eu tiver outras maneiras de lidar com o carregamento básico de scripts? "

E acredito que a resposta básica para isso é: "a menos que você tenha mais alguma coisa acontecendo e / ou não consiga usar ferramentas mais novas e mais modernas".

Sejamos claros desde o início: o RequireJS é uma ótima ferramenta que resolveu alguns problemas muito importantes e nos iniciou no caminho em que estamos, em direção a aplicativos Javascript mais escaláveis ​​e mais profissionais. É importante ressaltar que foi a primeira vez que muitas pessoas encontraram o conceito de modularização e de tirar as coisas do escopo global. Portanto, se você for criar um aplicativo Javascript que precisa ser dimensionado, o Exigir e o padrão AMD não são ferramentas ruins para isso.

Mas, existe algo em particular no Angular que faz do Require / AMD um ajuste particularmente bom? Não. De fato, o Angular fornece seu próprio padrão de modularização e encapsulamento, o que de muitas maneiras torna redundante os recursos básicos de modularização da AMD. E integrar módulos Angular no padrão AMD não é impossível, mas é um pouco ... exigente. Definitivamente, você estará gastando tempo conseguindo integrar os dois padrões.

Por alguma perspectiva da própria equipe Angular, há este , de Brian Ford, autor do Angular Batarang e agora um membro da equipe principal Angular:

Não recomendo usar o RequireJS com o AngularJS. Embora seja certamente possível, não vi nenhum caso em que o RequireJS tenha sido benéfico na prática.

Portanto, na questão muito específica do AngularJS: Angular e Require / AMD são ortogonais e em locais sobrepostos. Você pode usá-los juntos, mas não há nenhuma razão especificamente relacionada à natureza / padrões do próprio Angular.

Mas e o gerenciamento básico de dependências internas e externas para aplicativos Javascript escaláveis? Não exige que faça algo realmente crítico para mim lá?

Eu recomendo verificar o Bower e o NPM, principalmente o NPM. Não estou tentando iniciar uma guerra santa sobre os benefícios comparativos dessas ferramentas. Quero apenas dizer: existem outras maneiras de esfolar esse gato, e essas formas podem ser ainda melhores que a AMD / Require. (Eles certamente têm um impulso muito mais popular no final de 2015, principalmente o NPM, combinado com os módulos ES6 ou CommonJS. Consulte a pergunta SO relacionada .)

E quanto ao carregamento lento?

Observe que o carregamento lento e o download lento são diferentes. O carregamento lento do Angular não significa que você os puxe diretamente do servidor. Em um aplicativo no estilo Yeoman com automação javascript, você está concatenando e minificando todo o shebang em um único arquivo. Eles estão presentes, mas não são executados / instanciados até que sejam necessários. As melhorias de velocidade e largura de banda que você obtém ao fazer isso superam amplamente quaisquer supostas melhorias do download lento de um controlador de 20 linhas específico. De fato, a latência de rede desperdiçada e a sobrecarga de transmissão desse controlador serão uma ordem de magnitude maior que o tamanho do próprio controlador.

Mas digamos que você realmente precise de downloads preguiçosos, talvez para partes pouco usadas do seu aplicativo, como uma interface de administração. Esse é um caso muito legítimo. Exigir pode realmente fazer isso por você. Mas há também muitos outros , potencialmente mais flexíveis opções que realizam a mesma coisa. E o Angular 2.0 aparentemente cuidará disso para nós, incorporado ao roteador . ( Detalhes .)

Mas e durante o desenvolvimento no meu dev boxen local?

Como posso carregar todos os meus dezenas / centenas de arquivos de script sem precisar anexá-los todos ao index.html manualmente?

Veja os subgeradores no angular do gerador da Yeoman, ou nos padrões de automação incorporados no angular do gerador , ou na automação Webpack padrão do React. Eles fornecem uma maneira limpa e escalonável de: anexar automaticamente os arquivos no momento em que os componentes são montados em andaimes ou simplesmente capturá-los automaticamente se estiverem presentes em determinadas pastas / corresponder a determinados padrões globais. Você nunca mais precisará pensar em seu próprio carregamento de script depois de ter as últimas opções.

Bottom-line?

Exigir é uma ótima ferramenta, para certas coisas. Mas vá com o grão sempre que possível e separe suas preocupações sempre que possível. Deixe a Angular se preocupar com o próprio padrão de modularização da Angular e considere o uso de módulos ES6 ou CommonJS como um padrão geral de modularização. Deixe as ferramentas de automação modernas se preocupar com o carregamento de scripts e o gerenciamento de dependências. E cuide do carregamento preguiçoso assíncrono de maneira granular, em vez de enredá-lo com as outras duas preocupações.

Dito isso, se você estiver desenvolvendo aplicativos Angular, mas não puder instalar o Node em sua máquina para usar as ferramentas de automação Javascript por algum motivo, o Exigir poderá ser uma boa solução alternativa. E já vi configurações realmente elaboradas nas quais as pessoas querem carregar dinamicamente componentes Angular, cada um declarando suas próprias dependências ou algo assim. E, embora eu provavelmente tente resolver esse problema de outra maneira, posso ver os méritos da idéia, para aquela situação muito particular.

Mas, caso contrário ... ao começar do zero com um novo aplicativo Angular e flexibilidade para criar um ambiente de automação moderno ... você terá muitas outras opções, mais flexíveis e mais modernas.

(Atualizado repetidamente para acompanhar a cena JS em evolução).

XML
fonte
1
O projeto inicial NG-Boilerplate ( github.com/ngbp/ngbp ) também cria um webapp de uma única página com um arquivo js. O uso de um manifesto HTML5 garante que esse arquivo seja carregado apenas uma vez por versão.
Federico Elles
2
Embora, como sempre, <i> dependa </i>. Muitas pessoas usam o Exigir para toda a arquitetura e precisam integrar o Angular nesse ecossistema. É uma situação muito diferente da quando você está criando aplicativos isoladamente.
Dave Nichol
2
Acordado. Mas o impulso do OP parece ser: "Se estou construindo um aplicativo principalmente no Angular, e (implicitamente) fazendo isso na era do Grunt, e talvez eu tenha algumas dependências adicionais de biblioteca, o Requer requer um valor claro e específico além o que recebo usando o Angular sem exigir? " E acredito que a resposta é: não. Se você possui um aplicativo enorme com 40 dependências externas, ou não consegue controlar o ambiente do IC, ou o seu chefe adora o Exigir, ou você adora o Exigir, ou o Angular é apenas uma parte de um aplicativo maior, etc., etc., então YMMV.
XML
1
Mas, como ele não parece fazer essas perguntas, e como ele simplesmente menciona o contexto alternativo de um aplicativo Backbone, ele parece perguntar: "o Angular de baunilha precisa de Requerer para gerenciar seus componentes de maneira eficaz?" E a resposta é: "a menos que você tenha algo mais acontecendo". Além disso, essa pergunta surgiu no movimento do IC Javascript, em que temos maneiras muito melhores de lidar com o 'carregamento de script' básico e físico. Se você tiver esse problema resolvido, o Require é basicamente sobre correspondência e encapsulamento de dependência. Angular faz as duas coisas para você.
XML
O Google usa carregamento lento em alguns de seus projetos AngularJS, porque, caso contrário, o usuário faria o download de 24mb de arquivos no carregamento da primeira página (e isso ocorre com os arquivos uglificados e concatenados). Portanto, sim, em aplicativos complexos, não basta concatenar todas as seções, quando há seções que o usuário não abre a cada visita.
ngDeveloper
136

Sim, faz sentido.

Os módulos angulares não tentam resolver o problema da ordem de carregamento de scripts ou da busca lenta de scripts. Esses objetivos são ortogonais e os dois sistemas de módulos podem viver lado a lado e cumprir seus objetivos.

Fonte: Site oficial do Angular JS

Tiago Reis
fonte
6
Se você usar um módulo por arquivo js, ​​poderá carregar seu módulo angular em qualquer ordem. Mas se você deseja colocar, por exemplo, serviços diferentes em arquivos js diferentes, mas deseja anexá-los no mesmo módulo angular, é necessário carregar a declaração do módulo antes da declaração de serviços. Portanto, essa é uma decisão de arquitetura.
Matohawk 22/08
@Tiago: Por favor, forneça um link para o local de onde você o originou. Não consigo encontrar em lugar nenhum. Estou supondo que veio de uma versão anterior dos documentos Angular, antes que os padrões do Angular se tornassem tão bem estabelecidos e antes que se tornasse claro que há vantagens significativas em evitar o Exigir, pelo menos para os componentes Angular.
XML
@XMLilley: você pode fornecer um link que explique as vantagens de evitar o Exigir ao usar o Angular? Eu estou decidindo se deve ou não usar o Require no meu projeto e isso parece útil.
Trevor
1
Não estava claro no meu idioma aqui: há vantagens significativas em alavancar os próprios carregadores de módulos internos da Angular e seguir o padrão dos padrões angulares. A questão não é se deve evitar o Exigir, mas se há valor em adicionar uma camada adicional de complexidade. O que está claro é que os padrões internos do Angular atenderão de maneira fácil e elegante a necessidade do carregamento dos próprios módulos do Angular. Se Require serve para o propósito de carregar módulos fora do contexto Angular, que assim seja. Mas usar Require for Angular é estranho.
XML
6
@XMLilley tudo o que o Angular faz é fornecer injeção de dependência. O carregamento real do módulo é de sua responsabilidade. Você pode fazer isso adicionando uma tag de script, tendo um script de construção ou usando requirejs. O sistema do módulo Angulars não tem opinião sobre isso.
gillesruppert
57

Acredito que isso seja uma questão subjetiva, por isso darei minha opinião subjetiva.

O Angular possui um mecanismo de modularização incorporado. Quando você cria seu aplicativo, a primeira coisa a fazer é

var app = angular.module("myApp");

e depois

app.directive(...);

app.controller(...);

app.service(...);

Se você der uma olhada no angular-seed, que é um ótimo aplicativo inicial para angular, eles separaram as diretivas, serviços, controladores etc. em diferentes módulos e, em seguida, carregaram esses módulos como dependências no seu aplicativo principal.

Algo como :

var app = angular.module("myApp",["Directives","Controllers","Services"];

O Angular também carrega preguiçosamente esses módulos (na memória) e não seus arquivos de script.

Em termos de carregamento lento de arquivos de script, para ser franco, a menos que você esteja escrevendo algo extremamente grande, seria um exagero, porque angular por sua própria natureza reduz a quantidade de código que você escreve. Um aplicativo típico escrito na maioria das outras estruturas pode esperar uma redução de cerca de 30 a 50% no LOC, se escrito em angular.

ganaraj
fonte
5
De fato, é melhor configurar serviços no Angular.js do que carregar módulos com o Require.js. Isso torna mais fácil jogar com o escopo e os serviços $, como joguei com o Socket.io
Marco Godínez
33

O uso do RequireJS com o AngularJS faz sentido, mas apenas se você entender como cada um deles funciona com relação à injeção de dependência , como se ambos injetassem dependências, eles injetariam coisas muito diferentes.

O AngularJS possui seu próprio sistema de dependência que permite injetar módulos AngularJS em um módulo recém-criado para reutilizar implementações. Digamos que você criou um "primeiro" módulo que implementa um filtro AngularJS "greet":

angular
  .module('first', [])
  .filter('greet', function() {
    return function(name) {
      return 'Hello, ' + name + '!';
    }
  });

E agora, digamos que você queira usar o filtro "greet" em outro módulo chamado "segundo" que implementa um filtro "adeus". Você pode fazer isso injetando o módulo "primeiro" no módulo "segundo":

angular
  .module('second', ['first'])
  .filter('goodbye', function() {
    return function(name) {
      return 'Good bye, ' + name + '!';
    }
  });

O fato é que, para fazer isso funcionar corretamente sem o RequireJS, você deve garantir que o "primeiro" módulo AngularJS seja carregado na página antes de criar o "segundo" módulo AngularJS. Citando a documentação:

Dependendo de um módulo, implica que o módulo necessário precise ser carregado antes que o módulo exigido seja carregado.

Nesse sentido, é aqui que o RequireJS pode ajudá-lo, pois o RequireJS fornece uma maneira limpa de injetar scripts na página, ajudando a organizar as dependências de scripts entre si.

Voltando aos módulos AngularJS "primeiro" e "segundo", eis como você pode fazê-lo usando o RequireJS separando os módulos em arquivos diferentes para aproveitar o carregamento de dependências de script:

// firstModule.js file
define(['angular'], function(angular) {
  angular
    .module('first', [])
    .filter('greet', function() {
      return function(name) {
        return 'Hello, ' + name + '!';
      }
    });
});
// secondModule.js file
define(['angular', 'firstModule'], function(angular) {
  angular
    .module('second', ['first'])
    .filter('goodbye', function() {
      return function(name) {
        return 'Good bye, ' + name + '!';
      }
    });
});

Você pode ver que estamos dependendo do arquivo "firstModule" a ser injetado antes que o conteúdo do retorno de chamada RequireJS possa ser executado, o que precisa que o "primeiro" módulo AngularJS seja carregado para criar o "segundo" módulo AngularJS.

Nota lateral: Injetar "angular" nos arquivos "firstModule" e "secondModule" como dependência é necessário para usar o AngularJS dentro da função de retorno de chamada RequireJS e ele deve ser configurado na configuração do RequireJS para mapear "angular" para o código da biblioteca. Você também pode ter o AngularJS carregado na página de maneira tradicional (tag de script), embora isso anule os benefícios do RequireJS.

Mais detalhes sobre como ter o suporte do RequireJS do núcleo do AngularJS da versão 2.0 no meu blog.

Baseado no meu post no blog "Entendendo o RequireJS com o AngularJS" , aqui está o link .

leog
fonte
2
Na verdade, é melhor, ao incluir um link, resumir o conteúdo do link aqui no Stack Overflow. Se o seu link for interrompido, o que ocorre na Internet, sua resposta aqui será inútil para futuros visitantes. Considere uma edição para trazer um resumo e melhorar esta postagem. Boa sorte!
jmort253
3
Lá vai você, obrigado jmort253.
leog
Obrigado por fazer essas edições e explicar como o RequireJS pode ajudar a gerenciar as dependências para evitar problemas com o Angular tentando carregar algo que ainda não existe.
jmort253
concordo totalmente, é melhor usar essa abordagem para aplicativos grandes, caso contrário, você terá várias tags <script> em seu aplicativo.
usar o seguinte comando
21

Como o @ganaraj mencionou, o AngularJS possui injeção de dependência em seu núcleo. Ao criar aplicativos de sementes de brinquedos com e sem o RequireJS, eu pessoalmente descobri que o RequireJS provavelmente era um exagero para a maioria dos casos de uso.

Isso não significa que o RequireJS não seja útil por seus recursos de carregamento de scripts e por manter sua base de código limpa durante o desenvolvimento. A combinação do otimizador r.js ( https://github.com/jrburke/r.js ) com amêndoa ( https://github.com/jrburke/almond ) pode criar uma história de carregamento de script muito pequena. No entanto, como seus recursos de gerenciamento de dependências não são tão importantes com o angular no núcleo do seu aplicativo, você também pode avaliar outras soluções de carregamento de script do lado do cliente (HeadJS, LABjs, ...) ou mesmo do lado do servidor (MVC4 Bundler, ...) para sua aplicação específica.

johlrich
fonte
17

Sim, sim, especialmente para SPAs muito grandes.

Em alguns cenários, o RequireJS é obrigatório. Por exemplo, desenvolvo aplicativos PhoneGap usando o AngularJS, que também usa a API do Google Map. Sem o carregador da AMD, como o RequireJS, o aplicativo simplesmente travava ao ser iniciado quando está offline, pois não pode obter os scripts da API do Google Map. Um carregador AMD me dá a chance de exibir uma mensagem de erro para o usuário.

No entanto, a integração entre AngularJS e RequireJS é um pouco complicada. Criei o angularAMD para tornar esse processo menos doloroso:

http://marcoslin.github.io/angularAMD/

marcoseu
fonte
12

Resposta curta é, faz sentido. Recentemente, isso foi discutido no ng-conf 2014. Aqui está a conversa sobre este tópico:

http://www.youtube.com/watch?v=4yulGISBF8w

Dalorzo
fonte
7

Sim, faz sentido usar o requireJS com Angular. Passei vários dias para testar várias soluções técnicas.

Eu fiz uma semente angular com RequireJS no lado do servidor. Muito simples. Eu uso a notação SHIM para nenhum módulo AMD e não AMD, porque acho muito difícil lidar com dois sistemas diferentes de injeção de dependência.

Uso grunt e r.js para concatenar arquivos js no servidor, dependendo do arquivo de configuração do SHIM (dependência). Portanto, refiro-me apenas a um arquivo js no meu aplicativo.

Para obter mais informações, acesse meu Angular Seed angular do github: https://github.com/matohawk/angular-seed-requirejs

Matohawk
fonte
3

Eu evitaria usar o Require.js. Os aplicativos que eu vi fazer isso acabam com uma confusão de vários tipos de arquitetura de padrão de módulo. AMD, revelador, diferentes tipos de IIFE, etc. Existem outras maneiras de carregar sob demanda, como o mod angular loadOnDemand . A adição de outras coisas apenas preenche seu código cheio de lixo, cria uma baixa relação sinal / ruído e dificulta a leitura do código.

Julia Anne Jacobs
fonte
2

Aqui está a abordagem que eu uso: http://thaiat.github.io/blog/2014/02/26/angularjs-and-requirejs-for-very-large-applications/

A página mostra uma possível implementação do AngularJS + RequireJS, em que o código é dividido por recursos e depois pelo tipo de componente.

Avi Haiat
fonte
3
Mesmo quando o link fornece informações para responder à pergunta, uma explicação sobre o que a página mostra é uma prática recomendada.
juliocesar 26/02
0

Eu acho que depende da complexidade do seu projeto, já que o angular é praticamente modularizado. Seus controladores podem ser mapeados e você pode apenas importar essas classes JavaScript na sua página index.html.

Mas caso o seu projeto fique maior. Ou, se você antecipar esse cenário, integre angular com requirejs. Em este artigo você pode ver um aplicativo de demonstração para essa integração.

lastboy
fonte