¿Tiene sentido usar Require.js con Angular.js? [cerrado]

443

Soy un novato en Angular.js y trato de entender cómo es diferente de Backbone.js ... Solíamos administrar nuestras dependencias de paquetes con Require.js mientras usábamos Backbone. ¿Tiene sentido hacer lo mismo con Angular.js?

Franck
fuente
Otro blog y proyecto semilla: startersquad.com/blog/angularjs-requirejs
iwein
19
No, no use require.js O browserify con Angular.JS simplemente no hay necesidad de hacerlo: AngularJS tiene un sistema de módulos y el uso de otro sistema de módulos por encima hará que su vida sea innecesariamente difícil. He seguido las respuestas en este hilo y he perdido muchas horas en algo que era completamente innecesario. Lea este artículo que explica por qué no: medium.com/@dickeyxxx/…
VitalyB
Lea esto para comprender la diferencia entre módulos angulares y obligatorios juristr.com/blog/2014/07/lazy-angular-modules
pilavdzice
1
Aquí hay un gran video que explica por qué es una buena idea y muestra cómo usar requireJS con angularJS youtube.com/watch?v=4yulGISBF8w#t=142
gskalinskii
2
@VitalyB ¡Buen artículo! Estoy a favor de cargar aplicaciones en piezas pequeñas. No costará nada lo suficientemente pronto . Diablos, no me cuesta nada en este momento.
dsign

Respuestas:

224

Sí, tiene sentido usar angular.jsjunto con el require.jsque puede usar require.jspara modularizar componentes.

Hay un proyecto semilla que utiliza both angular.js and require.js.

Anshu
fuente
108
El proyecto semilla mencionado anteriormente no se ha tocado en un año, por lo que he creado uno nuevo utilizando los últimos AngularJS y RequireJS con soporte completo para pruebas basadas en pruebas testaculares.
tnajdek
2
@tnajdek, actualicé el enlace en la respuesta de Anshu para señalar el que sugieres.
David Rivers
77
Tenga en cuenta que ninguno de esos proyectos semilla cuenta con el respaldo del equipo de Angular. Requerir es un patrón que tiene más sentido en otros contextos, y calzarlo en angular no es, en mi humilde opinión, una práctica recomendada.
XML
2
El libro O'Reilly AngularJS de Brad Green & Shyam Seshadri (publicado en abril de este año) también recomienda agregar RequireJS temprano en el crecimiento de un proyecto Angular, y presenta los detalles con bastante claridad.
bjorke
1
Prefiero hacer todo en tiempo de compilación 1. browserify.org 2. npmjs.org/package/gulp-angular-filesort
A-Dubb
150

Para reafirmar lo que creo que la pregunta del OP realmente es:

Si estoy compilando una aplicación principalmente en Angular 1.x, y (implícitamente) lo hago en la era de Grunt / Gulp / Broccoli y Bower / NPM, y tal vez tenga un par de dependencias de biblioteca adicionales, requiere agregar, claro, específico valor más allá de lo que obtengo al usar Angular sin Requerir?

O, dicho de otra manera:

"¿Vanilla Angular necesita Requerir gestionar la carga básica de componentes Angulares de manera efectiva, si tengo otras formas de manejar la carga básica de scripts? "

Y creo que la respuesta básica a eso es: "no, a menos que tenga algo más que hacer y / o no pueda usar herramientas más nuevas y modernas".

Seamos claros desde el principio: RequireJS es una gran herramienta que resolvió algunos problemas muy importantes y nos inició en el camino en el que estamos, hacia aplicaciones Javascript más escalables y más profesionales. Es importante destacar que fue la primera vez que muchas personas encontraron el concepto de modularización y sacar las cosas del alcance global. Entonces, si va a construir una aplicación Javascript que necesita escalar, entonces Requerir y el patrón AMD no son malas herramientas para hacerlo.

Pero, ¿hay algo en particular en Angular que haga que Require / AMD sea un ajuste particularmente bueno? No. De hecho, Angular le proporciona su propio patrón de modularización y encapsulación, que de muchas maneras hace redundantes las características básicas de modularización de AMD. Y, integrar módulos angulares en el patrón AMD no es imposible, pero es un poco ... complicado. Definitivamente pasarás tiempo haciendo que los dos patrones se integren bien.

Para obtener una perspectiva del equipo Angular en sí, existe esto , de Brian Ford, autor del Angular Batarang y ahora miembro del equipo central de Angular:

No recomiendo usar RequireJS con AngularJS. Aunque es ciertamente posible, no he visto ninguna instancia en la que RequireJS haya sido beneficioso en la práctica.

Entonces, en la pregunta muy específica de AngularJS: Angular y Require / AMD son ortogonales y en lugares superpuestos. Usted puede utilizarlos juntos, pero no hay ninguna razón específica relacionada con la naturaleza / patrones de sí angular.

Pero, ¿qué pasa con la gestión básica de dependencias internas y externas para aplicaciones JavaScript escalables? ¿No requiere hacer algo realmente crítico para mí allí?

Recomiendo revisar Bower y NPM, y particularmente NPM. No estoy tratando de comenzar una guerra santa sobre los beneficios comparativos de estas herramientas. Simplemente quiero decir: hay otras formas de desollar a ese gato, y esas formas pueden ser incluso mejores que AMD / Require. (Ciertamente tienen un impulso mucho más popular a fines de 2015, particularmente NPM, combinado con módulos ES6 o CommonJS. Consulte la pregunta SO relacionada ).

¿Qué pasa con la carga perezosa?

Tenga en cuenta que la carga diferida y la descarga diferida son diferentes. La carga diferida de Angular no significa que los esté sacando directamente del servidor. En una aplicación de estilo Yeoman con automatización javascript, estás concatenando y minimizando todo el shebang en un solo archivo. Están presentes, pero no se ejecutan / instancian hasta que se necesitan. Las mejoras de velocidad y ancho de banda que obtienes al hacer esto superan enormemente cualquier supuesta mejora de la descarga diferida de un controlador de 20 líneas en particular. De hecho, la latencia de red desperdiciada y la sobrecarga de transmisión para ese controlador será un orden de magnitud mayor que el tamaño del controlador en sí.

Pero supongamos que realmente necesita una descarga lenta, tal vez para piezas de su aplicación que se usan con poca frecuencia, como una interfaz de administración. Ese es un caso muy legítimo. Requerir puede hacer eso por usted. Pero hay también muchos otros , potencialmente más flexibles opciones que logran la misma cosa. Y Angular 2.0 aparentemente se encargará de esto por nosotros, integrado en el enrutador . ( Detalles )

Pero, ¿qué pasa durante el desarrollo en mi dev boxen local?

¿Cómo puedo cargar todas mis docenas / cientos de archivos de script sin necesidad de adjuntarlos a index.html manualmente?

Eche un vistazo a los subgeneradores en el generador angular de Yeoman, o en los patrones de automatización incorporados en generador-trago-angular , o en la automatización estándar de Webpack para React. Estos le proporcionan una forma limpia y escalable de: adjuntar automáticamente los archivos en el momento en que los componentes se andamian, o simplemente tomarlos automáticamente si están presentes en ciertas carpetas / hacer coincidir ciertos patrones globales. Nunca más tendrá que pensar en su propia carga de script una vez que tenga las últimas opciones.

¿Línea de fondo?

Requerir es una gran herramienta, para ciertas cosas. Pero vaya con el grano siempre que sea posible, y separe sus preocupaciones siempre que sea posible. Deje que Angular se preocupe por el patrón de modularización propio de Angular, y considere usar módulos ES6 o CommonJS como patrón de modularización general. Deje que las herramientas de automatización modernas se preocupen por la carga de scripts y la gestión de dependencias. Y cuide la carga lenta asincrónica de forma granular, en lugar de enredarla con las otras dos preocupaciones.

Dicho esto, si está desarrollando aplicaciones Angular pero no puede instalar Node en su máquina para utilizar herramientas de automatización de Javascript por alguna razón, entonces Requerir puede ser una buena solución alternativa. Y he visto configuraciones realmente elaboradas donde las personas quieren cargar dinámicamente componentes angulares que declaran cada uno sus propias dependencias o algo así. Y aunque probablemente trataría de resolver ese problema de otra manera, puedo ver los méritos de la idea, para esa situación muy particular.

Pero de lo contrario ... al comenzar desde cero con una nueva aplicación Angular y flexibilidad para crear un entorno de automatización moderno ... tiene muchas otras opciones más flexibles y modernas.

(Actualizado varias veces para mantenerse al día con la evolución de la escena JS).

XML
fuente
1
El proyecto semilla NG-Boilerplate ( github.com/ngbp/ngbp ) también crea una aplicación web de una sola página con un archivo js. El uso de un manifiesto HTML5 garantiza que este archivo solo se cargue una vez por versión.
Federico Elles
2
Aunque, como siempre, <i> depende </i>. Muchas personas usan Require para toda su arquitectura y necesitan integrar Angular en ese ecosistema. Es una situación muy diferente a cuando estás creando aplicaciones de forma aislada.
Dave Nichol
2
Convenido. Pero el objetivo del OP parece ser: "Si estoy construyendo una aplicación principalmente en Angular, y (implícitamente) lo hago en la era de Grunt, y tal vez tenga un par de dependencias adicionales de la biblioteca, Requiere agregar un valor claro y específico más allá ¿Qué obtengo al usar Angular sin Requerir? " Y creo que la respuesta es: no. Si tiene una aplicación enorme con 40 dependencias externas, o no puede controlar su entorno de CI, o su jefe adora Requerir, o adora Requerir, o Angular es solo una pieza de una aplicación más grande, etc., etc., entonces YMMV.
XML
1
Pero como no parece hacer esas preguntas, y dado que simplemente menciona el contexto alternativo de una aplicación Backbone, parece preguntarse: "¿Vanilla Angular necesita Requerir gestionar sus componentes de manera efectiva?" Y la respuesta es: "no, a menos que tenga algo más que hacer". Además, esta pregunta surgió en la cúspide del movimiento de CI de Javascript, en el que obtuvimos formas mucho mejores de manejar la 'carga de script' básica y física. Si tiene resuelto ese problema, Requerir se trata básicamente de coincidencia de dependencias y encapsulación. Angular hace ambas cosas por ti.
XML
Google usa la carga diferida en algunos de sus proyectos AngularJS, porque de lo contrario, el usuario descargaría 24mb de archivos en la primera carga de la página (y esto es con archivos uglificados y concatenados). Entonces, sí, en aplicaciones complejas no se trata solo de concatenar todas las secciones, cuando hay secciones que el usuario no abrirá con cada visita.
ngDeveloper
136

Si, tiene sentido.

Los módulos angulares no intentan resolver el problema del ordenamiento de carga de scripts o la recuperación de scripts perezosos. Estos objetivos son ortogonales y ambos sistemas de módulos pueden convivir y cumplir sus objetivos.

Fuente: sitio web oficial de Angular JS

Tiago Reis
fuente
66
Si usa un módulo por archivo js, ​​puede cargar su módulo angular en cualquier orden. Pero si desea poner, por ejemplo, diferentes servicios en diferentes archivos js pero desea adjuntarlos en el mismo módulo angular, debe cargar la declaración del módulo antes de la declaración de servicios. Entonces esta es una decisión de arquitectura.
Matohawk
@Tiago: proporcione un enlace a la ubicación de donde lo obtuvo. No puedo encontrarlo por ninguna parte. Supongo que provino de una versión anterior de los documentos de Angular, antes de que los patrones de Angular se hubieran establecido tan bien, y antes de que quedara claro que existen ventajas significativas para evitar Requerir, al menos para los componentes de Angular.
XML
@XMLilley: ¿puede proporcionar un enlace que explique las ventajas de evitar Requerir al usar Angular? Estoy decidiendo si usar o no Requerir en mi proyecto y parece que sería útil.
Trevor
1
No estaba claro en mi idioma aquí: hay ventajas significativas en aprovechar los cargadores de módulos integrados de Angular y seguir el patrón de los patrones de Angular. La pregunta no es si se debe evitar Requerir, sino más bien si tiene valor agregar una capa adicional de complejidad. Lo que está claro es que los patrones integrados de Angular abordarán de manera fácil y elegante la necesidad de cargar los propios módulos de Angular. Si Requerir sirve para cargar módulos fuera del contexto angular, entonces que así sea. Pero usar Require for Angular es extraño.
XML
66
@XMLilley todo lo que Angular hace es darle una inyección de dependencia. La carga real del módulo es su responsabilidad. Puede hacerlo agregando una etiqueta de script, teniendo un script de compilación o usando requirejs. El sistema de módulos angulares no tiene una opinión al respecto.
gillesruppert
57

Esto creo que es una pregunta subjetiva, por lo que proporcionaré mi opinión subjetiva.

Angular tiene un mecanismo de modularización incorporado. Cuando crea su aplicación, lo primero que haría es

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

y entonces

app.directive(...);

app.controller(...);

app.service(...);

Si echa un vistazo a la semilla angular, que es una aplicación de inicio ordenada para angular, han separado las directivas, servicios, controladores, etc.en diferentes módulos y luego cargaron esos módulos como dependencias de su aplicación principal.

Algo como :

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

Angular también lazy carga estos módulos (en la memoria), no sus archivos de script.

En términos de archivos de script de carga diferida, para ser sincero, a menos que esté escribiendo algo extremadamente grande, sería una exageración porque angular por su propia naturaleza reduce la cantidad de código que escribe. Una aplicación típica escrita en la mayoría de los otros marcos podría esperar una reducción de alrededor del 30-50% en LOC si se escribe en angular.

ganaraj
fuente
55
De hecho, es mejor configurar servicios en Angular.js que cargar módulos con Require.js. Esto hace que sea más fácil jugar con $ scope y servicios, como jugué con Socket.io
Marco Godínez
33

El uso de RequireJS con AngularJS tiene sentido, pero solo si comprende cómo funciona cada uno de ellos con respecto a la inyección de dependencia , ya que si bien ambos inyectan dependencias, inyectan cosas muy diferentes.

AngularJS tiene su propio sistema de dependencia que le permite inyectar módulos AngularJS en un módulo recién creado para reutilizar implementaciones. Digamos que creó un "primer" módulo que implementa un "saludo" del filtro AngularJS:

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

Y ahora digamos que desea utilizar el filtro "saludar" en otro módulo llamado "segundo" que implementa un filtro "adiós". Puede hacer eso inyectando el "primer" módulo al "segundo" módulo:

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

Lo importante es que para que esto funcione correctamente sin RequireJS, debe asegurarse de que el "primer" módulo AngularJS esté cargado en la página antes de crear el "segundo" módulo AngularJS. Documentación de cita:

Dependiendo de un módulo implica que el módulo requerido debe cargarse antes de cargar el módulo requerido.

En ese sentido, aquí es donde RequireJS puede ayudarlo, ya que RequireJS proporciona una forma limpia de inyectar guiones en la página, ayudándoles a organizar las dependencias de guiones entre sí.

Volviendo a los módulos "primero" y "segundo" de AngularJS, así es cómo puede hacerlo utilizando RequireJS que separa los módulos en diferentes archivos para aprovechar la carga de dependencias 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 + '!';
      }
    });
});

Puede ver que dependemos del archivo "firstModule" que se inyectará antes de que se pueda ejecutar el contenido de la devolución de llamada RequireJS que necesita cargar el "primer" módulo AngularJS para crear el "segundo" módulo AngularJS.

Nota al margen: la inyección de "angular" en los archivos "firstModule" y "secondModule" como dependencia es necesaria para utilizar AngularJS dentro de la función de devolución de llamada RequireJS y debe configurarse en la configuración RequireJS para asignar "angular" al código de la biblioteca. Es posible que AngularJS se cargue en la página de manera tradicional también (etiqueta de script), aunque anula los beneficios de RequireJS.

Más detalles sobre la compatibilidad con RequireJS del núcleo de AngularJS desde la versión 2.0 en mi publicación de blog.

Basado en mi publicación de blog "Dando sentido a RequireJS con AngularJS" , aquí está el enlace .

leog
fuente
2
En realidad, es mejor, cuando se incluye un enlace, resumir el contenido del enlace aquí en Stack Overflow. Si su enlace se rompiera alguna vez, lo que hacen los enlaces en Internet, su respuesta aquí sería inútil para futuros visitantes. Considere una edición para traer un resumen y mejorar esta publicación. ¡Buena suerte!
jmort253
3
Ahí tienes, gracias jmort253.
Leog
Gracias por hacer estas ediciones y explicar cómo RequireJS puede ayudar a administrar las dependencias para evitar problemas con Angular que intenta cargar algo que aún no existe.
jmort253
Estoy totalmente de acuerdo, es mejor utilizar este enfoque para aplicaciones grandes, de lo contrario tendrá múltiples etiquetas <script> en su aplicación.
I.Tyger
21

Como @ganaraj mencionó, AngularJS tiene la inyección de dependencia en su núcleo. Al construir aplicaciones de semillas de juguete con y sin RequireJS, personalmente encontré que RequireJS probablemente era excesivo para la mayoría de los casos de uso.

Eso no significa que RequireJS no sea útil por sus capacidades de carga de scripts y por mantener limpia su base de código durante el desarrollo. La combinación del optimizador r.js ( https://github.com/jrburke/r.js ) con almendra ( https://github.com/jrburke/almond ) puede crear una historia de carga de script muy delgada. Sin embargo, dado que sus características de administración de dependencias no son tan importantes con angular en el núcleo de su aplicación, también puede evaluar otras soluciones de carga de script del lado del cliente (HeadJS, LABjs, ...) o incluso del lado del servidor (MVC4 Bundler, ...) para su aplicación particular

johlrich
fuente
17

Sí, especialmente para SPA muy grandes.

En algún escenario, RequireJS es imprescindible. Por ejemplo, desarrollo aplicaciones PhoneGap usando AngularJS que también usa Google Map API. Sin el cargador AMD como RequireJS, la aplicación simplemente se bloqueará al iniciarse cuando esté desconectada, ya que no puede obtener los scripts de la API de Google Map. Un cargador AMD me da la oportunidad de mostrar un mensaje de error al usuario.

Sin embargo, la integración entre AngularJS y RequireJS es un poco complicada. Creé angularAMD para hacer que este sea un proceso menos doloroso:

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

marcoseu
fuente
7

Sí, tiene sentido usar requireJS con Angular, pasé varios días para probar varias soluciones técnicas.

Hice una semilla angular con RequireJS en el lado del servidor. Muy simple Uso la notación SHIM para ningún módulo AMD y no AMD porque creo que es muy difícil lidiar con dos sistemas de inyección de dependencia diferentes.

Uso grunt y r.js para concatenar archivos js en el servidor depende del archivo de configuración (dependencia) de SHIM. Así que solo remito un archivo js en mi aplicación.

Para obtener más información, vaya a mi semilla angular github: https://github.com/matohawk/angular-seed-requirejs

Matohawk
fuente
3

Evitaría usar Require.js. Las aplicaciones que he visto que hacen esto terminan en un lío de múltiples tipos de arquitectura de patrones de módulos. AMD, Revelador, diferentes sabores de IIFE, etc. Hay otras formas de cargar bajo demanda, como el mod angular loadOnDemand . Agregar otras cosas solo llena su código lleno de cruft y crea una baja relación señal / ruido y hace que su código sea difícil de leer.

Julia Anne Jacobs
fuente
0

Creo que depende de la complejidad de su proyecto, ya que angular está bastante modularizado. Sus controladores se pueden asignar y puede importar esas clases de JavaScript en su página index.html.

Pero en caso de que su proyecto sea más grande. O anticipa ese escenario, debe integrar angular con requirejs. En este artículo, puede ver una aplicación de demostración para dicha integración.

lastboy
fuente