javascript - Gir det mening å bruke Require.js med Angular.js?
Jeg er nybegynner i Angular.js og prøver å forstå hvordan det er forskjellig fra Backbone.js... Vi pleide å håndtere våre pakkeavhengigheter med Require.js mens vi brukte Backbone. Gir det mening å gjøre det samme med Angular.js?
Svar #1
Ja, det gir mening å bruke angular.js sammen med require.js hvor du kan bruke require.js for å modulere komponenter.
Det finnes et startprosjekt som bruker både angular.js og require.js.
Svar #2
For å gjenta det jeg tror OPs spørsmål egentlig er:
Hvis jeg bygger en applikasjon hovedsakelig i Angular 1.x, og (implisitt) gjør det i epoken med Grunt/Gulp/Broccoli og Bower/NPM, og jeg kanskje har et par ekstra biblioteksavhengigheter, tilfører Require tydelig, spesifikk verdi utover det jeg får ved å bruke Angular uten Require?
Eller, sagt på en annen måte:
«Trenger vanlig Angular Require for å håndtere grunnleggende Angular-komponentlasting effektivt, hvis jeg har andre måter å håndtere grunnleggende skriptlasting på?»
Og jeg tror det grunnleggende svaret på det er: "ikke med mindre du har noe annet på gang, og/eller du ikke kan bruke nyere, mer moderne verktøy."
La oss være klare fra starten av: RequireJS er et flott verktøy som løste noen svært viktige problemer, og som startet oss på veien vi er på, mot mer skalerbare, mer profesjonelle Javascript-applikasjoner. Viktigere er det at det var første gang mange mennesker møtte konseptet med modularisering og å få ting ut av globalt omfang. Så, hvis du skal bygge en Javascript-applikasjon som må kunne skaleres, er Require og AMD-mønsteret ikke dårlige verktøy for å gjøre det.
Men, er det noe spesielt med Angular som gjør Require/AMD spesielt egnet? Nei. Faktisk gir Angular deg sitt eget modulær- og kapslingsmønster, som på mange måter gjør de grunnleggende modulærfunksjonene i AMD overflødige. Og å integrere Angular-moduler i AMD-mønsteret er ikke umulig, men det er litt... vrient. Du vil definitivt bruke tid på å få de to mønstrene til å fungere godt sammen.
For litt perspektiv fra Angular-teamet selv, finnes dette, fra Brian Ford, forfatter av Angular Batarang og nå medlem av Angular-kerneteamet:
Jeg anbefaler ikke å bruke RequireJS med AngularJS. Selv om det absolutt er mulig, har jeg ikke sett noen tilfelle hvor RequireJS var nyttig i praksis.
Så, når det gjelder det veldig spesifikke spørsmålet om AngularJS: Angular og Require/AMD er ortogonale, og noen steder overlappende. Du kan bruke dem sammen, men det er ingen grunn som spesifikt er relatert til naturen/mønstrene til Angular selv.
Men hva med grunnleggende håndtering av interne og eksterne avhengigheter for skalerbare Javascript-applikasjoner? Gjør ikke Require noe virkelig kritisk for meg der?
Jeg anbefaler å sjekke ut Bower og NPM, og spesielt NPM. Jeg prøver ikke å starte en hellig krig om de relative fordelene med disse verktøyene. Jeg vil bare si: det finnes andre måter å gjøre det på, og disse måtene kan være enda bedre enn AMD/Require. (De har absolutt mye mer populær framdrift mot slutten av 2015, spesielt NPM, kombinert med ES6- eller CommonJS-moduler. Se relaterte SO-spørsmål.)
Hva med lat lasting?
Merk at lat-lasting og lat-nedlasting er forskjellige. Angulars lat-lasting betyr ikke at du henter dem direkte fra serveren. I en Yeoman-stil applikasjon med JavaScript-automatisering, blir alt sammenkjedet og minifisert til en enkelt fil. De er til stede, men blir ikke kjørt/instansiert før det trengs. Hastighets- og båndbreddeforbedringene du får ved å gjøre dette overgår langt, langt alle påståtte forbedringer fra lat-nedlasting av en bestemt controller på 20 linjer. Faktisk vil den bortkastede nettverksforsinkelsen og overføringskostnaden for den controlleren være en størrelsesorden større enn størrelsen på controlleren selv.
Men la oss si at du virkelig trenger treg-nedlasting, kanskje for sjelden brukte deler av applikasjonen din, slik som et administrasjonsgrensesnitt. Det er et veldig legitimt tilfelle. Require kan faktisk gjøre det for deg. Men det finnes også mange andre, potensielt mer fleksible alternativer som oppnår det samme. Og Angular 2.0 vil tydeligvis ta seg av dette for oss, innebygd i ruteren. (Detaljer.)
Men hva med under utvikling på min lokale dev-boks?
Hvordan kan jeg få alle mine dusinvis/hundrevis av skriptfiler lastet uten å måtte legge dem alle til i index.html manuelt?
Ta en titt på sub-generatorene i Yeomans generator-angular, eller på automatiseringsmønstrene som er innarbeidet i generator-gulp-angular, eller på standard Webpack-automatisering for React. Disse gir deg en ren, skalerbar måte å enten: automatisk legge til filene når komponentene bygges, eller ganske enkelt hente dem alle automatisk hvis de finnes i bestemte mapper/passer med bestemte glob-mønstre. Du trenger aldri igjen å tenke på din egen skriptlasting når du har de sistnevnte alternativene.
Bunnlinje?
Require er et flott verktøy for visse ting. Men følg strømmen når det er mulig, og skill dine bekymringer når det er mulig. La Angular ta seg av Angulars egen modulering, og vurder å bruke ES6-moduler eller CommonJS som et generelt moduleringmønster. La moderne automatiseringsverktøy ta seg av scriptlasting og avhengighetsstyring. Og ta hånd om asynkron lat-lasting på en detaljert måte, i stedet for å blande det med de to andre bekymringene.
Når det er sagt, hvis du utvikler Angular-apper, men ikke kan installere Node på maskinen din for å bruke Javascript-automatiseringsverktøy av en eller annen grunn, kan Require være en god alternativ løsning. Og jeg har sett virkelig omfattende oppsett der folk ønsker å dynamisk laste Angular-komponenter som hver erklærer sine egne avhengigheter eller noe. Og selv om jeg sannsynligvis ville prøvd å løse det problemet på en annen måte, kan jeg se fordelene med ideen, for akkurat den spesifikke situasjonen.
Men ellers... når man starter fra bunnen av med en ny Angular-applikasjon og har fleksibilitet til å lage et moderne automatiseringsmiljø... har man mange andre, mer fleksible, mer moderne alternativer.
(Oppdatert gjentatte ganger for å holde tritt med den utviklende JS-scenen.)
Svar #3
Ja, det gir mening.
Angular-moduler prøver ikke å løse problemet med rekkefølgen på skriptinnlasting eller forsinket skripthenting. Disse målene er ortogonale, og begge modul-systemene kan eksistere side om side og oppfylle sine mål.
Kilde: Angular JS offisielle nettsted
Svar #4
Dette tror jeg er et subjektivt spørsmål, så jeg vil gi min subjektive mening.
Angular har en moduliseringsmekanisme innebygd. Når du oppretter appen din, er det første du ville gjort
var app = angular.module("myApp");
og så
app.directive(...);
app.controller(...);
app.service(...);
Hvis du tar en titt på angular-seed, som er en ryddig startapp for Angular, har de skilt ut direktiver, tjenester, kontrollere osv. i forskjellige moduler, og deretter lastet disse modulene som avhengigheter på hovedappen din.
Noe som:
var app = angular.module("myApp",["Directives","Controllers","Services"];
Angular laster også disse modulene tregt (inn i minnet), ikke deres skriptfiler.
Når det gjelder lat lasting av skriptfiler, for å være ærlig, med mindre du skriver noe ekstremt stort, ville det være overkill fordi Angular av sin natur reduserer mengden kode du skriver. En typisk app skrevet i de fleste andre rammeverk kan forvente en reduksjon på rundt 30-50 % i kodelinjer hvis den skrives i Angular.
Svar #5
Å bruke RequireJS med AngularJS gir mening, men bare hvis du forstår hvordan hver av dem fungerer når det gjelder dependency injection, siden selv om begge injiserer avhengigheter, injiserer de veldig forskjellige ting.
AngularJS har sitt eget avhengighetssystem som lar deg injisere AngularJS-moduler til en nyopprettet modul for å gjenbruke implementeringer. La oss si at du opprettet en "first"-modul som implementerer et AngularJS-filter "greet":
angular
.module('first', [])
.filter('greet', function() {
return function(name) {
return 'Hello, ' + name + '!';
}
});
Og la oss nå si at du vil bruke "greet"-filteret i en annen modul kalt "second" som implementerer et "goodbye"-filter. Du kan gjøre det ved å injisere "first"-modulen i "second"-modulen:
angular
.module('second', ['first'])
.filter('goodbye', function() {
return function(name) {
return 'Good bye, ' + name + '!';
}
});
Saken er at for å få dette til å fungere riktig uten RequireJS, må du sørge for at den "første" AngularJS-modulen lastes på siden før du oppretter den "andre" AngularJS-modulen. Sitat fra dokumentasjonen:
Å være avhengig av en modul innebærer at den nødvendige modulen må lastes før den modul som krever den blir lastet.
I den forstand er dette stedet hvor RequireJS kan hjelpe deg, siden RequireJS gir en ryddig måte å injisere skript på siden på, og hjelper deg med å organisere skriptafhengigheter mellom hverandre.
Når vi går tilbake til de "første" og "andre" AngularJS-modulene, her er hvordan du kan gjøre det ved å bruke RequireJS og separere modulene i forskjellige filer for å utnytte lasting av skriptavhengigheter:
// 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 + '!';
}
});
});
Du kan se at vi er avhengige av at filen "firstModule" blir injisert før innholdet i RequireJS-callbacken kan kjøres, noe som krever at "first" AngularJS-modulen blir lastet for å opprette "second" AngularJS-modul.
Side note: Å injisere "angular" på filene "firstModule" og "secondModule" som avhengighet er nødvendig for å bruke AngularJS inne i RequireJS callback-funksjonen, og det må konfigureres i RequireJS-konfigurasjonen for å mappe "angular" til bibliotekskoden. Du kan også ha AngularJS lastet inn på siden på en tradisjonell måte (script-tag), selv om det undergraver fordelene med RequireJS.
Flere detaljer om å ha RequireJS-støtte fra AngularJS-kjernen fra versjon 2.0 på blogginnlegget mitt.
Baseret på blogginnlegget mitt "Making sense of RequireJS with AngularJS", her er lenken.
Svar #6
Som @ganaraj nevnte, har AngularJS avhengighetsinjeksjon som kjerne. Når jeg bygde små prøveapplikasjoner med og uten RequireJS, fant jeg personlig at RequireJS sannsynligvis var overkill for de fleste bruksområder.
Det betyr ikke at RequireJS ikke er nyttig for dets skriptlastingsmuligheter og for å holde kodebasen ryddig under utvikling. Å kombinere r.js-optimalisatoren (https://github.com/jrburke/r.js) med almond (https://github.com/jrburke/almond) kan skape en veldig slank skriptlastingsløsning. Siden avhengighetsstyringsfunksjonene likevel ikke er like viktige med Angular i kjernen av applikasjonen din, kan du også vurdere andre klientbaserte (HeadJS, LABjs, ...) eller til og med serverbaserte (MVC4 Bundler, ...) skriptlastingsløsninger for din spesifikke applikasjon.
Svar #7
Ja, det gjør det, spesielt for veldig store SPA.
I noen scenarioer er RequireJS et must. For eksempel utvikler jeg PhoneGap-applikasjoner ved hjelp av AngularJS som også bruker Google Maps API. Uten en AMD-loader som RequireJS, ville appen rett og slett krasje ved oppstart når den er offline siden den ikke kan hente Google Maps API-skriptene. En AMD-loader gir meg en mulighet til å vise en feilmelding til brukeren.
Integrasjon mellom AngularJS og RequireJS er imidlertid litt tricky. Jeg laget angularAMD for å gjøre dette til en mindre smertefull prosess:
http://marcoslin.github.io/angularAMD/
Svar #8
Kort sagt, det gir mening. Dette ble nylig diskutert på ng-conf 2014. Her er foredraget om dette emnet:
http://www.youtube.com/watch?v=4yulGISBF8w
