angularjs deployment essentials -...
Post on 13-Feb-2018
233 Views
Preview:
TRANSCRIPT
TableofContents
AngularJSDeploymentEssentials
Credits
AbouttheAuthor
AbouttheReviewers
www.PacktPub.com
Supportfiles,eBooks,discountoffers,andmore
Whysubscribe?
FreeaccessforPacktaccountholders
Preface
Whatthisbookcovers
Whatyouneedforthisbook
Whothisbookisfor
Conventions
Readerfeedback
Customersupport
Errata
Piracy
Questions
1.OurAppandToolStack
Therighttoolsforthejob
VersioncontrolwithGitandGitHub
Node.js
NPM
Yeoman’sworkflow
Yo
InstallingYo
Grunt
Bower
TheIonicframework
www.allitebooks.com
Batarang
SublimeTextandEditorintegration
Krakn
SettingupGitandGitHub
ScaffoldingtheappwithYo
Development
Views,controllers,androutes
Theloginview
Thechatview
Theaccountview
Themenuview
Theaboutview
Globalcontrollerconstants
Modelsandservices
Predeployment
Summary
2.DeployingtoApache
Fromlocaltoremote
Deploymentdestination
Acomparisonbetweenthelocalandremotesetup
Manualdeployment
FTPingfromyourcommandline
FTPclients
AutomatingdeploymentwithGitHubandSSH
Troubleshootingdeploymentissues
Avisualdifftool
UsingdiffwithGit
ConfiguringApacheforAngular
Google’sPageSpeedServiceforApache
Summary
3.DeployingtoHeroku
www.allitebooks.com
SettingupyourHerokuenvironment
Creatinganaccount
Heroku’sdashboard
Defininganewapplication
TheHerokuToolbelt
Installation
SSHaccess
NewappinToolbelt
Newappindashboard
Herokubranch
Predeploymentconfiguration
Express
Gzippo
Package.json
TheProcfile
Web.js
ScalinganddeployingtoHeroku
Dynos
Scalability
Add-ons
Troubleshootingdeploymentissues
Summary
4.DeployingtoFirebaseHosting
TheFirebasesetup
CreatingyourFirebaseaccount
UsingtheFirebaseForgedashboard
UsingtheDataview
UsingtheSecurityRulesview
UsingtheSimulatorview
UsingtheAnalyticsview
UsingtheSimpleLoginview
www.allitebooks.com
Hostingyourapplication
Usingthefirebase-toolsCLI
ConfiguringyourFirebaseenvironment
Troubleshootingdeploymentissues
HTTPresourcesservedoverHTTPS
Summary
5.DeployingaMobileApp
Contextistheking
WhatisApacheCordovaandhowdoesitaddressissues?
ConfiguringyourdevelopmentenvironmentforApacheCordova
AwordonCordova’sdependencies
InstallingApacheCordova
InstallingtheAndroidSDK
ConfiguringtheAndroidSDKandtools
OSXconfiguration
Windowsconfiguration
InstallinganAndroidtargetandcreatinganemulator
FromAngularwebapplicationstohybridmobileappswithCordova
Deployingyourapptoanemulator
Movingyourcodeinto/www
DeployingyourapptoyourphysicaldevicewithCordova
FromAngularwebapplicationstomobileappswiththeCordovaChromeApptoolchain
ConfiguringyourdevelopmentenvironmentfortheCordovaChromeApptoolchain
PackagingyourAngularwebapplicationformobilewithCCA
FromAngularwebapplicationstomobileappswithPhoneGapBuild
Publishingyourapplication
Signingyour.apkfile
PublishingtotheGooglePlayStore
Troubleshootingdeploymentissues
Summary
6.DeployingasChromeApps
www.allitebooks.com
WhyChromeApps?
Choosingthebestapptype
TheChromeAppsetup
AugmentingyourAngularAppforChrome
Themanifest.jsonfile
Icons
Contentsecuritypolicy
Otherwaystocustomizeyourmanifest.jsonfile
Thebackground.jsfile
DeployingtoyourChromeinstance
Troubleshootingdeploymentissues
DeployingtotheChromeWebStore
Summary
7.Postdeployment
Featuresandfixes
AddingsupporttoGoogleAnalytics
Settinguptheangular-google-analyticsmodule
DeployingupdatestoApache
TheFTPcommand-lineinterface
AnFTPclient
GitandSSH
DeployingupdatestoHeroku
DeployingupdatestoFirebaseHosting
Deployingupdatestomobileapps
DeployingupdatestothelocalemulatorwithCordova
DeployingupdatestothephysicaldevicewithCordova
DeployingupdatestothelocalemulatorwithCCA
DeployingupdatestothephysicaldevicewithCCA
BuildingupdateswithPhoneGapBuild
DeployingupdatestoGooglePlayStore
DeployingupdatestoChromeApp
www.allitebooks.com
PackingupdateswithyourlocalChromeinstance
DeployingupdatestotheChromeWebStore
Summary
8.Conclusion–AngularJSDeploymentEssentials
Developingadynamictoolstack
Deployingearlyanddeploying
Index
www.allitebooks.com
AngularJSDeploymentEssentialsCopyright©2015PacktPublishing
Allrightsreserved.Nopartofthisbookmaybereproduced,storedinaretrievalsystem,ortransmittedinanyformorbyanymeans,withoutthepriorwrittenpermissionofthepublisher,exceptinthecaseofbriefquotationsembeddedincriticalarticlesorreviews.
Everyefforthasbeenmadeinthepreparationofthisbooktoensuretheaccuracyoftheinformationpresented.However,theinformationcontainedinthisbookissoldwithoutwarranty,eitherexpressorimplied.Neithertheauthor,norPacktPublishing,anditsdealersanddistributorswillbeheldliableforanydamagescausedorallegedtobecauseddirectlyorindirectlybythisbook.
PacktPublishinghasendeavoredtoprovidetrademarkinformationaboutallofthecompaniesandproductsmentionedinthisbookbytheappropriateuseofcapitals.However,PacktPublishingcannotguaranteetheaccuracyofthisinformation.
Firstpublished:February2015
Productionreference:1250215
PublishedbyPacktPublishingLtd.
LiveryPlace
35LiveryStreet
BirminghamB32PB,UK.
ISBN978-1-78398-358-2
www.packtpub.com
CreditsAuthor
ZachariahMoreno
Reviewers
KentC.Dodds
LadislavGažo
K.AavaRani
CommissioningEditor
AndrewDuckworth
AcquisitionEditors
RichardHarvey
JamesJones
ContentDevelopmentEditor
AdrianRaposo
TechnicalEditors
RuchiDesai
RosmyGeorge
CopyEditors
RashmiSawant
AshwatiThampi
ProjectCoordinator
KinjalBari
Proofreaders
MariaGould
PaulHindle
ChrisSmith
Indexer
RekhaNair
Graphics
DishaHaria
AbhinashSahu
AbouttheAuthorZachariahMorenoisa23-year-oldwebdeveloperfromSacramento,California,whoworksforthestategovernmentandenjoyscontributingtoopensourceprojectsofthewebvariety.ZachcompletedaninternshipwithGooglein2012andgraduatedwithhisBSinwebdevelopmentfromtheArtInstituteofCalifornia—Sacramento,inthefollowingyear.HehaspublishedanarticleentitledAngularJSToolStackinSoftwareDeveloper’sJournal.ZachcantypicallybefoundonGoogle+discussingdesign,developertools,workflow,camping,golf,andhisEnglishbulldog,Gladstone.
AbouttheReviewersKentC.DoddsisafrontendsoftwareengineeratAlianza,Inc.He’sactivelyinvolvedinthefrontendcommunityonTwitter(@kentcdodds)andthroughhisvariousprojectsonGitHub(kentcdodds).HeisacohosttoAngularAir,alivevideopodcastallaboutAngularJS.HeisalsoaninstructoratEgghead.io(https://egghead.io/),asitededicatedtobite-sizedvideosteachingwebdevelopmentskills.Hespendsmostofhisfreetimewithhiswifeandtwokidsorcoding.
IwouldliketothankDomoTechnologiesforgettingmestartedonfrontendwebdevelopmentaswellasAngular.Iwouldliketothankmywife,Brooke,forherpatiencewhileIworkedonthisbook,andalltheotherprojectsthathaveoccupiedmytime.
LadislavGažoisalong-timecomputerenthusiastandhasbeendiggingintothesoftwareworldsincehisyouth.Hehasmorethan12yearsofprofessionalexperienceindevelopmentandsoftwareengineering.Whilestartingexperimentswithcomputergraphicsandnetworkadministration,herealizedthetruepathistowardthecombinationofsoftwareengineeringandbusiness.Hehasbeendeveloping,analyzing,andarchitectingJava-based,desktop-based,andfinally,modernweb-basedsolutionsforseveralyears.TheapplicationoftheAgileapproachandadvancedtechnologyisbothhishobbyanddailyjob.
RichexperiencewithvarioustechnologiesledhimtocofoundSeges,asoftwaredevelopmentcompanyinSlovakia.Heactivelyparticipatesinstart-upeventsandhelpsbuilddevelopmentcommunities,namelyGoogleDeveloperGroupandJavaGroup,inSlovakia.Withhiscolleagues,hedesignedandspunoffaninteractivecontentmanagementsolutioncalledSynapso,utilizingcontemporarytechnologiescombinedwithuserexperienceinmind.
HehasalsoworkedonthebooksLearningApacheKaraf,ApacheKarafCookbook,andLearningKarafCellar,allbyPacktPublishing.
Iwouldnothavebeenabletorealizemyknowledgeaspartofthereviewprocessofthisbookwithoutthesupportofallmycolleagues,friends,andfamily.Creatingagoodlong-termenvironmenthelpedmegaintheexperiencethatIcanpassfurtheron.
K.AavaRaniisacofounderofCulpzLabPvtLtd,asoftwarecompanywith10yearsofexperienceingametechnologies.Asuccessfulbloggerandtechnologist,sheswitchedherfocustogamedevelopmentin2004.Sincethen,shehasproducedanumberofgametitlesandhasprovidedartandprogrammingsolutionstoUnitydevelopersacrosstheglobe.SheisbasedinNewDelhi,India.Shehasbeentherecipientofseveralprestigiousawards,includingAdobeforGameTechnologyExpert2012andSmartFoxServer,forherarticles.Shehasexperienceinvariousdifferenttechnologies.
AavaiscofounderofCulpzLab,asoftwaredevelopmentcompanyofhighlyskilledprofessionalsinwebgamedevelopmentandinteractivemedia.Foundedin2010,CulpzLabhasprovenitselftobeareliabletechnologypartnerforitsclients.Currently,CulpzLabemploysover50peopleandhasitsofficebasedoutofNewDelhi,India.
www.allitebooks.com
CulpzLabisaleading-edgecustom(bespoke)process-drivensoftwaresolutionsproviderthathashelpedandpartneredwithmanyreputablebrands,start-upventures,andoffshoreITcompanies.Ithashelpedthemrealizeanddelivereffective,efficient,andon-timedigitalsolutions.
CulpzLabhasworkedgloballywithaplethoraofclientswithadiversetechnologybackground,industryexpertise,andaclientfootprintthatextendstomorethan14countries.CulpzLabiswellpositionedtohelporganizationsderivemaximumvaluefromtheirITinvestmentsandfullysupporttheirbusinessaims.
CulpzLab’scorebusinesspurposeistoinvent,engineer,anddelivertechnologysolutionsthatdrivebusinessvalue,createsocialvalue,andimprovethelivesofcustomers.
ShehasalsoworkedonCreatingE-learningGameswithUnity3D,PacktPublishing.
IwouldliketoacknowledgethecreatorsoftheUnity3Dprogram,anamazingtoolthatallowstheultimatedigitalexperienceincreativeexpression.I’dalsoliketothankmyclientsforbeingpartofthefun!Manyofyouhavebecomegoodfriendsthroughmycreativesuccesses.Finally,I’dliketothankR.K.Rajanjanwhotaughtmehowtolovetechnologies.
Supportfiles,eBooks,discountoffers,andmoreForsupportfilesanddownloadsrelatedtoyourbook,pleasevisitwww.PacktPub.com.
DidyouknowthatPacktofferseBookversionsofeverybookpublished,withPDFandePubfilesavailable?YoucanupgradetotheeBookversionatwww.PacktPub.comandasaprintbookcustomer,youareentitledtoadiscountontheeBookcopy.Getintouchwithusat<service@packtpub.com>formoredetails.
Atwww.PacktPub.com,youcanalsoreadacollectionoffreetechnicalarticles,signupforarangeoffreenewslettersandreceiveexclusivediscountsandoffersonPacktbooksandeBooks.
https://www2.packtpub.com/books/subscription/packtlib
DoyouneedinstantsolutionstoyourITquestions?PacktLibisPackt’sonlinedigitalbooklibrary.Here,youcansearch,access,andreadPackt’sentirelibraryofbooks.
Whysubscribe?FullysearchableacrosseverybookpublishedbyPacktCopyandpaste,print,andbookmarkcontentOndemandandaccessibleviaawebbrowser
FreeaccessforPacktaccountholdersIfyouhaveanaccountwithPacktatwww.PacktPub.com,youcanusethistoaccessPacktLibtodayandview9entirelyfreebooks.Simplyuseyourlogincredentialsforimmediateaccess.
PrefaceWhereisAngularJS?SinceAngularJS’sinception,ithasbeendeployedintoamultitudeofdifferentenvironments,mostlyduetoitsflexibilityandextensibility.ParalleltoAngular’srisearedevelopertoolssuchasApacheCordovaandChromepackagedapps.ThesehavegivendeveloperstheopportunitytodeploywebapplicationsonplatformsthatwerepreviouslydominatedbylanguagessuchasJavaandC.Withtheseadvancements,AngularJSappscannowbefoundintheChromeWebStore,GooglePlayStore,AppleAppStore,PlayStationStore,andFirefoxMarketplace,allinadditiontotraditionalin-browserwebapplications.ToseeexamplesofothermembersoftheAngularJScommunitythatarebuiltonAngularJS,https://builtwith.angularjs.org/isaphenomenalplace.AsAngularJSanditscommunitymature,Isuspectthattheaforementionedquestionwillbecome“Whereisn’tAngularJS?”
Withoutatalentedandthrivingdevelopercommunity,AngularJSwouldnotbetheframeworkthatitistoday.ThemostapparentmetricIfoundtomeasurethisphenomenonistherateatwhichthenewversionsofAngularJSarereleased.Atitsapex,itreaches3minorreleasesin1dayand5minorreleasespermonthinMarch2014.Tohelpthecommunityandcontributorskeepupwiththepaceofdevelopment,theAngularJScoreteammaintainsthewebsitehttps://dashboard.angularjs.org/,whichprovidesareal-timesnapshotintothecurrentbuildstatusofAngularJS’score.Becauseofitsextensibledesign,contributorshavealsobeenabletoenhanceAngularJS’scorethroughthedevelopmentofthird-partymodules,services,filters,anddirectives.SomeexamplesarethepopularRESTAngularmoduleforconsumingRESTfulAPIs,theAngular-UIfrontendframework,IonicFrameworkformobileUIs,Firebasereal-timedatastorageandsyncing,andYoemangeneratorsforAngular.
WhatthisbookcoversChapter1,OurAppandToolStack,explainsthetoolingprocess,whichisoneofthehottesttopicsintoday’swebdevelopmentcommunity,andAngularJShasasuiteoftoolsthatenhancesyourdeveloperexperience.YouwilllearnaboutAngular’stoolstack,howtheyfittogether,andmostnotably,howtheycanhelpyoudeployandmaintainfutureapplications.
Chapter2,DeployingtoApache,explainswhyApache,beingthemostpopularwebserverenvironment,isasolidplatformforhostingmostAngularapplications.YouwillgetanopportunitytoenhanceApache’sdefaultconfigurationtobestsupportyourAngularapplication.WewillalsodiscussbestpracticestodeterminewhetherApacheissuitableforyourtypeofapplicationorwhetheranalternateinfrastructureshouldbeconsidered.
Chapter3,DeployingtoHeroku,discussesHeroku,whichisoneofthebestplatformsasaservice.Itsinfrastructureempowersdeveloperstospinup,deployto,andscaletheirownNode.jsserversataminimalcost.DeployingtoHerokuisapositivedeveloperexperiencebecauseitstoolspeedandefficiencyaresecondtonone.
Chapter4,DeployingtoFirebaseHosting,explainswhyFirebasehasonlybeenofferingPaaSforafewmonths,butthepromiseofhostingyourapplicationcodeinthesameenvironmentasyourreal-timedatabasehascreatedalotofinterestaroundtheFirebaseservices.YouwilllearnhowFirebaseispreconfiguredtooptimallyservetheAngularJSapplicationsandhowtofurthertailorFirebaseHostingtoyourapplication’sneeds.
Chapter5,DeployingaMobileApp,explainswhyhybridmobileappsisnotanewidea,butthequalityandtoolingaroundithasmadeitastrongcontenderwhenbuildingamobileapplication.Wewilltakeourapplication’scodeandbuilditforAndroid/iOSusingPhoneGap,ApacheCordova,andCordovaChromeApps.
Chapter6,DeployingasChromeApps,explainswhyChromeOS’sadoptionisgrowingatanexponentialrateandtheneedfordeveloperstosupportthisplatformisparallelinimportance.Angularthrivesinthisenvironment,anddeployingourapplicationasaChromeAppforconsumptionontheChromeWebStore/ChromeOSisanexcitingfrontierforbothdevelopersandconsumers.
Chapter7,Postdeployment,explainswhydeploymentisnoexceptiontothemarketingadageof“rinse,lather,repeat”,becauseitisneverfinished.Optimizingyourworkflowwithbestpracticesisnecessarytoensurethelongevityofyourapplication.Wewillenhanceourapplicationandgrokhowtosafelydeploytheenhancementintoproduction.
Chapter8,Conclusion–AngularJSDeploymentEssentials,explainsthatharnessingthetoolswillallowyoutodeployasingleAngularJSapplicationtonewplatformsandnewcustomers.Wewilldiscussafewtipsthatwillhelpyougetthebestoutofthesetools.
WhatyouneedforthisbookThematerialsneededforthisbookincludethe,somewhatobvious,toolstypicallyassociatedwithmostformsofwebdevelopment.Thisincludesacomputerwiththeoperatingsystemofyourchoice,astableInternetconnection,anapplicationtocreateandedittextfiles,basicworkingknowledgeofyourcomputer’scommandline,aninstanceofeachmodernwebbrowser,andbecauseitisparamounttostayhydratedwhilegrowingnewinformation,water.AllothersoftwareandtoolsneededtoaccomplishtheexamplesinthisbookarecoveredinChapter1,OurAppandToolStack.
WhothisbookisforThisbookisdesignedtobuildyourexistingknowledgeofAngularJSdevelopmentwiththetoolsandbestpracticesnecessarytosuccessfullydeployanapplicationintoastableproductionenvironment.Thus,priorunderstandingofHTML,CSS,JavaScript,theMV*architecture,andAngularJSareneededbyyoutofullyimplementthetechniquesandbestpracticescoveredinthisbook.Ifyouhavecommittedtothisbookandaren’tfeelingconfidentabouttheantecedentcriterion,theAngularJScommunityhaspublishedasurfeitoffreeresources(listedasfollows)thatwilladequatelyprepareyoutoassimilatetheknowledgetocome:
http://egghead.iohttp://thinkster.iohttps://github.com/jmcunningham/AngularJS-Learning
ConventionsInthisbook,youwillfindanumberofstylesoftextthatdistinguishbetweendifferentkindsofinformation.Herearesomeexamplesofthesestyles,andanexplanationoftheirmeaning.
Codewordsintextareshownasfollows:“Thisfileiscalledmanifest.json.”
Ablockofcodeissetasfollows:
angular.module('krakn.controllers',['ionic','ngAnimate'])
.controller('HomeCtrl',['$scope','syncData',function($scope,syncData){
syncData('syncedValue').$bind($scope,'syncedValue');
}]);
Whenwewishtodrawyourattentiontoaparticularpartofacodeblock,therelevantlinesoritemsaresetinbold:
angular.module('krakn.controllers',['ionic','ngAnimate'])
.controller('HomeCtrl',['$scope','syncData',function($scope,syncData){
syncData('syncedValue').$bind($scope,'syncedValue');
}]);
Newtermsandimportantwordsareshowninbold.Wordsthatyouseeonthescreen,inmenusordialogboxesforexample,appearinthetextlikethis:“Fromthedrop-downmenu,selecttheSettingsmenuitemnearthebottom.”
NoteWarningsorimportantnotesappearinaboxlikethis.
TipTipsandtricksappearlikethis.
Fromthispointforward,IwilluseafewtermsIconsidertoberelevantindustrystandardslangandacronymstoenhanceyourvocabularywhenspeakingwithotherdevelopers,watchingtutorialvideosonline,andreadingassociatedliteratureorblogposts.Theseincludethefollowingterms:
Angular:ThistermisashorthandnamereferringtoallfacetsofAngularJSanditscommunity.ToolStack:Thistermisusedforacollectionoftoolsencompassingallphasesofthedevelopmentprocess.Theseinclude,butarenotlimitedto,boilerplates/seedprojects,codeeditors,IDEs,codelinters,command-lineutilities,languageabstractioncompilers,packagemanagers,localwebservers,LiveReload,source/versioncontrolandtheirrespectivewebapplications,webbrowsers/BrowserStack,browserDevTools,testingrunners,buildtools,servercommunicationclients,andothers.Forfurtherinformation,GooglesearchforslidesfromPaulIrish’spresentationentitledTooling&TheWebappDevelopmentStack.DevTools:ThistermisashorthandnamereferringtotheGoogleChromeDeveloperTools.HavingcontributedtotheChromiumOpenSourcecommunity,Iambiased
towardsGoogleChromeandmostnotablytowardstheChromeDeveloperTools.PaaS:ThistermisanacronymforPlatformasaService.CLI:Thistermisanacronymforcommand-lineinterface.
ReaderfeedbackFeedbackfromourreadersisalwayswelcome.Letusknowwhatyouthinkaboutthisbook—whatyoulikedordisliked.Readerfeedbackisimportantforusasithelpsusdeveloptitlesthatyouwillreallygetthemostoutof.
Tosendusgeneralfeedback,simplye-mail<feedback@packtpub.com>,andmentionthebook’stitleinthesubjectofyourmessage.
Ifthereisatopicthatyouhaveexpertiseinandyouareinterestedineitherwritingorcontributingtoabook,seeourauthorguideatwww.packtpub.com/authors.
CustomersupportNowthatyouaretheproudownerofaPacktbook,wehaveanumberofthingstohelpyoutogetthemostfromyourpurchase.
www.allitebooks.com
ErrataAlthoughwehavetakeneverycaretoensuretheaccuracyofourcontent,mistakesdohappen.Ifyoufindamistakeinoneofourbooks—maybeamistakeinthetextorthecode—wewouldbegratefulifyoucouldreportthistous.Bydoingso,youcansaveotherreadersfromfrustrationandhelpusimprovesubsequentversionsofthisbook.Ifyoufindanyerrata,pleasereportthembyvisitinghttp://www.packtpub.com/submit-errata,selectingyourbook,clickingontheErrataSubmissionFormlink,andenteringthedetailsofyourerrata.Onceyourerrataareverified,yoursubmissionwillbeacceptedandtheerratawillbeuploadedtoourwebsiteoraddedtoanylistofexistingerrataundertheErratasectionofthattitle.
Toviewthepreviouslysubmittederrata,gotohttps://www.packtpub.com/books/content/supportandenterthenameofthebookinthesearchfield.TherequiredinformationwillappearundertheErratasection.
PiracyPiracyofcopyrightedmaterialontheInternetisanongoingproblemacrossallmedia.AtPackt,wetaketheprotectionofourcopyrightandlicensesveryseriously.IfyoucomeacrossanyillegalcopiesofourworksinanyformontheInternet,pleaseprovideuswiththelocationaddressorwebsitenameimmediatelysothatwecanpursuearemedy.
Pleasecontactusat<copyright@packtpub.com>withalinktothesuspectedpiratedmaterial.
Weappreciateyourhelpinprotectingourauthorsandourabilitytobringyouvaluablecontent.
QuestionsIfyouhaveaproblemwithanyaspectofthisbook,youcancontactusat<questions@packtpub.com>,andwewilldoourbesttoaddresstheproblem.
Chapter1.OurAppandToolStackBeforeNASAorSpaceXlaunchesavesselintothecosmos,thereisatremendousamountofplanningandpreparationinvolved.Theguidingprinciplewhenplanningforanysuccessfulmissionissimilartominimizingeffortsandresourceswhileretainingmaximumreturnonthemission.Ourprinciplesfordevelopmentanddeploymentarenoexceptiontothisaxiom,andyouwillgainafirmerworkingknowledgeofhowtodosointhischapter.
Inthischapter,youwilllearnhowtodothefollowing:
MinimizeeffortsandmaximizeresultsusingatoolstackoptimizedforAngularJSdevelopmentAccessthekraknappviaGitHubfordeploymentinfuturechaptersScaffoldanAngularappwithYeoman,Grunt,andBowerSetupalocalNode.jsdevelopmentserverReadthroughkrakn’ssourcecode
TherighttoolsforthejobWebapplicationscanbecomparedtobuildings;withouttools,neitherwouldbeapleasuretobuild.Thismakestoolsanindispensablefactorinbothdevelopmentandconstruction.Whentoolsarecombined,theyformaworkflowthatcanberepeatedacrossanyprojectbuiltwiththesamestack,facilitatingthepracticesofdesign,development,anddeployment.Theargumentcanbemadethatitisjustasparamounttodocumentworkflowasanapplication’ssourcecodeorAPI.
Alongwithgroupingtoolsintocategoriesbasedonthephasesofbuildingapplications,itisalsousefultogrouptoolsbasedontheopinionsofarespectiveproject—inourcase,Angular,Ionic,andFirebase.Icalltoolsgroupedintoopinionatedworkflowstoolstacks.Forexample,theremainderofthischapterdiscussesthetoolstackusedtobuildtheapplicationthatwewilldeployacrossenvironmentsinthisbook.Incontrast,ifyouweretobuildaRubyonRailsapplication,thetoolstackwouldbecompletelydifferentbecausetheproject’sopinionsaredifferent.Ourappiscalledkrakn,anditfunctionsasareal-timechatapplicationbuiltontopoftheopinionsofAngular,theIonicFramework,andFirebase.
TipYoucanfindallofkrakn’ssourcecodeatgithub.com/zachmoreno/krakn.
VersioncontrolwithGitandGitHubGitisacommand-lineinterface(CLI)developedbyLinusTorvalds,touseonthefamedLinuxkernel.Gitismostlypopularduetoitsdistributedarchitecturemakingitnearlyimpossibleforcorruptiontooccur.Git’sdistributedarchitecturemeansthatanyremoterepositoryhasallofthesameinformationasyourlocalrepository.ItisusefultothinkofGitasafreeinsurancepolicyformycode.
YouwillneedtoinstallGitusingtheinstructionsprovidedatwww.git-scm.com/book/en/Getting-Started-Installing-Gitforyourdevelopmentworkstation’soperatingsystem.
www.GitHub.comhasplayedanotableroleinGit’spopularization,turningitsfunctionalityintoasocialnetworkfocusedonopensourcecodecontributions.WithapricingmodelthatincentivizesOpenSourcecontributionsandlicensingforprivate,GitHubelevatedtheuseofGittoheightsneverseenbefore.
Ifyoudon’talreadyhaveanaccountonGitHub,nowistheperfecttimetovisitwww.github.comtoprovisionafreeaccount.Imentionedearlierthatkrakn’scodeisavailableforforkingatwww.github.com/zachmoreno/krakn.ThismeansthatanypersonwithaGitHubaccounthastheabilitytoviewmyversionofkrakn,andcloneacopyoftheirownforfurthermodificationsorcontributions.InGitHub’swebapplication,forkingmanifestsitselfasabuttonlocatedtotherightoftherepository’stitle,whichinthiscaseisZachMoreno/krakn.Whenyouclickonthebutton,youwillseeananimationthatsimulatesthehardcoreforkingaction.ThisresultsinaclonedrepositoryunderyouraccountthatwillhaveatitletothetuneofYourName/krakn.
Node.jsNode.js,commonlyknownasNode,isacommunity-drivenserverenvironmentbuiltonGoogleChrome’sV8JavaScriptruntimethatisentirelyeventdrivenandfacilitatesanonblockingI/Omodel.Accordingtowww.nodejs.org,itisbestsuitedfor:
“Data-intensivereal-timeapplicationsthatrunacrossdistributeddevices.”
Sowhatdoesallthisboildownto?NodeempowerswebdeveloperstowriteJavaScriptbothontheclientandserverwithbidirectionalreal-timeI/O.TheadventofNodehasempowereddeveloperstotaketheirskillsfromtheclienttotheserver,evolvingfromfrontendtofullstack(likeacaterpillarevolvingintoabutterfly).Notonlydotheseskillsfacilitateapayincrease,theyalsoadvancetheWebtowardsthesamefunctionalityasthetraditionaldesktopornativeapplication.
Forourpurposes,weuseNodeasatool;atooltobuildreal-timeapplicationsinthefewestnumberofkeystrokes,videoswatched,andwordsreadaspossible.Nodeis,infact,amodulartoolthroughitsextensiblepackageinterface,calledNodePackageManager(NPM).YouwilluseNPMasameanstoinstalltheremainderofourtoolstack.
NPMTheNPMisameanstoinstallNodepackagesonyourlocalorremoteserver.NPMishowwewillinstallthemajorityofthetoolsandsoftwareusedinthisbook.Thisisachievedbyrunningthe$npminstall–g[PackageName]commandinyourcommandlineorterminal.TosearchthefulllistofNodepackages,visitwww.npmjs.orgorrun$npmsearch[SearchTerm]inyourcommandlineorterminalasshowninthefollowingscreenshot:
Yeoman’sworkflowYeomanisaCLIthatisthegluethatholdsyourtoolsintoyouropinionatedworkflow.Althoughthetermopinionatedmightsoundoff-putting,youmustfirstconsiderthewisdomandexperienceofthedevelopersandcommunitybeforeyouwhomaintainYeoman.Inthiscontext,opinionatedmeansalittlemorethanacollectionofthebestpracticesthatareallaimedatimprovingyourdeveloper’sexperienceofbuildingstaticwebsites,singlepageapplications,andeverythinginbetween.Opinionateddoesnotmeanthatyouarelockedintowhatsomeoneelsefeelsisbestforyou,nordoesitmeanthatyoumuststrictlyadheretotheopinionsorbestpracticesincluded.YeomanisgeneralenoughtohelpyoubuildnearlyanythingfortheWebaswellasimprovingyourworkflowwhiledevelopingit.ThetoolsthatmakeupYeoman’sworkflowareYo,Grunt.js,Bower,andafewothersthataremore-or-lessoptional,butareprobablyworthyourtime.
YoApartfromhavingoneofthehippestnamespaces,Yoisapowerfulcodegeneratorthatisintelligentenoughtoscaffoldmostsitesandapplications.Bydefault,instantiatingayocommandassumesthatyoumeantoscaffoldsomethingataprojectlevel,butyocanalsobescopedmoregranularlybymeansofsub-generators.Forexample,thecommandforinstantiatinganewvanillaAngularprojectisasfollows:
$yoangularradicalApp
YowillnotfinishyourrequestuntilyouprovidesomefurtherinformationaboutyourdesiredAngularproject.Thisisachievedbyaskingyouaseriesofrelevantquestions,andbasedonyouranswers,yowillscaffoldafamiliarapplicationfolder/filestructure,alongwithalltheboilerplatecode.Notethatifyouhaveworkedwiththeangular-seedproject,thentheAngularapplicationthatyogenerateswilllookveryfamiliartoyou.OnceyouhaveanAngularappscaffolded,youcanbeginusingsub-generatorcommands.Thefollowingcommandscaffoldsanewroute,radicalRoute,withinradicalApp:
$yoangular:routeradicalRoute
The:routesub-generatorisaverypowerfulcommand,asitautomatesallofthefollowingkeytasks:
Itcreatesanewfile,radicalApp/scripts/controllers/radicalRoute.js,thatcontainsthecontrollerlogicfortheradicalRouteviewItcreatesanothernewfile,radicalApp/views/radicalRoute.html,thatcontainstheassociatedviewmarkupanddirectivesLastly,itaddsanadditionalroutewithin,radicalApp/scripts/app.js,thatconnectstheviewtothecontroller
Additionally,thesub-generatorsforyoangularincludethefollowing:
:controller
:directive
:filter
:service
:provider
:factory
:value
:constant
:decorator
:view
Allthesub-generatorsallowyoutoexecutefinerdetailedcommandsforscaffoldingsmallercomponentswhencomparedto:route,whichexecutesacombinationofsub-generators.
InstallingYo
Withinyourworkstation’sterminalorcommand-lineapplicationtype,insertthefollowingcommand,followedbyareturn:
$npminstall-gyo
TipIfyouareaLinuxorMacuser,youmightwanttoprefixthecommandwithsudo,asfollows:
$sudonpminstall–gyo
GruntGrunt.jsisataskrunnerthatenhancesyourexistingand/orYeoman’sworkflowbyautomatingrepetitivetasks.Eachtimeyougenerateanewprojectwithyo,itcreatesa/Gruntfile.jsfilethatwiresupallofthecuratedtasks.YoumighthavenoticedthatinstallingYoalsoinstallsallofYo’sdependencies.Readingthrough/Gruntfile.jsshouldinciteafairamountofawe,asitgivesyouasnapshotofwhatisgoingonunderthehoodofYeoman’scuratedGrunttasksanditsdependencies.
GeneratingavanillaAngularappproducesa/Gruntfile.jsfile,asitisresponsibleforperformingthefollowingtasks:
ItdefineswhereYoplacesBowerpackages,whichiscoveredinthenextsectionItdefinesthepathwherethegruntbuildcommandplacestheproduction-readycodeItinitializesthewatchtasktorun:
JSHintwhenJavaScriptfilesaresavedKarma’stestrunnerwhenJavaScriptfilesaresavedCompasswhenSCSSorSASSfilesaresavedThesaved/Gruntfile.jsfile
ItinitializesLiveReloadwhenanyHTMLorCSSfilesaresavedItconfiguresthegruntservercommandtorunaNode.jsserveronlocalhost:9000,ortoshowtestresultsonlocalhost:9001ItautoprefixesCSSrulesonLiveReloadandgruntbuildItrenamesfilesforoptimizingbrowsercachingItconfiguresthegruntbuildcommandtominifyimages,SVG,HTML,andCSS
www.allitebooks.com
filesortosafelyminifyAngularfiles
Letuspauseforamomenttoreflectontheamountoftimeitwouldtaketofind,learn,andimplementeachdependencyintoourexistingworkflowforeachprojectweundertake.Ok,weshouldnowhaveagreaterappreciationforYeomananditscommunity.
Forthevastmajorityofthetime,youwilllikelyonlyuseafewGruntcommands,whichincludethefollowing:
$gruntserver
$grunttest
$gruntbuild
BowerIfYoscaffoldsourapplication’sstructureandfiles,andGruntautomatesrepetitivetasksforus,thenwhatdoesBowerbringtotheparty?Boweriswebdevelopment’smissingpackagemanager.ItsfunctionalityparallelsthatofRubyGemsfortheRubyonRailsMVCframework,butisnotlimitedtoanysingleframeworkortechnologystack.TheexplicituseofBowerisnotrequiredbytheYeomanworkflow,butasImentionedpreviously,theuseofBowerisconfiguredautomaticallyforyouinyourproject’s/Gruntfile.jsfile.
Howdoesmanagingpackagesimproveourdevelopmentworkflow?Withallofthetimewe’vebeenspendinginourcommandlinesandterminals,itishandytohavetheabilitytoautomatethemanagementofthird-partydependencieswithinourapplication.Thisabilitymanifestsitselfinafewsimplecommands,themostubiquitousbeingthefollowingcommand:
$bowerinstall[PackageName]--save
Withthiscommand,Bowerwillautomatethefollowingsteps:
1. First,searchitspackagesforthespecifiedpackagename2. Downloadthelateststableversionofthepackageiffound3. Movethepackagetothelocationdefinedinyourproject’s/Gruntfile.jsfile,
typicallyafoldernamed/bower_components4. Insertdependenciesintheformof<link>elementsforCSSfilesinthedocument’s
<head>element,and<script>elementsforJavaScriptfilesrightabovethedocument’sclosing</body>tag,tothepackage’sfileswithinyourproject’s/index.htmlfile
ThisprocessisonethatwebdevelopersaremorethanfamiliarwithbecauseaddingaJavaScriptlibraryornewdependencyhappensmultipletimeswithineveryproject.Bowerspeedsupourexistingmanualprocessthroughautomationandimprovesitbyprovidingthelateststableversionofapackageandthennotifyingusofanupdateifoneisavailable.Thislastpart,“notifyingusofanupdateif…available”,isimportantbecauseasawebdeveloperadvancesfromoneprojecttothenext,itiseasytooverlookkeepingdependenciesasuptodateaspossible.Thisisachievedbyrunningthefollowing
command:
$bowerupdate
Thiscommandreturnsalltheavailableupdates,ifavailable,andwillgothroughthesameprocessofinsertingnewreferenceswhereapplicable.
Bower.ioincludesallofthedocumentationonhowtouseBowertoitsfullestpotentialalongwiththeabilitytosearchthroughalloftheavailableBowerpackages.
TipSearchingforavailableBowerpackagescanalsobeachievedbyrunningthefollowingcommand:
$bowersearch[SearchTerm]
Ifyoucannotfindthespecificdependencyforwhichyousearch,andtheprojectisonGitHub,considercontributingabower.jsonfiletotheproject’srootandinvitingtheownertoregisteritbyrunningthefollowingcommand:
$bowerregister[ThePackageName][GitEndpoint]
Registrationallowsyoutoinstallyourdependencybyrunningthenextcommand:
$bowerinstall[ThePackageName]
TheIonicframeworkTheIonicframeworkisatrulyremarkableadvancementinbridgingthegapbetweenwebapplicationsandnativemobileapplications.Insomeways,IonicparallelsYeomanwhereitassemblestoolsthatwerealreadyavailabletodevelopersintoaneatpackage,andstructuresaworkflowaroundthem,inherentlyimprovingourexperienceasdevelopers.
IfIonicisanalogoustoYeoman,thenwhatarethetoolsthatmakeupIonic’sworkflow?Thetoolsthat,whencombined,makeIonicnoteworthyareApacheCordova,Angular,Ionic’ssuiteofAngulardirectives,andIonic’smobileUIframework.
BatarangAninvaluablepiecetoourAngulartoolstackistheGoogleChromeDeveloperToolsextension,Batarang,byBrianFord.Batarangaddsathird-partypanel(ontheright-handsideofConsole)toDevToolsthatfacilitatesAngular’sspecificinspectionintheeventofdebugging.Wecanviewdatainthescopesofeachmodel,analyzeeachexpression’sperformance,andviewabeautifulvisualizationofservicedependenciesallfromwithinBatarang.BecauseAngularaugmentstheDOMwithng-attributes,italsoprovidesaPropertiespanewithintheElementspanel,toinspectthemodelsattachedtoagivenelement’sscope.TheextensioniseasytoinstallfromeithertheChromeWebStoreortheproject’sGitHubrepositoryandinspectioncanbeenabledbyperformingthefollowingsteps:
1. Firstly,opentheChromeDeveloperTools.2. YoushouldthennavigatetotheAngularJSpanel.3. Finally,selecttheEnablecheckboxonthefarrighttab.
YouractiveChrometabwillthenbereloadedautomatically,andtheAngularJSpanelwillbeginpopulatingtheinspectiondata.Inaddition,youcanleveragetheAngularpanewiththeElementspaneltoviewAngular-specificpropertiesatanelementallevel,andobservethe$scopevariablefromwithintheConsolepanel.
SublimeTextandEditorintegrationWhiledevelopinganyAngularapp,itishelpfultoaugmentourworkflowfurtherwithAngular-specificsyntaxcompletion,snippets,gotodefinition,andquickpanelsearchintheformofaSublimeTextpackage.Performthefollowingsteps:
1. Ifyouhaven’tinstalledSublimeTextalready,youneedtofirstinstallPackageControl.Otherwise,continuewiththenextstep.
2. Onceinstalled,presscommand+Shift+PinSublime.3. Then,youneedtoselectthePackageControl:InstallPackageoption.4. Finally,typeangularjsandpressEnteronyourkeyboard.
InadditiontosupportwithinSublime,Angularenhancementsexistforlotsofpopulareditors,includingWebStorm,Coda,andTextMate.
KraknAsaquickrefresher,kraknwasconstructedusingallofthetoolsthatarecoveredinthischapter.TheseincludeGit,GitHub,Node.js,NPM,Yeoman’sworkflow,Yo,Grunt,Bower,Batarang,andSublimeText.TheapplicationbuildsonAngular,Firebase,theIonicFramework,andafewotherminordependencies.
TheworkflowIusedtodevelopkraknwentsomethinglikethefollowing.Followthesestepstoachievethesamething.Notethatyoucanskiptheremainderofthissectionifyou’dliketogetstraighttothedeploymentaction,andfeelfreetorenamethingswherenecessary.
SettingupGitandGitHubTheworkflowIfollowedwhiledevelopingkraknbeginswithinitializingourlocalGitrepositoryandconnectingittoourremotemasterrepositoryonGitHub.Inordertoinstallandsetupboth,performthefollowingsteps:
1. Firstly,installallthetoolstackdependencies,andcreateafoldercalledkrakn.2. Followingthis,run$gitinit,andyouwillcreateaREADME.mdfile.3. Youshouldthenrun$gitaddREADME.mdandcommitREADME.mdtothelocal
masterbranch.4. YouthenneedtocreateanewremoterepositoryonGitHubcalled
ZachMoreno/krakn.5. Followingthis,runthefollowingcommand:
$gitremoteaddorigingit@github.com:[YourGitHubUserName]/krakn.git
6. Concludethesetupbyrunning$gitpush–uoriginmaster.
ScaffoldingtheappwithYoScaffoldingourappcouldn’tbeeasierwiththeyoionicgenerator.Todothis,performthefollowingsteps:
1. Firstly,installYobyrunning$npminstall-gyo.2. Afterthis,installgenerator-ionicjsbyrunning$npminstall-ggenerator-
ionicjs.3. Toconcludethescaffoldingofyourapplication,runtheyoioniccommand.
DevelopmentAfterscaffoldingthefolderstructureandboilerplatecode,ourworkflowadvancestothedevelopmentphase,whichisencompassedinthefollowingsteps:
1. Tobegin,rungruntserver.2. Youarenowinapositiontomakechanges,forexample,thesebeingdeletionsor
additions.3. Oncethesearesaved,LiveReloadwillautomaticallyreloadyourbrowser.4. Youcanthenreviewthechangesinthebrowser.5. Repeatsteps2-4untilyouarereadytoadvancetothepredeploymentphase.
www.allitebooks.com
Views,controllers,androutesBeingasimplechatapplication,kraknhasonlyahandfulofviews/routes.Theyarelogin,chat,account,menu,andabout.Themenuviewispresentinalltheotherviewsintheformofanoff-canvasmenu.
TheloginviewThedefaultview/route/controllerisnamedlogin.TheloginviewutilizestheFirebase’sSimpleLoginfeaturetoauthenticateusersbeforeproceedingtotherestoftheapplication.Apartfromloggingintokrakn,userscanregisteranewaccountbyenteringtheirdesiredcredentials.Aninterestingpartoftheloginviewistheuseoftheng-showdirectivetotogglethesecondpasswordfieldiftheuserselectstheregisterbutton.However,theng-modeldirectiveisthefirststephere,asitisusedtopasstheinputtextfromtheviewtothecontrollerandultimately,theFirebaseSimpleLogin.OtherthantheAngularmagic,thisviewusestheion-viewdirective,grid,andbuttonsthatareallcoretoIonic.
EachviewwithinanIonicappiswrappedwithinanion-viewdirectivethatcontainsatitleattributeasfollows:
<ion-viewtitle="Login">
Theloginviewusesthestandardinputelementsthatcontainang-modelattributetobindtheinput’svaluebacktothecontroller’s$scopeasfollows:
<inputtype="text"placeholder="you@email.com"ng-model="data.email"/>
<inputtype="password"placeholder="embodystrength"ng-
model="data.pass"/>
<inputtype="password"placeholder="embodystrength"ng-
model="data.confirm"/>
TheLogInandRegisterbuttonscalltheirrespectivefunctionsusingtheng-clickattribute,withthevaluesettothefunction’snameasfollows:
<buttonclass="buttonbutton-blockbutton-positive"ng-click="login()"
ng-hide="createMode">LogIn</button>
TheRegisterandCancelbuttonssetthevalueof$scope.createModetotrueorfalsetoshoworhidethecorrectbuttonsforeitheraction:
<buttonclass="buttonbutton-blockbutton-calm"ng-click="createMode=
true"ng-hide="createMode">Register</button>
<buttonclass="buttonbutton-blockbutton-calm"ng-show="createMode"ng-
click="createAccount()">CreateAccount</button>
<buttonclass="buttonbutton-blockbutton-assertive"ng-show="createMode"
ng-click="createMode=false">Cancel</button>
$scope.errisdisplayedonlywhenyouwanttoshowthefeedbacktotheuser:
<png-show="err"class="assertivetext-center">{{err}}</p>
</ion-view>
ThelogincontrollerisdependentonFirebase’sloginServicemoduleandAngular’score$locationmodule:
controller('LoginCtrl',['$scope','loginService','$location',
function($scope,loginService,$location){
Ionic’sdirectivestendtocreateisolatedscopes,soitwasusefulheretowrapourcontroller’svariableswithina$scope.dataobjecttoavoidissueswithintheisolatedscopeasfollows:
$scope.data={
"email":null,
"pass":null,
"confirm":null,
"createMode":false
}
Thelogin()functioneasilychecksthecredentialsbeforeauthenticationandsendsfeedbacktotheuserifneeded:
$scope.login=function(cb){
$scope.err=null;
if(!$scope.data.email){
$scope.err='Pleaseenteranemailaddress';
}
elseif(!$scope.data.pass){
$scope.err='Pleaseenterapassword';
}
Ifthecredentialsaresound,wesendthemtoFirebaseforauthentication,andwhenwereceiveasuccesscallback,weroutetheusertothechatviewusing$location.path()asfollows:
else{
loginService.login($scope.data.email,$scope.data.pass,
function(err,user){
$scope.err=err?err+'':null;
if(!err){
cb&&cb(user);
$location.path('krakn/chat');
}
});
}
};
ThecreateAccount()functionworksinmuchthesamewayaslogin(),exceptthatitensuresthattheusersdon’talreadyexistbeforeaddingthemtoyourFirebaseandloggingthemin:
$scope.createAccount=function(){
$scope.err=null;
if(assertValidLoginAttempt()){
loginService.createAccount($scope.data.email,$scope.data.pass,
function(err,user){
if(err){
$scope.err=err?err+'':null;
}
else{
//mustbeloggedinbeforeIcanwritetomyprofile
$scope.login(function(){
loginService.createProfile(user.uid,user.email);
$location.path('krakn/account');
});
}
});
}
};
TheassertValidLoginAttempt()functionisafunctionusedtoensurethatnoerrorsarereceivedthroughtheaccountcreationandauthenticationflows:
functionassertValidLoginAttempt(){
if(!$scope.data.email){
$scope.err='Pleaseenteranemailaddress';
}
elseif(!$scope.data.pass){
$scope.err='Pleaseenterapassword';
}
elseif($scope.data.pass!==$scope.data.confirm){
$scope.err='Passwordsdonotmatch';
}
return!$scope.err;
}
}])
ThechatviewKeepingveganpracticesaside,themeatandpotatoesofkrakn’sfunctionalityliveswithinthechatview/controller/route.ThedesignissimilartomostSMSclients,withtheinputinthefooteroftheviewandmessageslistedchronologicallyinthemaincontentarea.Theng-repeatdirectiveisusedtodisplayamessageeverytimeamessageisaddedtothemessagescollectioninFirebase.Ifyousubmitamessagesuccessfully,unsuccessfully,orwithoutanytext,feedbackisprovidedviatheplaceholderattributeofthemessageinput.
Therearetwofiltersbeingutilizedwithinthechatview:orderByPriorityandtimeAgo.TheorderByPriorityfilterisdefinedwithinthefirebasemodulethatusestheFirebaseobjectIDsthatensureobjectsarealwayschronological.
TipThetimeAgofilterisanopensourceAngularmodulethatIfound.Youcanaccessitatwww.jsfiddle.net/i_woody/cnL5T/.
Theion-viewdirectiveisusedonceagaintocontainourchatview:
<ion-viewtitle="Chat">
Ourlistofmessagesiscomposedusingtheion-listandion-itemdirectives,inadditiontoacoupleofkeyattributes.Theion-listdirectivegivesussomeniceinteractive
controlsusingtheoption-buttonsandcan-swipeattributes.Thisresultsineachlistitembeingswipeabletotheleft,revealingouroption-buttonsasfollows:
<ion-listoption-buttons="itemButtons"can-swipe="true"ng-
show="messages">
Ourworkhorseinthechatviewisthetrustyng-repeatdirective,responsibleforpersistingourdatafromFirebasetoourservicetoourcontrollerandintoourviewandbackagain:
<ion-itemng-repeat="messageinmessages|orderByPriority"item="item"
can-swipe="true">
Then,webindourdataintovanillaHTMLelementsthathavesomecustomstylesappliedtothem:
<h2class="user">{{message.user}}</h2>
Thethird-partytimeagofilterconvertsthetimeintosomethingsuchas,“5minago”,similartoInstagramorFacebook:
<smallclass="time">{{message.receivedTime|timeago}}</small>
<pclass="message">{{message.text}}</p>
</ion-item>
</ion-list>
Avanillainputelementisusedtoacceptchatmessagesfromourusers.Theinputdataisboundto$scope.data.newMessageforsendingdatatoFirebaseand$scope.feedbackisusedtokeepourusersinformed:
<inputtype="text"class="{{feeling}}"placeholder="{{feedback}}"
ng-model="data.newMessage"/>
Whenyouclickonthesend/submitbutton,theaddMessage()functionsendsthemessagetoyourFirebase,andaddsittothelistofchatmessages,inrealtime:
<buttontype="submit"id="chat-send"class="buttonbutton-smallbutton-
clear"ng-click="addMessage()"><spanclass="ion-android-send"></span>
</button>
</ion-view>
TheChatCtrlcontrollerisdependantonafewmoremodulesotherthanourLoginCtrl,includingsyncData,$ionicScrollDelegate,$ionicLoading,and$rootScope:
controller('ChatCtrl',['$scope','syncData','$ionicScrollDelegate',
'$ionicLoading','$rootScope',
function($scope,syncData,$ionicScrollDelegate,$ionicLoading,
$rootScope){
TheuserNamevariableisderivedfromtheauthenticateduser’se-mailaddress(savedwithintheapplication’s$rootScope)bysplittingthee-mailandusingeverythingbeforethe@symbol:
varuserEmail=$rootScope.auth.user.e-mail
userName=userEmail.split('@');
Avoidisolatedscopeissueinthesamefashion,aswedidinLoginCtrl:
$scope.data={
newMessage:null,
user:userName[0]
}
Ourviewwillonlycontainthelatest20messagesthathavebeensyncedfromFirebase:
$scope.messages=syncData('messages',20);
Whenanewmessageissaved/synced,itisaddedtothebottomoftheng-repeatedlist,soweusethe$ionicScrollDeligatevariabletoautomaticallyscrollthenewmessageintoviewonthedisplayasfollows:
$ionicScrollDelegate.scrollBottom(true);
Ourdefaultchatinputplaceholdertextissomethingonyourmind?:
$scope.feedback='somethingonyourmind?';
//displaysasclassonchatinputplaceholder
$scope.feeling='stable';
Ifwehaveanewmessageandavalidusername(shortened),thenwecancallthe$add()function,whichsyncsthenewmessagetoFirebaseandourviewisasfollows:
$scope.addMessage=function(){
if($scope.data.newMessage
&&$scope.data.user){
//newdataelementscannotbesyncedwithoutaddingthemtoFB
SecurityRules
$scope.messages.$add({
text:$scope.data.newMessage,
user:$scope.data.user,
receivedTime:Number(newDate())
});
//cleanup
$scope.data.newMessage=null;
Onasuccessfulsync,thefeedbackupdatessayDone!What'snext?,asshowninthefollowingcodesnippet:
$scope.feedback='Done!What\'snext?';
$scope.feeling='stable';
}
else{
$scope.feedback='Pleasewriteamessagebeforesending';
$scope.feeling='assertive';
}
};
$ionicScrollDelegate.scrollBottom(true);
])
TheaccountviewTheaccountviewallowstheloggedinuserstoviewtheircurrentnameande-mailaddress
alongwithprovidingthemwiththeabilitytoupdatetheirpasswordande-mailaddress.TheinputfieldsinteractwithFirebaseinthesamewayasthechatviewdoesusingthesyncDatamethoddefinedinthefirebasemodule:
<ion-viewtitle="'Account'"left-buttons="leftButtons">
The$scope.userobjectcontainsourloggedinuser’saccountcredentials,andwebindthemintoourviewasfollows:
<p>{{user.name}}</p>
…
<p>{{user.email}}</p>
Thebasicaccountmanagementfunctionalityisprovidedwithinthisview;souserscanupdatetheire-mailaddressandorpasswordiftheychooseto,usingthefollowingcodesnippet:
<inputtype="password"ng-keypress="reset()"ng-model="oldpass"/>
…
<inputtype="password"ng-keypress="reset()"ng-model="newpass"/>
…
<inputtype="password"ng-keypress="reset()"ng-model="confirm"/>
BoththeupdatePassword()andupdateEmail()functionsworkinmuchthesamefashionasourcreateAccount()functionwithintheLoginCtrlcontroller.Theycheckwhetherthenewe-mailorpasswordisnotthesameastheold,andifalliswell,itsyncsthemtoFirebaseandbackagain:
<buttonclass="buttonbutton-blockbutton-calm"ng-click=
"updatePassword()">updatepassword</button>
…
<pclass="error"ng-show="err">{{err}}</p>
<pclass="good"ng-show="msg">{{msg}}</p>
…
<inputtype="text"ng-keypress="reset()"ng-model="newemail"/>
…
<inputtype="password"ng-keypress="reset()"ng-model="pass"/>
…
<buttonclass="buttonbutton-blockbutton-calm"ng-click=
"updateEmail()">updateemail</button>
…
<pclass="error"ng-show="emailerr">{{emailerr}}</p>
<pclass="good"ng-show="emailmsg">{{emailmsg}}</p>
…
</ion-view>
ThemenuviewWithinkrakn/app/scripts/app.js,themenurouteisdefinedastheonlyabstractstate.Becauseofitsabstractstate,itcanbepresentedintheappalongwiththeotherviewsbytheion-side-menusdirectiveprovidedbyIonic.Youmighthavenoticedthatonlytwomenuoptionsareavailablebeforesigningintotheapplicationandthattherestappearonlyafterauthenticating.Thisisachievedusingtheng-show-authdirectiveonthechat,account,andlogoutmenuitems.ThemajorityoftheoptionsforIonic’sdirectivesare
availablethroughattributesmakingthemsimpletouse.Forexample,takealookattheanimation="slide-left-right"attribute.YouwillfindIonic’suseofcustomattributeswithinthedirectivesasoneofthewaysthattheIonicFrameworkissettingitselfapartfromotheroptionswithinthisspace.
Theion-side-menudirectivecontainsourmenulistsimilarlytotheonewepreviouslycovered,theion-viewdirective,asfollows:
<ion-side-menus>
<ion-paneion-side-menu-content>
<ion-nav-barclass="bar-positive">
Ourbackbuttonisdisplayedbyincludingtheion-nav-back-buttondirectivewithintheion-nav-bardirective:
<ion-nav-back-buttonclass="button-clear"><iclass="iconion-chevron-
left"></i>Back</ion-nav-back-button>
</ion-nav-bar>
AnimationswithinIonicareexposedandusedthroughtheanimationattribute,whichisbuiltatopthengAnimatemodule.Inthiscase,wearedoingasimpleanimationthatreplicatestheexperienceofanativemobileapp:
<ion-nav-viewname="menuContent"animation="slide-left-right"></ion-nav-
view>
</ion-pane>
<ion-side-menuside="left">
<headerclass="barbar-headerbar-positive">
<h1class="title">Menu</h1>
</header>
<ion-contentclass="has-header">
Asimpleion-listdirective/elementisusedtodisplayournavigationitemsinaverticallist.Theng-showattributehandlesthedisplayofmenuitemsbeforeandafterauserhasauthenticated.Beforeauserlogsin,theycanaccessthenavigation,butonlytheAboutandLogInviewsareavailableuntilaftersuccessfulauthentication.
<ion-list>
<ion-itemnav-clearmenu-closehref="#/app/chat"ng-show-
auth="'login'">
Chat
</ion-item>
<ion-itemnav-clearmenu-closehref="#/app/about">
About
</ion-item>
<ion-itemnav-clearmenu-closehref="#/app/login"ng-show-auth="
['logout','error']">
LogIn
</ion-item>
TheLogOutnavigationitemisonlydisplayedonceloggedin,anduponaclick,itcalls
thelogout()functioninadditiontonavigatingtotheloginview:
<ion-itemnav-clearmenu-closehref="#/app/login"ng-click="logout()"
ng-show-auth="'login'">
LogOut
</ion-item>
</ion-list>
</ion-content>
</ion-side-menu>
</ion-side-menus>
TheMenuCtrlcontrolleristhesimplestcontrollerinthisapplication,asallitcontainsisthetoggleMenu()andlogout()functions:
controller("MenuCtrl",['$scope','loginService','$location',
'$ionicScrollDelegate',function($scope,loginService,$location,
$ionicScrollDelegate){
$scope.toggleMenu=function(){
$scope.sideMenuController.toggleLeft();
};
$scope.logout=function(){
loginService.logout();
$scope.toggleMenu();};
}])
TheaboutviewTheaboutviewis100percentstatic,anditsonlyrealpurposeistopresentthecreditsforalltheopensourceprojectsusedintheapplication.
GlobalcontrollerconstantsAllofkrakn’scontrollersshareonlytwodependencies:ionicandngAnimate.BecauseFirebase’smodulesaredefinedwithin/app/scripts/app.js,theyareavailableforconsumptionbyallthecontrollerswithouttheneedtodefinethemasdependencies.Therefore,thefirebaseservice’ssyncDataandloginServiceareavailabletoChatCtrlandLoginCtrlforuse.
ThesyncDataserviceishowkraknutilizesthree-waydatabindingprovidedbywww.krakn.firebaseio.com.Forexample,withintheChatCtrlcontroller,weusesyncData('messages',20)tobindthelatesttwentymessageswithinthemessagescollectionto$scopeforconsumptionbythechatview.Conversely,whenang-clickuserclicksthesubmitbutton,wewritethedatatothemessagescollectionbyuseofthesyncData.$add()methodinsidethe$scope.addMessage()function:
$scope.addMessage=function(){
if(...){$scope.messages.$add({...});
}
};
ModelsandservicesThemodelforkrakniswww.krakn.firebaseio.com.Theservicesthatconsumekrakn’sFirebaseAPIareasfollows:
Thefirebaseserviceinkrakn/app/scripts/service.firebase.jsTheloginserviceinkrakn/app/scripts/service.login.jsThechangeEmailserviceinkrakn/app/scripts/changeEmail.firebase.js
ThefirebaseservicedefinesthesyncDataservicethatisresponsibleforroutingdatabidirectionallybetweenkrakn/app/bower_components/angularfire.jsandourcontrollers.PleasenotethatthereasonIhavenotmentionedangularfire.jsuntilthispointisthatitisbasicallyanabstractdatatranslationlayerbetweenfirebaseio.comandAngularapplicationsthatintendonconsumingdataasaservice.
www.allitebooks.com
PredeploymentOncethemajorityofanapplication’sdevelopmentphasehasbeencompleted,atleastfortheinitiallaunch,itisimportanttorunallofthecodethroughabuildprocessthatoptimizesthefilesizethroughcompressionofimagesandminificationoftextfiles.ThispieceoftheworkflowwasnotoverlookedbyYeomanandisavailablethroughtheuseofthe$gruntbuildcommand.AsmentionedinthesectiononGrunt,the/Gruntfile.jsfiledefineswherebuiltcodeisplacedonceitisoptimizedfordeployment.Yeoman’sdefaultlocationforbuiltcodeisthe/distfolder,whichmightormightnotexistdependingonwhetheryouhaverunthegruntbuildcommandbefore.
SummaryInthischapter,wediscussedthetoolstackandworkflowusedtobuildtheappthatwewilldeployintheforthcomingchapters.Together,GitandYeomanformedasolidfoundationforbuildingkrakn.GitandGitHubprovideduswithdistributedversioncontrolandaplatformforsharingtheapplication’ssourcecodewithyouandtheworld.Yeomanfacilitatedtheremainderoftheworkflow:scaffoldingwithYo,automationwithGrunt,andpackagemanagementwithBower.Withourappfullyscaffolded,wewereabletobuildourinterfacewiththedirectivesprovidedbytheIonicFramework,andwireupthereal-timedatasynchronizationforgedbyourFirebaseinstance.Withafewkeytools,wewereabletominimizeourdevelopmenttimewhilemaximizingourreturn.
Next,wewilltakeourfreshlyconstructedreal-timechatapp,krakn,anddeployittoanApachewebserverforconsumptionovertheWeb.OncemanuallydeployedtoApache,wewilldiscussautomatingfuturedeploymentsandoptimizingtheenvironmentforanAngularapplication.
Chapter2.DeployingtoApacheTheApacheHTTPserveriswithoutadoubtthemostcommondestinationforwebsitesandapplicationsbeingdeployedintoproduction.Becauseofthis,mostdevelopershavesomelevelofcomfortwithdeployingtoaremoteApacheserver,butwilllikelyhavelimitedexperienceindeployinganAngularapplicationtothisserverenvironment.TakealookatthegraphinthefollowingfiguretoseehowApachestacksupwhencomparedtoothertopservers:
Source:http://w3techs.com/technologies/cross/web_server/ranking
Inthischapter,wewillcoverthefollowingpoints:
ThingsneededtoproperlyhostanAngularapponanApacheserverTodeploytoaremoteApacheserverusingboththeFTPCLIandclientsToautomatedeploymentwithGitHubServiceHooksandSSHTooptimizeApache’sconfigurationtosupporttheuseofGoogle’sPageSpeedServiceandAngular’sHTML5ModeToavoidsomegotchasandpitfallsalongtheway
FromlocaltoremotePriortoautomatingsegmentsofyourworkflow,itisvaluabletotraversetheflowmanuallytoensurethatallphasesareaccountedfor,andtominimizevariablesintheprocess.MostdevelopershavelikelydeployedsourcecodetoeitherlocalorremoteApacheserversalike,andbecauseofthatIwillattempttofocusmyeffortsonthegotchasandnuancesthatapplytoapplicationswritteninAngular.
Upuntilthispoint,wehaveconductedalllocaldevelopmentonaNode.jsserver,providedbyrunningthegruntservercommandfromwithinourapplication’srootdirectory.Toclarifyanypossibleconfusioncausedbythisdivergence,Angularisdesignedtobeserveragnostic,andthereforecanbeservedfromalmostanybackendstackyoulike,includingApache.BecauseofAngular’sserveragnosticdesign,itisfullypossibletodevelopAngularapplicationslocallyservedfromApache.IencouragealocalNode.jsserveroverApache,becausethedeveloperexperienceofJavaScriptontheclientandserverisimprovedbynotintroducingalternatesyntaxandpossibleconfusiontherein.
DeploymentdestinationAllwebserversshareaconstantpattern,whichisasinglerootdirectorywhereallsitesorapplicationsareservedfrom.Apache’srootdirectoryistypicallynamed/public_html.Thiswillbetheremotelocationwhereweuploadallapplicationsourcecodeandresource.
TipApachecanlookatadifferentdirectoryasitsrootifyousoconfigure.Todoso,open/etc/apache2/conf/httpd.confinyourtexteditorofchoice(SublimeTextwilldonicely).Thenlookfortwolinesthatarethesameorverysimilarto:
DocumentRoot"/etc/lampp/public_html"
<Directory"/etc/lampp/public_html">
Here,youcanchangethepathand/orrootfoldernametowhateveryoudesire.RememberthatyourchangeswillnottakeeffectuntilyourestartApache.
AcomparisonbetweenthelocalandremotesetupBemindfulofthedifferencesbetweenyourlocalandremoteApacheenvironmentalconfigurations.Forexample,localdevelopmentenvironmenttoolssuchasXAMPP,MAMPP,andWAMPPoftenchangethedefaultdocumentrootdirectory’snamefrom/public_html(remote)to/htdocs(local).Youwillmostlikelyfindthatthismattersverylittleinyourworkflowoverall,butitcancausenotableconfusion.Beyondtheaforementioneddifference,itisusefultorunbothyourlocalandremotehttpd.conffilesthroughadifferenttool(seetheTroubleshootingdeploymentissuessectionformoredetails)toensuretheyareconfiguredasyouintend.
ManualdeploymentNowthatweknowApachewillwatchourremote/public_htmldirectory,wecanmoveforwardbyuploadingourfilestothatlocation.ThemostcommonwayofpublishingyourfilestoaremotewebserverisbyuseoftheFileTransferProtocol(FTP).FTPcanbeachievedthroughaCLIthatliveswithinthecoreofalloperatingsystems,bothopensourceandlicensed.Itiscommon,however,toutilizeanFTPclient,toagain,improveyourdeveloperexperience.ApplicationssuchasthefreeFileZillaandlicensedTransmitprovideahighlyusableinterfacefordragginganddroppingfilesfromyourdevelopmentworkstationontoyourremoteserver,apatternthatmostpeoplearecomfortablewith.
FTPingfromyourcommandlineAtsomepoint,youmayfeelthatusingthecommandlineisagruelingprocessincomparisontoaninterface,butithasitsbenefits,speedmainly,andtheftpcommandisnoexception.WebeginbyrunningtheftpcommandfollowedbytheIPaddressofourdestinationserverasfollows:
ftp123.4.5.678
TakenoticethatyourprompthaschangedtoreflectthatyouareindeedconductinganFTPsession.Itshouldreadftp>belowthepreviouscommand.InitiatinganFTPsessionwilltypicallyconnectyouatyourserver’srootdirectory,whichisnotwhereweintendtodeployourapplication.Therefore,wemustchangedirectoriesbyutilizingthefollowingcommand:
ftp>cdpath/to/your/public_html
TheCLIwillthenprovideyouwithfeedbackofeitherasuccessorfailure,alongwithyournewlocation.
TipIfyoursessioniseverinterruptedandyouneedtoleaveyourmachineinordertocomebacklater,itishandytoknowthecurrentlocationofyourFTPsession.Todoso,employthefollowingcommand:
ftp>pwd
OnceconnectedviaFTPtoyourremoteserverandwithinthe/public_htmldirectory,youcandeploykrakntoyourremoteApacheserver.Beforedoingso,wemustfirstensurethatwearewithinourlocalversionofkrakn.WhileconnectedtoFTP,youcanchangeyourworkstationlocationbyusingtheftp>lcdcommand,asfollows:
ftp>lcd/location/of/your/local/krakn/dist
TipMytendencyistoplaceallclonedGitrepositorieswithinasinglefolderonmydesktop,resultinginastructuresimilarto~/Desktop/clones/krakn/dist.Rememberthat/dististhelocationwhereGruntplacespost-buildfilesandresourcesthatareoptimizedfor
deployment.
OurFTPdeploymentworkflowwillbeasfollows:
1. Firstly,youneedtocreateanewdirectorynamedkrakn.2. Youcanthenchangetheremoteworkingdirectoryto/krakn.3. Toconclude,putallfilesfrom/location/of/your/local/krakn/distto
/your/remote/apache/server/public_html.
Thepreviousworkflowhasallbeenmadepossiblebyrunningthefollowingcommands:
ftp>mkdirkrakn
ftp
>cdkrakn
ftp>mput*
TheFTPmputcommandbehavesthesameasthestandardputcommandexceptthatyoucanpublishmultiplefilesinonecommand,while*isinterpretedasallfiles(orsometimesreferredtoasa“wildcard”).TheCLIwillagainprovidefeedbackonsuccessorfailure,soyoudonothavetogothroughandmanuallyinspectthatallfilesareindeedpresentandaccountedforonyourremoteserver.Onceyourfileshavebeendeployedsuccessfully,youcanexittheFTPCLIbyrunningthefollowingcommand:
ftp>close
FTPclientsThetwoFTPclientsImentionedearlierarejusttwoofthelargerfishinafairlylargepond.FileZillaisverypopularbecauseofitslackofcost,whileTransmit(OSXonly)comesatafairpriceanddeliversahighlypolishedUI.AllFTPclientsimproveupontheCLIbyimprovingthedevelopmentexperienceofthefollowing:
NavigatingtoyourownlocalfoldersandresourcesConnectingtoyourremoteserverNavigatingtoyourremotedestinationfolder,/public_htmlDrag-and-dropforuploadanddownload
ThefollowingisascreenshotofPanic’sTransmitFTPclient.Fromlookingatthis,youcanseehowTransmitprovidesasleekinterfaceforFTPingyourfilestoyourremoteserverenvironment.TheinterfaceinmostFTPclientsdividesthelayoutintotwocolumns.Theleftcolumnismostoftenthelocalharddrivefilesystemnavigator,whiletherightistheremoteserverfilesystemnavigator.Onceyourtwodestinationshavebeenselected,youcanselectyourfilesontheleftanddragthemtotherightforuploadingasshowninthefollowingscreenshot:
(source:http://panic.com/transmit/)
Theyalltendtofurtheraugmenttheuploadprocessbyprovidingyouwiththeabilitytointelligentlyuploadordownloadfiles.Takeforexample,thatyouaredeployingVersion2.0ofkrakn,oranyotherapplication,andyoudonotwanttoworryaboutwhichfileswerechangedandwhichfileswerenot,beforeuploading.FileZillawillallowyoutoselecteverythinganddropthemontheremoteserver.FTPclientswilltypicallyaskyouwhatactionyou’dliketotakeonoverwritingduplicatefilesornot.Youhavetheoptiontooverwriteexistingfiles,overwriteifthesourcefilesarenewer,overwriteifdifferentsize,renamethenewfiles,orskipoverthemalltogether.
ThisisextremelyhandyasitprovidesalevelofgranularitytoyouruploadordownloadthatisnotpossiblewiththecoreFTPCLI.OtherusefulfeaturesprovidedbymanyFTPclientsaretheabilitytoseewhat,ifany,filesfailedtouploadinreal-time,withthereasonforthefailure,andtheabilitytosaveconnectionsettingsforreuse.ThelatterfeatureisreallysimplebutitisafeaturethattheCLIlacks.Furthermore,thesavedconnectionsaretypicallyexportableandimportable,asisthecaseinFileZilla.
AutomatingdeploymentwithGitHubandSSHGitHub’sfeaturesgowellbeyonddistributedversioncontrolinthecloud,whichisamazinginitself.InthesettingsforeachrepositoryhostedonGitHub,thereisasectionentitled“ServiceHooks”.Thisprovidesaninterfacetoautomateareactioneverytimeaspecifiedactiontakesplace.Forinstance,youcaneffectivelytellGitHubwheneverIpushtomyremotemasterrepository(theaction)todo“something”(thereaction).Inourcase,that“something”willbetorunaspecific.PHPfileonyourremoteApacheserverthatinitiatesagitpullfromthesamerepository.Thedeveloperandblogger,JeffreyWay,firstdocumentedthistechniqueinanarticleandvideohepublished(whichyoucanaccessathttp://goo.gl/qgFyg4)onthetutorialsitetutsplus.com(whichwasformerlynettuts.com).WewillexploreconfiguringyourremoteGitrepositoryfordeploymentwheneveryoucompleteapushtotheremotemasterrepository.
NoteNotethatyouwillneedtoattainSSHaccesstoyourremoteApacheservertocompletethisautomation.AttainingSSHaccesstoyourserverwillvaryfromhostingprovidertoprovider,soitisbesttosimplyGoogle“yourWebHost+SSH”tofindhosting-specificinstructions.
1. OnceSSHedintoyourserver,youwillneedtogenerateanewSSHpublickeyforyourremoteserverenvironment,tosecurelycommunicatewithyourGitHubrepository.Thisisachievedbyrunningthefollowingcommandonyourserver:
$ssh-keygen-trsa-C"your_email@example.com"
2. ThenyouwillbeaskedtocreateandverifyanewpassphraseforthenewlycreatedSSHpublickeyasfollows:
Enterpassphrase(emptyfornopassphrase):[Typeapassphrase]
Entersamepassphraseagain:[Typepassphraseagain]
3. Whenthepassphrasehasbeensuccessfullyassigned,youwillreceivethefollowingresponse:
Youridentificationhasbeensavedin/Users/you/.ssh/id_rsa.
Yourpublickeyhasbeensavedin/Users/you/.ssh/id_rsa.pub.
Thekeyfingerprintis:#
01:0f:f4:3b:ca:85:d6:17:a1:7d:f0:68:9d:f0:a2:dbyour_email@example.com
4. TofullyaddthenewSSHpublickeytoyourApacheserver’sSSH-agent,runthefollowingcommand:
ssh-add~/.ssh/id_rsa
5. WewillthencopythenewlycreatedSSHkeytoourlocalclipboardforuseonGitHub.comasfollows:
pbcopy<~/.ssh/id_rsa.pub
TocompletethesecureconnectionbetweenyourremoteapacheserverandGitHub,youwillneedtoaddthenewlycreated/copiedSSHpublickeytoyourGitHubaccount.Todosoperformthefollowingsteps:
1. Firstly,selecttheglobalAccountSettingslinkthatisalwayspresentneartherightsideofGitHub’snavigation.
2. YouthenneedtoselecttheSSHKeysmenuitemwithintheleftsidebaroftheAccountSettingspage.
3. NowselecttheAddSSHKeybutton,enteradescriptivenameforyourremoteApacheserver,andpasteinyournewlycreatedSSHpublickey.
4. Finally,clickingontheAddKeybuttonwillpromptaverificationofyourGitHubpassword.NowGitHubandyourremoteApacheservercansenddatato-and-fro,usingtheSSHprotocol.
Followingthis,wewillenableGitHubservicehooksfromwithinourrepository’ssettings.Todosoperformthefollowingsteps:
1. YoushouldfirstnavigatetotherootofyourrepositoryonGitHub.com,somethingsimilartohttps://github.com/YourName/krakn.
2. OntheleftofthepageselecttheSettingsmenuitem,justabovetheSSHcloneURL.Then,selectthethirdmenuitemwithintheSettingsviewthatreadsWebhooksandServices.GitHubdefinestheseservicesas“pre-builtintegrationsthatperformcertainactionswheneventsoccuronGitHub.”
3. Next,selecttheAddServicebuttonsothatwecanselectthePost-ReceiveURLsoptionfromthedrop-downmenu.AtthispointintimeyouhavenoURLtopasteintothePost-ReceiveURLfield,soyouwillneedtocreateanewfilewithintherootofyourrepositorycalledgithub-pull.php.ThecontentsofwhichisonlyasinglelineofPHPcodeasfollows:
<?php`gitpull`;?>
TheabovecodewillexecutethegitpullshellcommandforyoufromyourremoteApacheserver,whichisexactlythedesiredreactionyouwanttoexecutewheneveryoupushtoyourGitHubrepository.
4. Youwillthenneedtouploadthegithub-pull.phpfiletoyourserverwitheitherFTPorbySSHingintoyourserverandrunningaGitcloneandpullofyourdesiredrepository.OncepresentonyourremoteApacheserverinthelocationyou’dliketoautomaticallypullyourrepository,youwillneedtofigureouttheexactURLofthegithub-pull.phpfilethatisnowonyourserver.
5. OnceyouhavetheURLcopiedtoyourlocalclipboard,youcanreturntoyourGitHubPost-ReceivesettingstopasteintheURLofyourgithub-pull.phpfile.Noweachtimeyoupushupdatestoyourremoterepository,GitHubwillrunyourPHPcodeonyourremoteApacheserverandautomaticallypullinthelatestcode.
TroubleshootingdeploymentissuesItisnearlyinevitablethattherewillsomedaybeanissuewithinyourdeploymentworkflow.Theseissuescanrangefromsomethingassimpleasforgettingtoincludeafileinyourput,orascomplexasoverridingyourenvironmentalconfiguration.Whatevertheissuemaybe,itisbesttohaveacontingencyplanforthisrainyday.Toolsareeveryourfriends,troubleshootingincluded.Thecornerstoneofanydeploymentissueisabulletproofdifftool.Difftoolsallowyoutocomparethecontentsoftwofilesorfolders.Take,forexample,youmistakenlypublishedanoldversionofyourapplication.Youcoulduseadifftooltocompareyourlocaldevelopmentsourcecodewithyourremoteproductionsourcecodetotellyouwhichfilesareoutofplace.Mostdifftoolssportsimilarinterfacesthatallowyoutoselecttwofoldersortwofilestocompareagainsteachother.Difftoolsarelikeusingamagnettofindaneedleinahaystack;theywillnarrowtheissuetoamanageablefocus.
AvisualdifftoolMeldisanopensourcediffandmergetoolthatrunscrossplatform,andsupportsbothfoldersandfilesalike.TodownloadMeldforyourdevelopmentenvironmentnavigatetohttp://meldmerge.org/.
Youcanseeinthefollowingscreenshot,thefiledirectoryforMeld.MosttoolslikeMeldofferasimilarinterfacetotheoneyousawpreviously.Theinterfaceistypicallydividedinhalf,withtheleftcontainingthefileorfolderthatistheoriginal,andtherightcontainingthefileorfolderyouarecomparingitto.Deletedlinesorfilesaredisplayedontherightinredfordeleted,andgreenforaddedasshowninthefollowingscreenshot:
UsingdiffwithGitIfyoufindyourselfinthetrenchesofadeploymentcatastrophewithouttools,andyouareusingGit,youcanrunadiffontwocommitsfromthecommandline.TodiffwithGit,runthefollowingcommandinyourterminalorcommandline:
$gitdiff<commit><commit>
or
$gitdiff<commit>—<path>
Theoutputwillresemblethefollowingscreenshot.Similartomostvisualdifftools,Gitdiffprovidesyouwithaline-for-line/file-for-filebreakdownofwhathasbeenaddedordeleted.Additionsaredisplayedasgreenwithaprepended+,whiledeletionsaredisplayedasredwithaprepended-asshowninthefollowingscreenshot:
ConfiguringApacheforAngularAngularapplicationscanrunwellwhenservedbyApacheunderitsdefaultconfiguration,butthereisundoubtedlyroomforimprovements,bothAngularspecificandotherwise.Wewillexploreaddingathird-partymoduletoextendApache’sdefaultglobalfunctionality,whileaddingsomerewriterulestosupporttheuseoftheHTML5HistoryAPIwithinyourAngularapplication.
NoteNotethatApachecanbeconfiguredinmanyvaryingwaystosupportalltypesofinfrastructuresandapplications.BeforemodifyinganyofApache’sconfigurationswithinaproductionenvironment,pleaseconsultwithyournetworkorserveradministrators.Ifyouareafull-stackdeveloper,thenyoushouldbegoodtogo!
Google’sPageSpeedServiceforApacheOptimizingawebsiteorapplicationisascienceuntoitsownandpeoplespendthemajorityoftheircareersstrivingtoshaveoffmillisecondsorcleanupjank(animationstutters).Therearewell-documentedbestpracticesthatallwebdevelopersshouldfollowlessthan60framespersecondtosomedegree,buttoolsexisttoachievebiggainswithminimaleffort.Google’sPageSpeedServiceisoneofthesetools.Itworksbyattemptingtoautomatealotofbestpracticesontheserver,beforethefilesaredeliveredtotheclient.Forexample,animagefileinproductionhasnotbeenoptimizedorcompressed.PageSpeedServicewilloptimizeorcompressitforyou,beforeitisdeliveredtoyourusers.
GooglePageSpeed,accordingtohttps://developers.google.com/speed/pagespeed/,isdescribedasa
“familyoftools[that]isdesignedtohelpyouoptimizetheperformanceofyourwebsite.”
ItisusefultothinkofGooglePageSpeedasapostdeploymenttoolstackforoptimizingthedeliveryofyourcode,similartoGrunt’sbuildprocess,butexecutedontheserverside.TheApacheHTTPServerisextensiblethroughmodules,andPageSpeedcanbeutilizedasanApachemodule.mod_pagespeedisonetoolinthesuitethat,accordingtohttps://developers.google.com/speed/pagespeed/moduleisdescribedastoolthat:
“rewrit[es]webpagestoreducelatencyandbandwidth.”
Todownloadandinstallmod_pagespeedforDebian/UbuntuLinux,runthefollowingtwocommandsinyourterminal:
$sudodpkg–imod-pagespeed-*.deb
$sudoapt-get–finstall
TodothesamebutforCentOS/FedoraLinux,runthefollowingtwocommandsinyourterminal:
$sudoyuminstallat
$sudorpm-Umod-pagespeed-*.rpm
Oncethemoduleisinstalledandenabled,youcanutilizeanyofitsmanyfiltersin/etc/apache2/mods-available/pagespeed.confforDebian/UbuntuLinuxand/etc/httpd/conf.d/pagespeed.confforCentOS/FedoraLinux.
SupportforAngular’sHTML5ModeAngularhasalesserknownmethodofthe$locationservicethatfacilitatestheconfigurationofhowyourapplicationinterfaceswiththeURL.Settinghtml5Mode(true)resultsinafundamentalchangeinhowAngularroutesviewsbasedontheURL,mostnotablybyremoving#/(thedefaultHashmode)fromAngular’sURLstructure.Enablinghtml5Modewillalsoresultinelevatednumbersof404Errorsifvisitorsattempttonavigatetodeeplinkedcontent.ThisunwantedsideeffectiscurablebyconfiguringApachetoautomatearedirectionto/index.htmlanytimean
unknownURLisattempted.Because/index.htmlbootstrapsyourAngularapplication,andsubsequentlyallroutes,itwillinterprettheURLaccuratelyandservethecontentyourvisitorintended.
TipPleasenotethatusing$locationProvider.html5Mode(true)enablesAngulartousetheHTML5HistoryAPIinsteadofthedefaultHashmode.Youcanfindoutmorebyvisitinghttps://docs.angularjs.org/guide/$location.
Theangular-uiorui-routerrepository’sdocumentationonGitHubprovidessnippetstoconfigureApache(andotherpopularwebserverenvironments)tosupporttheuseofhtml5ModeinyourAngularapplication.Thisispossiblebyaddingafiletotherootfolderofyourapplicationcalled.htaccess.Addinga.htaccessfilewillallowyoutoconfigureyourApacheenvironmentonasite-by-site(orapplication-by-application)basis,providingmoregranularcontroloveryourenvironment.Putmodestly,thefollowingsnippetrewritesallHTTPtrafficbackto/index.htmliftheURLdoesnotcontain#/(theHash).Because/index.htmlkicksoffallsubsequentrouting,yourvisitorwillbeservedtheirintendedcontent.Takealookatthefollowinglineofcommands:
<VirtualHost*:80>
ServerNamemy-app
DocumentRoot/path/to/app
<Directory/path/to/app>
RewriteEngineon
#Don'trewritefilesordirectories
RewriteCond%{REQUEST_FILENAME}-f[OR]
RewriteCond%{REQUEST_FILENAME}-d
RewriteRule^-[L]
#Rewriteeverythingelsetoindex.html
#toallowhtml5statelinks
RewriteRule^index.html[L]
</Directory>
</VirtualHost>
SummaryDeployingAngularapplicationstoApachecanbeassimpleorcomplicatedasyouprefer.Initssimplestform,youcanuseaclientthataugmentstheprocessforyou,resultinginadrag-and-dropinterface.Ifspeedisyourprimaryconcern(puttingthe“hot”inhot-fix),thentheFTPcommand-lineinterfacewilllikelybeyourweaponofchoice.Andifyoudon’tmindsomelevelofconfiguration,andyoufancyautomation,thenauto-magicallydeployingyourcodefromGitHuboneachpushisyourcalling.Howeveryou’vedecidedtomoveyourfilesfromAtoB,ApacheisundoubtedlyanenvironmentthatanyAngularapplicationcanbeproudtocallhome.
Comingupnext,wewillexploretheNode.jsserverenvironmentprovidedbythepopularplatformserviceprovider,Heroku.PreparetodivedeepintothedepthofNode.jswiththegoalofoptimizingittobestserveyourAngularapplication,usingthetoolsprovidedbyHeroku.
Chapter3.DeployingtoHerokuHerokuisoneofafewcloudapplication-hostingservicesthatenabledeveloperstospinupanddeploytotheirownprivateNode.jsserversatminimalcostandeffort.Heroku’sservicesgobeyondapplicationhosting,byalsoprovidingelasticscalability,databases,add-ons,andreal-timemonitoringtools.Priortonow,youhaveservedanddeployedyourapplicationtoalocalNode.jsserverandaremoteApacheHTTPserver.WewillexpandonthisexperienceandknowledgebydeployingtoaremoteNode.jsserverrunninginHeroku’scloudinfrastructure.Asyouhavelearned,AngularandNode.jsfitverywelltogetherbecausethestackempowersdeveloperstowriteanddeployJavaScriptonboth,theclientandserver.
Inthischapter,youwilllearnhowto:
EffectivelyusetheHerokuDashboardtocontrolyourapplicationDeploytoHerokuusingGitConnecttoyourHerokuenvironmentoverSSHOptimizeHeroku’sconfigurationforservingyourAngularJSapplicationAvoidsomegotchasandpitfallsalongtheway
SettingupyourHerokuenvironmentTherearemanydifferentwaystoleveragetheservicesthatHeroku’scloudoffers.WorkingwithaNode.jsstackwillbeourweaponofchoiceforthisdeployment,andisinmyopinionthebesthostingenvironmentforacomplexAngularapplication.
CreatinganaccountCreatingafreeaccountonHeroku.comisahighlystraightforwardprocess.Beginbynavigatingtowww.Heroku.comandclickingontheSignUpbutton.Youwillbepromptedforavalide-mailaddress—proceedbyenteringyourdailydrivere-mailaddress.Herokuwillthene-mailyouastandardaccountverificatione-mail.Oncereceived,selectthelinkwithinyouraccountconfirmatione-mailfromHeroku.Nowthatyouraccounthasbeencreatedandconfirmed,youwilllandatyourHerokuDashboard.
Heroku’sdashboardHeroku’sDashboardishowyouwillmanageyourapplication’sdeployment,dependencies,andresourceswithinHeroku’slargercloudinfrastructure.ItishelpfultothinkofyourHerokuenvironmentasancillarytoaVirtualPrivateServer(VPS)inthatyourenvironmentisprivate,andyouarefreetoinstallmostlyanysoftwareusingrootaccess(moreonthatintheupcomingSSHaccesssection).However,itdivergesfromatraditionalVPS,inthatyouareprovidedwithpreconfiguredserver-sidestacksthatsuitcommonwebapplicationstructures.Theseresultintheabilitytodeploy,run,andmanageapplicationswritteninRuby,Node.js,Java,Python,Clojure,orScalainonlyafewclicksorkeystrokes,withouttheneedtomanagephysicalorvirtualservers.Heroku’sserverstackautomationmodelisaviablewayforanywebdevelopertofurthertransitiontheirskillsetfromexclusivelyfrontendorbackendtofull-stack,bymeansofremovingalotofthepain-pointstypicallyinvolvedinrolling-your-owncloudinfrastructure.Thisempowermentisadirectfactorinboth,Heroku’spositivedeveloperexperience,andintheirsuccessasacompany.Gonearethedayswhendevelopersconcernedthemselveswithphysicalserverresourceconstraints,backups,migrations,andsoon,allthankstoinfrastructureservicessuchasHerokuandothers.TakealookatthefollowingHerokuDashboard:
DefininganewapplicationHerokuprovidestwomethodsforinteractingwithyourprivatecloudinstance.ThefirstisbyusingHeroku’sDashboard,whilethesecondisbyutilizingtheHerokuToolbeltcommand-lineutility.Therouteyouselecttodefineyournewapplicationwillnothaveimplicationsonfuturedeployments,normanagement.MyonlyadviceonthisdecisionisthatifyouhaveanexistingappthatisalreadysomewhatdevelopedandtrackedbyGit(suchaskrakn),theHerokuToolbeltCLIwillaccommodateyourexistingworkflowfromthestart,forreasonsupcoming.
TheHerokuToolbeltTheHerokuToolbeltisacommand-lineinterfaceforinteractingwiththeHerokuPlatformAPI,responsibleforfacilitatingallbidirectionalinteractionswithaHerokuinstance.Toolbeltismadeupofafewopensourceprojects(similartohowYeomanaugmentssub-projects)thatincludethefollowing:
TheHerokuclientForemanGit
Asmentioned,theHerokuclientinterfaceswithyourHerokucloudinstance.WhileForemanfacilitatestheuseofProcfile-basedapplicationslocally(moreonthisinTheProcfilesectionahead),andGitisincludedbecauseHerokustoresandinteractswithallsourcecodeintheformofremoteGitrepositories.
TasksthattheToolbeltfacilitatesincludethefollowing:
CreatingandrenamingappsRecyclingserversRunningone-offdynos(moreonthatlater)CapturingbackupsConfiguringadd-ons
InstallationToinstalltheHerokuToolbeltCLI,navigatetohttps://toolbelt.heroku.comandselectthepackagethatbestfitsyourdevelopmentenvironment’soperatingsystem(Windows,OSX,andLinuxareallsupported).Oncefullyinstalled,youmayneedtorestartyourterminalorcommand-linebeforetheheroku*commandsareavailableforusage.Toverifythatallherokucommandsworkasintended,runthefollowingcommand:
$herokuversion
Theoutputshouldreadsomethingsimilartothefollowing:
heroku-toolbelt/3.7.3.
SSHaccessAccessingyourHerokucloudinstancefromthecommandlineissimple,andisanalogousinfashiontoaccessingGitHub,bothusingSSHasthetransportprotocol.JustaswecreatedapublickeyforGitHub,wewillneedtocreatethesameforHeroku.Tobegintheconnectionprocess,runthefollowingcommandinyourterminal:
$herokulogin
TheoutputwillguideyouthroughtheloginandRSAkeygenerationprocesses.YouwillnoticethattheHerokuToolbeltprovidesamuchmorestreamlinedmethodasgiveninthefollowing,forcreatinganRSAkeywhencomparedtothemanualprocesswefollowedforSSHaccesstoGitHub.
EnteryourHerokucredentials.
Email:you@email.com
Password:
Couldnotfindanexistingpublickey.
Wouldyouliketogenerateone?[Yn]Y
GeneratingnewSSHpublickey.
Uploadingsshpublickey/Users/adam/.ssh/id_rsa.pub
TipAutoupdatewasaddedtotheToolbeltinVersion2.32.0.Ifyouhaveanolderversion,pleasereinstalltheToolbeltusingtheinstructionsabove.
NewappinToolbeltWithyourconnectionfullysetup,youarereadytocreateanewHerokuapplicationusingtheHerokuToolbelt—todoso,runthefollowingcommandsinyourterminal:
$cd~/Desktop/clones/krakn
$herokucreate
TheprecedingcommandswillcreateanewapplicationwithinyourHerokucloudinstanceandcreatearemoteHerokuGitrepository,resultinginthefollowingoutput:
Creatingkrakn…done,stackiscedar
http://krakn.herokuapp.com/||Gitremoteherokuadded
NewappindashboardFromyourdashboardyouhavethefacilitytomanageandconfigureallaspectsofyourhostedapplication,includingresources,add-ons,activitylogs,collaboration/access,customdomains,errorpages,andmore.Beforetheconfigurationoptimizationandtweakingbegins,youmustfirstdefineanewapplication.BeginbyselectingCreateanewapponyourDashboard‘shomepage.Youwillbepromptedtoenterthenameofyourapplication,alongwiththegeographicregionyou’dliketobehostedwithin;inourcaselet’sgowithkraknandtheUnitedStates.ThenameyouprovidewillthenbeusedbyHerokutocreateyourAppURLandGitURL.Takealookatthefollowingscreenshot:
TheAppURLiswhatyoumighthaveexpected,buttheGitURLiswhydeployingtoHerokuissuchanenjoyableprocess.BelowthetwoallocatedURLs,thereisalineofcodeyouwillusetosetupyourappforlocaldevelopment.Thecodeisasfollows:
$gitclone<your-git-repo-url>-oheroku
Theprovidedcodeessentiallyclonesanemptyremoterepository(automaticallyinitiatedforyouuponcreatinganewapplicationwithinyourdashboard)toyourdevelopmentenvironmentthatcanlaterbepushedtoyourproductionapplication.
Donotrunthiscommandwithoutfirstreadingthefollowingsections.
HerokubranchWhetheryouhavechosentocreateyournewapplicationusingtheHerokuDashboardorHerokuToolbeltCLI,theprovidedcommandisnotexactlywhatyouneed.Aspreviouslymentioned,theprovidedcommandwillcloneanemptyrepository,andbecausewealreadyhavecodethatisinneedofdeploying(krakn),wehavelittletononeedforanemptyrepository.Sothequestionthenbecomes,“howdowedeployourexistinglocalGitrepository,krakn,totherepositorythathasbeencreatedbyHeroku?”.TheanswerlieswithinGitbranches.Currently,kraknhastwobranchesthatyouhaveused:localmasterandremotemaster.Thelocalmasterisbasicallyyourdevelopmentbranch,whiletheremotemasterbranchisthesinglesourceoftruthstoredonGitHub(hencemaster).Whilethepreviousquestionisavalidconcern,thesolutionisinfact,simple.Wewillmodifytheprovidedcommandtosuitourneeds,whichinthiscaseistoaddtheHerokumaster
repositoryasanewremotebranch.
Theprecedingdiagramillustrateshowourdesiredbranchingschemewillwork.AlldevelopmentandadditionswilloriginatefromyourLocalMasterBranch,thesecommitswillbepushedandpulledfromtheRemoteMasterBranchonGitHub.TheadditionyouwillmakeisoftheRemoteHerokuBranchthatwasautomaticallycreatedasaresultofyoucreatinganewapplicationwithinyourHerokuDashboard.Toachievetheabovebranchscheme,runthefollowingcommandswithinyourterminalorcommandline:
$cd~/Desktop/clones/krakn
$herokugit:remote-akrakn
PredeploymentconfigurationInthesamewayyouconfiguredyourApacheHTTPserver,itisvaluabletoconfigureyourNode.jsserverbeforeexecutingyourdeploymentstrategy.SomeofthefollowingenhancementsandconfigurationsarenecessaryforhostinganAngularapplication,andsomearesimplygoodform,butallarerecommended.Youwillbeaddingsomefilestoyourapplicationandexamplesofthesefilescanbefoundinthe/web-appsubfolderwithinthekraknrepositoryonGitHub.
ExpressExpressisdescribedasa,
“minimalandflexiblenode.jswebapplicationframework,providingarobustsetoffeaturesforbuildingsingleandmulti-page,andhybridwebapplications.”
(Source:http://expressjs.com)
NoteThereisananalogyIfindusefulwhendescribingExpresstopotentialornewusersofNode.jsandthatis,“ExpressistoNode.jsasRailsistoRuby.”
Node.jshasnocorenotionofserver-sideMVCarchitecture,andExpressfillsthatgapbyprovidingasimpleAPIforworkingwithJavaScriptontheserver.Itprovidesusefulprimitivesforhandlingroutes,requests,views,andmore.Foryourpurposes,youwillbeusingNodeandExpresstoserveyourAngularapplication.ExtensiveknowledgeonExpresscanbeacquiredbynavigatingtoandreadingexpressjs.com/api.html.
GzippoGzippo(pronouncedg-zippo)isagzipcompressionmiddlewareforExpress/Node.jsapplicationsthatisdevelopedandopensourcedbyTomGallacher.Thiswillautomaticallycompressallassetsservedtoallclientsthataccessyourapplication,providingastellarperformanceimprovementtothealreadyfiercespeedofNode.jsI/O.
Package.jsonPackage.jsonisthefileusedtoconfigureaNode.jspackage.ItisusefultoviewanyapplicationyouintendondeployingtoaNode.jsserverasaNodepackage,withpackage.jsonasthepackagemetadata.Thesyntaxwilllookfamiliarifyou’veeverworkedwithJSON(JavaScriptObjectNotation)previously.Thepackage.jsonfilehasadefinedsetofkeysthattheNPMparserwillaccept,andthereforeitisoptimumtoknowthelimitsofwhatcanandcan’tbedone.Attheveryleastyouneedtospecifytheapplication’snameandversion,astheyarerequiredforNPMtoparseyourpackage.jsonfile.Itisgoodform,however,toincludetheauthor,adescription,dependencies,developmentenvironmentdependencies,repositoryinformation,andlicensetype.Thefollowingsnippetisthecontentsofthepackage.jsonfileyouwillfindwithinthekrakn/herokudirectoryonGitHub.TakenotethatthepreviouslydiscussedExpress.jsand
Gzippoarebothincludedasdependenciesofthekraknpackage,asthesedependenciesareneededtoinstallwithinyourNode.jsserver.
{
"name":"krakn",
"version":"0.0.1",
"author":"ZachariahMoreno",
"description":"Real-timechatapplicationbuiltatopAngularJS,theIonic
FrameworkandFirebaseforthebookAngularJSDeploymentEssentials.",
"repository":{
"type":"git",
"url":https://github.com/zachmoreno/krakn
},
"license":"MIT",
"dependencies":{
"gzippo":"~0.2.0",
"express":"~4.2.0"
},
"devDependencies":{
"gzippo":"~0.2.0",
"express":"~4.2.0"
}
}
ForafullbreakdownofallkeysthatNPM’spackage.jsonparserwillaccept,navigatetoandreadnpmjs.org/doc/files/package.json.html.
TheProcfileAsmentionedpreviously,HerokurunsapplicationsinthecloudusinganopensourceprojectcalledForeman,ameansofcommunicatingasetofcommandsthatwillberunonyourapplication’sdynos(moreonthatintheupcomingScalabilitysection).Foremandoesthisbyfollowing:
“TheUnixprocessmodelisasimpleandpowerfulabstractionforrunningserver-sideprograms.Appliedtowebapps,theprocessmodelgivesusauniquewaytothinkaboutdividingourworkloadsandscalingupovertime.TheHerokuCedarstackusestheprocessmodelforweb,worker,andallothertypesofdynos.”
Whenitcomestoyourdesiredstack,weonlyneedtoincludeasinglecommandthatinstructsyourHerokuapplication’sdynostorunaNode.jsserver,whileusingtheweb.jsfileasNode’sconfiguration.ThecommandincludedinyourProcfilereadsasfollows:
web:nodeweb.js
WiththeuseofForemancomesadivergenceinthetoolusedtoserveyourapplicationlocally,withinyourdevelopmentenvironment.Upuntilthispoint,youhavebeenrunningalocalNode.jsserverbywayofrunningthegruntservecommand.ForemanisincludedaspartoftheHerokuToolbelt,becauseHeroku’scloudusesForemaninconjunctionwithyourProcfile,tocontroltheprocessesrunonyourenvironment’sdynos.YourlocalForemanisavailablebyrunningthefollowingcommandswithinyourterminalorcommandline:
$cd~/Desktop/clones/krakn
$foremanstart
18:06:23web.1|startedwithpid47219
18:06:23web.1|=>Awesomewebapplicationserveroutput
WhenForemanisrun,itwillreplicateyourremoteHerokuenvironmentonyourlocaldevelopmentenvironment.Thelevelofprecisionisvitalwhendevelopingfeaturesorfixesforaproductionapplication.ThemainconsiderationwhenmakingthedecisiontouseforemanstartovergruntserveisthattheNodeserverprovidedbygruntservewillnotrunExpress,Gzippo,oranyotherNodepackageunlessconfiguredotherwise.Asidefromthatconcern,thereisnoreasonwhyyoucan’tcontinuelocaldevelopmentusingtheNode.jsserverprovidedbythegruntservecommand.
Web.jsSotheProcfileisresponsibleforinstructingyourHerokuapplicationenvironmenttorunaNode.jsserver,andyouconfiguretheNode.jsserverwiththecontentsofafilenamedweb.js.YoudefinedtheExpressandGzipponodepackagesasdependencieswithinyourpackage.jsonfile,nowyouwillputthemtoworkwithinyourweb.jsfile.Theexpress()methodisthenamespaceforallExpressAPIcalls,andyouwilluseitheretocreateanewappandstorelogfileswithintheHerokudevelopmentenvironment.Gzipandservetheapplicationsourcecodeandassetsfromthe/distdirectoryinsteadofthedefaultrootfolder.
Andlastly,starttheNode.jsserveroneitherthedefaultenvironmentalHTTPportorport5000ifoneisnotdefined.
NoteRecallthatYeoman/Gruntplacealloptimizedsourcecodefilesandassetswithinthe/distfolder,asaresultofrunningthegruntbuildcommand.Withoutthisconfiguration,yourGrunt-builtapplicationwouldnotrunproperlyunderHeroku’sdefaultsetting.
Takealookatthefollowingcommandlines:
vargzippo=require('gzippo');
varexpress=require('express');
varapp=express();
//StorelogfileswithintheHerokudevelopmentenvironment
app.use(express.logger('dev'));
app.use(gzippo.staticGzip(""+__dirname+"/dist"));
//ifyouhavehtml5modeenabledinAngular
app.use(function(req,res){
res.sendfile(__dirname+"/dist/index.html");
}
app.listen(process.env.PORT||5000);
ScalinganddeployingtoHerokuNowthatyouhaveadeeperunderstandingofhowHeroku,Node.js,Express,Gzippo,theProcfile,andtheweb.jsfileallworktogethertoserveyourapplication,itistimetocommencewithdeployment.BecauseHerokustoresallfilesasremoteGitrepositories,allthatisneededtodeploycodetoyourHerokuapplicationenvironment,isapush.SimplyrunthefollowingcommandinyourterminalorcommandlinetodeployyourcodetoHeroku:
$gitpushherokumaster
ThiscommandworksbecausetheremoteGitbranch,heroku,wascreatedforyouwhenyoucreatedyourapplicationeitherintheHerokuDashboardorToolkit.Atthispointifyounavigatetoyourapplication’sDashboardandviewitsactivity,youwillseealogofyourdeployment,alongwiththeGitSHA-1ofyourlatestcommitasconfirmation.
DynosTounderstandhowyourHerokuenvironmentcanscale,itisvaluabletofirstunderstandhowHerokumeasuresyourapplication.Herokuappliesthenotionofdynosasaunitofmeasurementforcomputingpower.AsingledynoisasingleUnixsandbox,responsibleforrunningasingleprocessorcommandspecifiedinyourapplication’sProcfile.Eachnewcommandyouaddtoyourapplication’sProcfilewillberuninitsowndyno.Heroku’sdocumentationbestoutlinesthefeaturesofdynosasfollows:
Elasticity&scale:Thenumberofdynosallocatedforyourappcanbeincreasedordecreasedatanytime.Routing:Theroutertracksthelocationofallrunningdynoswiththewebprocesstype(webdynos)androutesHTTPtraffictothemaccordingly.Dynomanagement:Runningdynosaremonitoredtomakesuretheycontinuerunning.Dynosthatcrashareremovedandnewdynosarelaunchedtoreplacethem.Distributionandredundancy:Dynosaredistributedacrossanelasticexecutionenvironment.Anappconfiguredwithtwowebdynos,forexample,mayendupwitheachwebdynorunninginaseparatephysicallocation.Ifinfrastructureunderlyingoneofthosetwodynosfails,theotherstaysup,andsodoesyoursite.Isolation:Everydynoisisolatedinitsownsubvirtualizedcontainer,withmanybenefitsforsecurity,resourceguarantees,andoverallrobustness.
ScalabilityAsnotedintheHerokudocumentation,dynosareelasticandscalable.ThisisachievedthroughtheForeman“processmodel(via[your]Procfile)thatletsthemscaleupordowninstantlyfromthecommandlineordashboard.Eachapphasasetofrunningdynos,managedbythedynomanager,whichareknownasitsdynoformation.”Toscalethesingledynorunningyourapplicationfromonetotwodynos,runthefollowingcommandwithinyourterminalorcommandline:
$herokups:scaleweb=2
Scalingwebprocesses…done,nowrunning2
Youcanchoosetospecifythenumberofdynosyou’rescalingto,asanabsolutevalueorasanincrementalvalue,illustratedinthefollowingcommand:
$herokups:scaleweb+2
Scalingwebprocesses…done,nowrunning4
TipIfatanypointyou’dliketoascertainalloftheprocessesbeingrun(dynos)byyourHerokuenvironment,youcanrunthefollowingcommandwithinyourterminalorcommandline:
$herokups
===web:`nodeweb.js`web.1:upfor2m
Add-onsJustastherestofHeroku’sfeatures,add-onscanbemanagedfromboth,yourDashboardandToolbelt.Herokucategorizesadd-onsaseitherdatastores,mobile,search,logging,e-mailandSMS,workersandqueueing,analytics,caching,monitoring,media,utilities,andpayments.Eachcategorycontainsseveraladd-onsthataredesignedtobeasflexibleastherestofHeroku’sinfrastructure.Forinstance,itcanbescaled,removed,upgraded,downgraded,andconfigured.Someadd-onsprovideadashboard,suchastheNewRelicadd-onthatprovides,“Monitor[ing],troubleshoot[ing],andtune[ingof]productionwebapplications.”Toenabletheuseofanadd-on,runthefollowingcommandinyourterminalorcommandline:
$herokuaddons:addnewrelic:stark
TheprecedingcommandsprovidedintheherokuToolbeltusetheverbsyou’dexpectthemtowhileinteractingwithyourapplication’sadd-ons.Runthefollowingcommandinyourterminalorcommandline:
$herokuaddons:upgradenewrelic:wayne
$herokuaddons:downgradenewrelic:stark
$herokuaddons:opennewrelic
Openingnewrelic:starkforkrakn.
$herokuaddons:removenewrelic:stark
TipTolistalladd-onscurrentlybeingusedbyanapplication,runthefollowingcommandinyourterminalorcommandline:
$herokuaddons
newrelic:stark
Ithelpstoconceptualizeadd-onsasbackendservicesthatimproveyourdeveloperexperiencethroughaidinginapplicationmanagement,performance,andanalysis.Someadd-onsincludeafreetier,sothereislittletonoharminexperimentingwithhowyoucanimproveyourapplicationbyaddingnewbackendservices.
TroubleshootingdeploymentissuesJustasdeploymentissuescanariseindeployingtoApache,mistakescanbemadewhendeployingtoHeroku.However,unlikeApache,Heroku’sdeploymentmodelisbasedonGit’sprotocolandnotFTP.WhileFTPisrobustenoughtofacilitatedeployments,itdoesnotincludethedeepfileanalysisthatGitdoes.Thisanalysisistypicallyusedforrevisioncontrolandfilediffing(comparisons),butitisalsousedwhenmergingbranches.AndmergingbranchesisexactlywhatyouaredoingwhenyoupushyourcodetoHeroku.
NoteRecallthatyouconductalldevelopmentonyourrepository’slocalmasterbranchandwhenyoupushtoHeroku,youaremergingyourlocalmasterbranchwithyourremoteHerokubranch.
BecausedeployingtoHerokuissimplyamergeofGitbranches,asummaryofthechangesmadeduringdeploymentisprovidedasoutputtoyou,afterthedeploymenthasconcluded.Itisvaluabletoanalyzethisoutputtoensurethatthechangesyouexpectedweremade,nothingmoreandnothingless.Intheeventthatunexpectedchangesweremade,youcanemployapreviouslycoveredtooltofurtherinvestigatethediscrepancy,thegitdiffcommand.Forexample,youjustconcludedrunningthegitpushherokumastercommandfromwithinyourlocalrepository’smasterbranch.Outputofthechangesisprovidedwhenconcluded,andyounoticethatyouforgottoaddadependencyforusewithinacontroller.Thefollowingcommandcanberuntoviewthecontentsoftheremotefileinquestion:
$gitremoteshowherokujs/controllers.js
Whilethisisnice,itismoreusefultorunthefollowingcommandtocompareyourlocalcontroller.jsfromwithinitsremotecounterparttoensurethemistakeiswhatyouexpect:
$gitdiffmasterheroku/masterjs/controller.js
Thefirstparameteristhelocalbranchname,thesecondistheremotebranchnameofthetwoyouintendoncomparing,whilethethirdparameteristhespecificfilepath/name.Thesamecommandcanberunwithoutaspecificfilename,andallfileswillbecomparedforyou.
SummaryDeploymenttoHeroku’scloudinfrastructureisadelightfulexperiencethatisboth,empoweringandfun.Herokuhasdevelopedanenvironmentthathasanumberofqualitiesthatmakeitastrongcontenderwhenchoosinganinfrastructureforyourapplicationorproduct.Thisisachievedbyincludingtheprinciplesofredundancy,flexibility,andextensibilityintoeveryfacetofHeroku.Thenotionofdynosaffordsdeveloperstheopportunitytoexerciseagranularcontrolovertheirapplication’sentireenvironment.Inthischapter,weexploredhowtocontrolyourapplicationfromtheDashboardandToolbelt,connecttoyourenvironmentoverSSH,deployyourapplicationwithGit,andoptimizeconfigurationforservingyourAngularapplication,allwhilefollowingthebestpractices.
Inthenextchapter,youwilltakeyourapplicationtothenewfrontierofFirebasehosting.Firebaseisanexcitingcompanythatprovidesagroundbreakingreal-timedatasynchronizationandstorageservice,andinMay,2014announcedthattheyareenteringintotheapplicationhostingbusinessaswell.
Chapter4.DeployingtoFirebaseHostingUnlikeHeroku,Amazon,orGoogle,FirebasehasonlybeenamajornameinPlatformsasaService(PaaS)since2013andhasonlybeenofferinghostingasaservicesinceMay13,2014.Ageaside,thepromiseofhostingyourapplicationsourcecodeandstaticassetsinthesameenvironmentasyourreal-timebackendhascreatedalotofinterestaroundFirebase.TheFirebaseteamis17peoplestrong,locatedatSanFrancisco,CaliforniaandwasrecentlypurchasedbyGoogleinOctober,2014.Theyhavebuiltasecure,reliable,andscalableservicethatsyncsanyapplication’sdataacrossclientsinrealtime.WhilemanyapplicationsofferthesamesyncingexperiencetotheirusersviaacustomAPI,theseAPIsaretypicallytosomedegreecoupledwiththeapplicationstheyserve(custommethods,andsoon.).FirebasedisruptsthisnotionbyallowingdeveloperstocreateanAPIfortheirapplicationinminutesthatisinnowaycoupledwithanapplication.Theout-of-the-boxfunctionalityincludesdatastorage,thecreate,read,update,anddelete(CRUD)methods,thecovetedbidirectionalreal-timesyncingbetweentheclientsandserver,andnowhosting.
Inthischapter,wewillcoverthefollowingtopics:
EffectiveuseoftheFirebaseForgedashboardManagingapplication-specificsecurityrulesSimulatingAPIrequestsandresponsesLeveragingtheFirebaseSimpleLoginauthenticationmodelDeployingyourcodeandassetstoFirebaseHostingTroubleshootingdeploymentissues
TheFirebasesetupAnalogouslytoHeroku,themajorityoftheservicesprovidedbyFirebaseareaccessiblethroughawebapplicationlocatedathttps://www.firebase.com,whiletheremainderareaccessiblethroughthefirebasecommand-lineinterface.Ourjourneybeginsbysettingupyouraccountonfirebase.com.
CreatingyourFirebaseaccountTocreateyouraccountwithFirebase,webeginbynavigatingtofirebase.com,andselectingtheblueSIGNUPbuttonontheright-handsideofthenavigationbar.Thisactionwillpromptyoutoenteryourdesirede-mailaddressandpassword.Oncethesedetailsareentered,selecttheblueCreateMyAccountbutton(itisagoodpracticetofirstreadtheTermsofServiceandPrivacyPolicybeforeagreeingtocreatetheaccount).Onceyouraccounthasbeenfullycreated,youwillbeabletonavigatetoyournewFirebaseForgedashboard.
UsingtheFirebaseForgedashboardThemajorityofthecontrolthatyouwillexerciseoveryourFirebasehosteddataandapplicationwilloccurwithinthecontextoftheForgedashboard.BecauseyoucanhostmultipleapplicationswithinyourFirebaseaccount,youwillfirstseetheoptionCREATENEWAPPortoaccesstheForgeofanexistingapplication,asshowninthefollowingscreenshot:
Tocreateabackendforyourapplication,startbyenteringthenameofyourapplication.UnlessthenameisalreadytakenwithinFirebase,theAppURLwilldefaulttohttps://<yourappname>.firebaseIO.com.AfterselectingtheCREATENEWAPPbutton,youwillbepresentedwithacardsimilartothetwo(middleandright)youseeinthepreviousscreenshot.Toaccessanapplication’sForgedashboard,selecttheblueManageAppbuttonnearthebottomoftheapplication’scard.
Yourapplication’sForgeisorganizedintotheData,SecurityRules,Simulator,Analytics,Login&Auth,Hosting,andSecretsnavigationitemsontheleft-handsideofthescreen.Thedefault,andlikelymostused,viewisData,asshowninthefollowingscreenshotinthenextsection.
UsingtheDataviewAfewkeyinterfaceelementstonotewithintheDataviewaretheImportJSONandExportJSONbuttons,theLegend,andtheexpandabletreestructureofyourdata.AlldatastoredandsyncedthroughFirebaseisintheJavaScriptObjectNotation(JSON)format,andthereforeJSONdatacanbeimportedandexportedforquickaccessfromwithintheDataview.TheLegendisinterestingbecausewhendataisChanged,Added,Deleted,orMoved,youwillseethechangetakeplaceinrealtime,anditwillbecolor
codedforquickvisualreference.(Youcanliterallywatchasyourvisitorscreateandmutatedatainrealtime.)YourdataisdisplayedinanexpandabletreestructuretorepresentnestedobjectswithinyourJSONschema.IndividualvaluescanbeeditedfromwithintheDataviewbyclickingonthevalue;objectscanalsobeaddedanddeletedmanuallyinthesamefashion.Takealookatthefollowingscreenshot:
IfyouarereadingthisandwereexpectingtoseeatraditionalSQLtableviewofyourdata,thennowwouldbeagoodtimetodoafewGooglesearchesfor“NoSQL”.JSONdatastoresarebydefinitionNoSQLandthereforeschema-less.Thiscanbeconfusing(especially,becauseIjustreferencedkrakn’sschema)atfirst,becauseNoSQLdoes,infact,enduphavingaschema;itisjustdefinedinyourapplication’ssourcecoderatherthanwithinthedatastore.
UsingtheSecurityRulesviewTheSecurityRulesviewcontainsalittlemorethanaplacetodefinetherulesforhowyourdatacanbeaddedormanipulated.FirebasehaveconstructedtheirownJSONformatforhowtheserulesshouldbedefined.TheeditorsectionoftheviewwillvalidatetheJSONstructuredrulesandprovidefeedbackinrealtime,makingitfairlyeasytowritevalidsyntax.SecurityRulesinJSONaredesignedtofollowthehierarchicalstructureofyourapplication’sJSONdata.Forexample,youwillspecifyall/wildcardrulesatthetopoftherulesobjectwith.read=falseand.write=false,asgiveninthefollowingcode:
{
"rules":{
".read":true,
".write":true
}
}
ThepreviouscodesnippetisthedefaultSecurityRulesviewthatallowsyoutoperformread/writeoperationsoneverynestedobject.Itisimportanttonotethatonceyouchangethesevaluestofalse,youwillneedtospecifytheconditionswhenaclientcanread/writetoanobject.Thisisillustratedintheforthcomingscreenshot.
Theremainderoftherulesarenestedwithintherulesobjectandcontaintherulesforyourtop-levelobjects.Inthefollowingexample,thispertainstothemessagesandusersobjects.ThereasonSecurityRulesarestructuredinthismannerisstraightforward;ifaruleisdefinedatthetopoftherulesobject,itwillcascadedowntoitsnestedobjectsandapplytothem,andifaruleisdefinedwithinanestedobject,itwilloverridethepreviousrule(s)andalsocascadedowntoitsnestedobjectsandapplytothem.Thisformatallowshighlyexpressiveruleswhileallowinganylevelofgranularityyourapplicationrequires.Inthefollowingexample,thiscascadinggranularcontrolisexpressedbymakingallthedatasecurefromthe.read/.writeoperations,whiletheseexpressionsarethenoverriddenbytheexpressionswithinthemessagesobject,wherethe.read/.writeoperationsare,infact,allowed.Beyondthe.read/.writeoperations,validationcanalsobeenforcedbyemployingthe.validatekey.
Inthefollowingexample,Iamvalidatingallofthenestedobjectswrittenwithinagivenmessage;thisincludesthetext,user,receivedTime,andthecatch-all$otherobjects.Aseachoftheseobjectsisuniqueandthereforerequiresexplicitvalidation,thevalidationrulescanbeexpressedasnestedwithineachobject.Forexample,thetextobject(thebodyofthechatmessage)validatesthatallthenewdataisastringthatislessthanorequalto1,000charactersinlength,whilethereceivedTimeobjectvalidatesthatallthenewdataisanumber.Takealookatthefollowingscreenshot:
Whenyouarriveathostingyourapplication,itisoptionaltospecifyyourSecurityRulesviewwithintheForgedashboardorasastaticfilenamedsecurity-rules.jsonthatyouhostalongsidetherestofyourapplication.Ifyouchoosetohostthesecurity-rules.jsonfilesinsteadofdefiningthemwithintheForgedashboard,youwillgaintheaddedbenefitofversioncontrolthroughGit,andyouwillstillhaveaccesstothembyselectingtheblueLoadRulesbuttononthetopoftheeditingelement.
UsingtheSimulatorviewTheSimulatorviewwithinyourForgedashboardprovidesyouwiththeopportunitytosimulatepotentialread/writeoperationsbeforeyoubegindevelopingyourapplication.Thesimulatorsupportsdifferentlevelsofauthenticationalongwiththeabilitytoattempt
readingandwritingtoandfromnestedobjects.Inthefollowingexample,IamsimulatinganAnonymoususerthatisattemptingtoreaddatafromthe/messagesobject.Oncesimulated,theoutputisprovidedontheresultofthesimulationwiththeparametersIselected.TheSimulatorviewisanexcellentwaytoquicklytestthesecurityrulesyou’vedefinedforanobjectatanylevel,andinthiscase,thereadoperationwasallowedbecauseofthesecurityrulesIhavedefined.Let’stakealookatthefollowingscreenshot:
Inthenextexample,Ihavealteredtheparameterstosimulateareadoperationfromthe/usersobjectasanAnonymoususer.Takealookatthefollowingscreenshot:
Thisresultisdeniedasthesimulation’soutputbecauseausercanonlyreadhis/herownuserdataandanAnonymoususercannotreadusers’datathisisalsodefinedwithintheSecurityRulesview.
UsingtheAnalyticsviewTheAnalyticsviewis,asitsnamesuggests,providesasnapshotofsomekeymetricsalongwithafewdatavisualizationsofBandwidth,DataStored,andConcurrentUsers.Mainly,you’llwanttomonitorandbemindfuloftheamountofTotalDataStoredtoensurethatyouarenotexceedingtheamountallottedforyourparticularstorageplanwithFirebase.FirebasehasasimilarpricingmodeltoAmazonWebServices;inthis,youarefreetouseandscaleyourservicestoyourheart’s/application’scontent,butyouwilleventuallypayforit.Inthefollowingexample,kraknonlyhas12.97KBofTOTALDATASTORED,used418.01KBofBANDWIDTHinthelast30days,andhadapeakofthreeconcurrentusersatonepointintime.Takealookatthefollowingscreenshot:
UsingtheSimpleLoginviewTheSimpleLoginviewwithinyourapplication’sForgedashboardprovidesaneasy-to-implementsolutionforyourapplication’sauthenticationmodel.YoucanspecifyAuthorizedRequestOrigins(client’sorapplication’sURLs)asanextralayerofsecurityinadditiontothepreviouslymentionedSecurityRules.Takealookatthefollowingscreenshot:
Firebaseapplicationsareallclientside,thereforethereisno“server”foryoutodefinethelengthofaloginsession.ThiscanbedefinedwithintheLoginSessionLengthsectionwithintheSimpleLoginview,thedefaultvaluebeing24hours.
ThebreadandbutteroftheFirebaseSimpleLoginsolutionistheabilitytodefineasetofauthenticationprovidersthroughtheOpenAuthentication(OAuth)standardprotocol.OAuthprovidesastandardprotocolforservicestoauthenticateuserswiththird-partyservicecredentialsinsteadoftheuserhavingtocreateyetanothersetofcredentials,resultinginabetteruserexperience.YouhavelikelyencounteredOAuthinthewild,whetheryourealizeitornot,asGoogle,Facebook,andTwitterhaveallembracedtheOAuthstandard,whichmeansthatother(typicallysmaller)servicescanauthenticateuserswiththeirexistingGooglecredentials.MoreinformationontheOAuth2.0standardcanbeattainedbynavigatingtohttp://oauth.net/.FirebaseSimpleLoginprovidesyourapplicationwithamodestwaytoleverageOAuthfromdifferentservicesinsteadofrollingyourownsolution.SupportedOAuthprovidersincludeFacebook,Twitter,Google,Persona(MozillaFoundation),Email&Password,andAnonymous.IhaveoptedforkrakntoonlysupportEmail&Passwordauthenticationforthesakeofsimplicity,asallsocialprovidersrequiretheattainmentofanOAuthtokenand/orAPIkey.Bydefault,theAnonymousauthenticationprovideristheonlysolutionthatisenabled,againforsakeofsimplicity.
Forkrakn,IhavedisabledtheAnonymousproviderandenabledtheEmail&Passwordprovider,asinthefollowingexample.TheEmail&PasswordprovidersupportstheabilitytosendPasswordResetEmailswithadefaultorcustomizedemailtemplate.Takealookatthefollowingscreenshot:
Lastly,alistofRegisteredUsersisavailabletoyouwiththeoptionstoDelete,Create,ormanuallySendPasswordResetEmail:
HostingyourapplicationFirebaseHostingcontributestoyourarsenalofenvironmentsthatareeasytodeployAngularappsto.Featuresoftheserviceincludeone-commanddeployment,SSLconnectionsoverHTTPS,domaincustomization,andcontentdeliveryforstaticassets.Toworkwithanddeployit,youwillneedtoemploythehelpofthefirebase-toolscommand-lineinterface.
Usingthefirebase-toolsCLIToinstallthefirebase-toolsCLI,openyourterminalorconsoleandrunthefollowingcommand:
$npminstall-gfirebase-tools
Theprecedingcommandwillinstallthefirebase-toolsalongwithallofitsdependenciesusingthesameNodePackageManagerthatwediscussedinChapter1,OurAppandToolStack.
ConfiguringyourFirebaseenvironment
YourFirebasehostedenvironmentisconfigurableviaafilethatyouwillneedtocreatenamedfirebase.json.Thefollowingcommandwillcreatethefirebase.jsonfilebyaskingyouafewquestions,suchasyourapplication’sname(thesameasyourFirebasebackend),soinmycase,itwouldbekrakn:
$cd/Desktop/clones/krakn
$firebaseinit
ThecreatedconfigurationfileisthenpopulatedwiththefollowingJSON:
{
//required&nameofbackend
"firebase":"krakn",
//required&subfoldercontainingyourproductionapp
"public":"dist",
//optionalinsteadofForge=>SecurityRules
"rules":"security-rules.json",
//optional
"ignore":[
"firebase.json",
".*",
"**/node_modules/**"
]
}
NowthatyourapplicationisbootstrappedforhostingonFirebase,youcandeployittoproductionbyrunningthefollowingcommand:
$firebasedeploy–m"youroptionalmessage"
Atthispoint,youcanreturntoyourapplication’sForgedashboard,andwithintheHostingview,youwillnowseealogondeploymentinsteadofthedefaultinstructionstoinstallthefirebase-toolsCLI.ThefollowingexampleillustratestheUIcontrolsprovidedwithintheHostingview;theseincludethenewlycreatedURLforyourapp,abuttontoUseaCustomDomain,DeploymentHistory,andabuttontoRollback.Takealookatthefollowingscreenshot:
Nowthatyourapphasbeenconfiguredproperlywiththecreationofthefirebase.jsonfile,youarefreetorun$firebasedeploy.Takealookatthefollowingscreenshot:
TroubleshootingdeploymentissuesAswiththeenvironmentswehavepreviouslydeployedto,deploymentissueswilleventuallyarise.Toensurethattheydon’tcompletelyruinyourday,itisbesttoresearchcommonpitfallsthatcouldcauseissuesinyourFirebasehostedapplication.
HTTPresourcesservedoverHTTPSAspartoftheFirebaseHostingservice,allthetrafficisautomaticallyservedoverSSL/HTTPS.Makenomistake,thisisapositivestatement,butitcouldpotentiallycauseissuesintheformofblockedcontentfromexternalresourcesthatareservedoverstandardHTTP.I’verunintothisissuewhendeployinganapplicationthatstillhasresourcesloadedfromaContentDeliveryNetwork(CDN)thatisn’tusingHTTPS.Forexample,navigatingtohttp://code.ionicframework.com/*causesanerrorwithintheFirebaseenvironment.Thankfully,thesolutionisstraightforwardenough.YousimplyhavetoreplacetheexternalresourcecallwitheitheraresourceloadedoverHTTPS(mostCDNsprovidethisservice),orloadtheresourcefromwithinthesameenvironment.So,insteadofloadingionic.min.cssfromtheIonicFramework’s(seeChapter1,OurAppandToolStack)CDN,http://code.ionicframework.com,youwillincludethefilewithinyourproductioncodeandrunthefollowingcommand:
$firebasedeploy–m"FixedHTTPresourceissue"
Oncetheissuehasbeenresolved,youcanviewalogofyourhostinginteractionsfromwithintheHostingviewinyourapplication’sForgedashboard,asshowninthefollowingscreenshot:
SummaryFirebasehaveearnedaspotasatopcontenderintheplatformasaservicearenabecausetheyarearguablyprovidingthebestdeveloperexperiencewhencomparedtotheserviceswecoveredthisfar.TheyprovideasimilarexperiencetoHeroku,butwithanumberofimprovementsoutofthebox,includingHTTPSbydefaultandoptimizedcontentdelivery.Moreover,IgetawarmfuzzyfeelingwhenIknowthatmyapplicationcode,APIlogic,anddatacanallbemanagedfromonelocation—Firebase’sForgeDashboard.ItisclearthatdevelopersaroundtheworldhavenoticedFirebaseandhavebegunusingtheirserviceswithinproductionapplications.Forexample,afewdaysbeforeGoogleIO2014,NestannouncedthattheirdeviceAPIsarebuiltatopFirebase.Inmymind,thisisahugevoteofconfidenceintheservicefromsomeofthetopcompaniestoday.
Inthenextchapter,youwilllearnhowtodeployyourAngularJSapplicationasamobileapppackagedusingApacheCordova.
Chapter5.DeployingaMobileAppWebdevelopmenthastraditionallybeendiscussedinthecontextofdesktopwebbrowsers,untilrecenttechnologicaldevelopmentsthathavegivenwebapplicationsanewcontextualpurpose.Thesenewcontextsaroseintheformofqualitybrowserstailoredtomobileandwearabledevices.Thisalonewasahugeleapforwardforwebapplications,astheybegantoevolvetomeettheneedspresentedbythesenewcontexts.Manydevelopers,andsomeusers,stillfeelthatwebapplicationsshouldbetreatedasfirst-classcitizensonmobiledeviceswithexperiencesthatareonparwithnativemobileapplications.ThisistheHolyGrailoftheWebanditscommunitybecausenewcontextsallowustotakeourskillstonewheights,andultimately,providethebestexperiencepossible,nomatterwhatthecontextofuseis.Mostusersdonotcareaboutwhatlanguagetheirfavoriteapplicationsorgamesarewrittenin;alltheycareaboutisenjoyingadelightfulexperiencenomatterwhatthedeviceorcontextis.ThisisthereasonopensourceprojectssuchasApacheCordova,FirefoxOS,andChromeOSwerecreatedtoprovidedeveloperswithnewopportunitiestoreachanddelighttheirusers.
Inthischapter,wewilllearnaboutthefollowing:
EmulatingmobileoperatingsystemswithinyourdevelopmentenvironmentforrapiddevelopmentandtestingPackagingyourAngularwebapplicationasamobileapplicationusingApacheCordova,AdobePhoneGapBuild,andthemobileChromeappstoolchainIncorporatingCordovapluginstotroubleshootbuild/deploymentissuesonyourphysicaldevicesDeployingyourapplicationtotheGooglePlayStore
ContextisthekingMostapplicationsdevelopedontopofatraditionalwebstack,includingAngular,weredesignedwiththeassumptionthatthemajorityofuserswillaccessitfromthecontextofadesktopwebbrowser.ThiswastheassumptionmadeformanyyearsuntiltheiPhonewasintroducedonJune29,2007byApple.TheiPhonewasthefirsttruly“smart”phone,whichmeansthatithadafull-featuredSafariwebbrowserandotherwebserviceintegrations.Itseemsthattheterm“gamechanger”wasinventedtohonorproductsdeliveredbyApple,andtheiPhonewasnoexception.Websites(andeverybodyelse)atthetimewereseeminglytakenbysurprise,andthediscussiononhowtooptimizeexistingwebsitesforthisnewmobiledevicecontextbegan,adiscussionthatisstillalivetoday.
Since2007,wehavelearnedfromthetrials,errors,andsuccessesofwebdevelopersthathavevettedoutthepainpointsandbestpracticesthatweallshouldfollowtoday.TheInternetasacommunityandplatformnowsupportmobiledevicecontextsbyadaptinglayoutsandstylestobettersupportmobileformfactors.Thesebestpracticesprovideabetteruserexperiencewhencomparedtousingawebsiteonlydesignedforthedesktopcontextwithinamobilecontext.However,whencomparedtonativemobileapplications,thisseeminglyimprovedexperiencesteadilydeclinesforthefollowingreasons:
Nodesign/UIstandardsNoaccesstonativedeviceAPIsLimitedsharingbetweenwebapplicationsAddednavigationalstepstoaccess
Withtheexceptionofthefirstreason,alloftheseconcernsaddressthecontextinwhichyouruseraccessesyourapplication.Contextisthekingbecausetheabilitytoprovidethemostrelevantinformationattherighttimeandplace(context)isamorepositiveexperienceforyouruser.Theseconcerns,ifleftunaddressed,wouldalwaysgiveanunfairadvantagetonativeapplicationsoverwebapplications.Thankfully,theopensourcecommunityhasbeenhardatworkaddressingtheseexactconcernsintheformoftheApacheCordovaproject.
WhatisApacheCordovaandhowdoesitaddressissues?TheApacheFoundation’sCordovaprojectisatoolthatprovideswebdeveloperswithameansofpackagingtheirentirewebapplicationwithanextremelylightweightand“chromeless”webbrowser.TheresultingpackagecomesintheformofanAndroid(.apk)oriOS(.ipa)filethatcanbemanuallyinstalledonamobiledeviceoruploadedtoanapplicationmarketplaceforconsumptionbyallofyourusers.TheexperienceofusingyourCordova-packagedapplicationversusanativeapplicationisnearlyidentical.Becausetheoperatingsysteminstalledinthepackageisthesameasanativeapplication,usersgetaniconontheirdesktoptolaunchit,resolvingtheissueofaddednavigationalstepstoaccess.Whentheapplicationlaunches,thereisnoURLinputfieldnorhomeandbackbuttons(thatis,achromelessbrowser),soyourapplicationisviewedinfullscreenlikemostothernativeapplications,addressingtheissueofaddednavigationandnon-standarddesign/UI.ThefinalissuesofnoaccesstonativedeviceAPIsandlimitedsharingbetweenwebapplicationsarebothaddressedbytheCordovapluginsystem.CordovapluginsbridgethegapbetweendeviceAPIsandJavaScriptAPIs.NeitherAngularnorvanillaJavaScriptprovideAPIstodisplayOS-levelnotificationsonyourusers’mobiledevice.Nevertheless,alotofdeveloperslikelywanttoutilizethisfunctionalityintheirCordova-packagedwebapplications,andthisismadepossiblethroughtheCordovapluginsystem.Cordovaissmartenoughtodeterminewhatdeviceitisrunningonandhowthatdevicehandlesnotifications,andtranslatesthenecessarydeviceAPIsintofamiliarJavaScriptobjectsforusewithinyourwebapplication.
ConfiguringyourdevelopmentenvironmentforApacheCordovaCordova,liketheothertoolswehavecoveredsofar,requiresinstallationandconfigurationonyourdevelopmentworkstation.BecauseCordovais,infact,dependentonalonglistofotherprojects,I’lldomybesttoprovidethemostaccurateinformationforthewidestarrayofdevelopmentenvironments.However,thetruthremainsthateachofCordova’sdependenciesrequiresdifferinginstructionsdependingonyourdevelopmentworkstation’sOS.Forexample,XcodecanonlybeinstalledonanOSXworkstation,soifyouwishtopackageyourAngularapplicationforiOS,youwillneedtouseamachinerunningOSXtodoso.Conversely,ifyouareintendingtodeployyourapplicationonWindowsPhone,youcanonlydosofromwithinaWindowsenvironment.
NoteTomyknowledge,theonlywaytogetaroundthisistorunavirtualmachinewithOSXinstalledastheimageOS,andinstallXcodewithintheVM.Forfurtherinstructionsonhowtodoso,navigatetohttp://blog.getspool.com/79/download-install-xcode-windows-7-8-pc/.
AwordonCordova’sdependenciesIwouldberemissifItoldyouthatsettingupyourenvironmenttopackageapplicationswithCordovaisaneasyprocess.Ithasareputationofbeingdifficult;however,theblamewouldbemisguidedifdirectedatCordova.Inmyexperience,thedifficultiesliewithinCordova’sdependenciestoproperlyinstallorconfiguretheAndroidSoftwareDeveloperKit(SDK)and/orXcode.CordovaisdependentontheAndroidSDKand/orXcodebecauseCordovaisonlyresponsibleforthree-quartersofthemagicthatresultsinyourpackagedmobileapplication.Thehigh-levelprocessbywhichyourapplicationispackagedgoesasfollows:
1. Youbuildyourworkingmobileoptimizedwebapplication.2. Youmakesurethatallassetsanddependenciesareincludedwithinyourapplication’s
rootfolder(noexternaldependencies).3. YourunCordovawithinyourapplication’srootfolderandtellitwhetherit’sdestined
forAndroidoriOS.4. Cordovabuildsyourapplicationwithachromelessbrowser,icon,andother
metadata.5. CordovahandsthebuiltapplicationofftotheAndroidSDKorXcodeandthey
packageitasa.apkor.ipafile.
Stepfiveiswheretheaforementioneddifficultieslie.Nevertheless,developershavebeenworkingonthisissueforafewyearsandtheprocessisnowlesspainfulthanever,butIstillhesitatetocallitapositivedeveloperexperience.
InstallingApacheCordovaCordova,likeothertoolsthatwehaveusedfordeployment,shipsintheformofacommand-lineinterface(CLI)thatyouwilluseinyourterminaloraCMDapplication.Toinstallthis,youwillagainusethenodepackagemanagerasfollows.
$sudonpminstall–gcordova
TipFortheCordovacommandstobemadeavailable,youmightneedtorestartyourterminalorCMDapplication.
NoteTheremainingdependenciesthatyouwillinstallareoptional,dependingonwhetheryourapplicationisdestinedforAndroidoriOS.IfyouareplanningonpackagingyourapplicationforAndroid,youwillneedtofollowtheinstructionstoinstalltheAndroidSDK;conversely,ifyouareplanningonpackagingyourapplicationforiOS,youwillneedtofollowtheinstructionstoupdateXTools.
InstallingtheAndroidSDKBeforeyouinstalltheAndroidSDK,itisagoodpracticetoknowwhatyouareabouttoinstallonyour(likelyexpensive)developmentworkstation.TheSDKprovidesyouwiththeAPIlibrariesanddevelopertoolsnecessarytobuild,test,anddebugappsforAndroid.
BecauseAndroidapplicationsaretypicallywritteninJava,theSDKshipsthemintheformoftheEclipseAndroidDeveloperTools(ADT),AndroidStudio(Betaatthetimeofwriting),andlastly,theSDKforanexistingJavaIDE.Allofthesethreeoptionswillinstallthetoolsnecessarytopackageyourapplicationasa.apkfilethatisreadytobeinstalledonaphysicaldeviceoremulator.Themoststableoftheseoptions,andinmyopinion,theeasiesttoinstall,istheEclipseADT.TheEclipseADTcomeswiththefollowingoptions:
Eclipse+ADTpluginAndroidSDKtoolsAndroidplatformtoolsAversionoftheAndroidplatformAversionoftheAndroidsystemimagefortheemulator
Foryourpurposes,theonlyfactorsthatareofusearetheSDKtools,platformtools,andemulator.Eclipseisjustdeadweightonyourworkstationandit’sbesttojustletitbe,unlessyouhaveaspirationsofJavadevelopment.TheSDKtools,platformtools,andemulatorallneedtobeconfiguredtoworkwithinyourdevelopmentenvironment.Tobegin,installtheEclipseIDEforyourdevelopmentworkstation’sOSavailablefordownloadfromhttp://developer.android.com/sdk.
NoteMakeanoteoftheinstalllocationoftheEclipseIDE/ADT,asyouwillneeditforfuturecommands.
Onceinstalled,youwillneedtoconfigurethetoolstoworkproperlyforusewithCordova.
ConfiguringtheAndroidSDKandtoolsCordovaisaCLI,anditisdependentontheAndroidSDK.IfyouguessedthattheSDKisasetofCLIsusedforworkingwithAndroid,thenyouarecorrect.Thecommandsdonotnecessarilyworkautomaticallywithinyourterminalorcommandline.Tofacilitatethis,youneedtoaddtheSDKtoolsandplatformtoolsinterfacestoyourdevelopmentenvironment’s$PATHvariable.
NoteYourdevelopmentenvironment’s$PATHvariableissimplyalistofcommandsthathavebeeninstalledtoworkwithinyourterminalorcommand-lineapplications.
OSXconfiguration
ToaddthetwoCLIsnecessaryforCordovaonOSX,openyour.bash_profilefileusing
thefollowingcommand:
$open~/.bash_profile
Thiswillopenthefileinyourdefaulttexteditorandallowyoutoaddthefollowingcodebelowanyexistingcodeinthefile:
#AddsandroidCLItoPATHvariable
exportPATH=${PATH}:/Applications/adt-bundle-<some-version-number>
>sdk/tools:/Applications/adt-bundle-<some-version-number>/sdk/platform-
tools
Forthecommandstofullywork,youwillneedtorefreshyour$PATHbyeitherclosingandreopeningyourterminalorbyrunningthefollowingcommand:
$source~/.bash_profile
Windowsconfiguration
ThefollowingscreenshotshowsthebasicinformationofWindowsOS:
ToaddthetwoCLIsnecessaryforCordovaonWindows,beginbynavigatingtoyour
desktop,right-clickonComputer,andselectProperties.WithinthePropertiesdialoguebox,selecttheAdvancedSystemSettingsmenuitemwithintheleftcolumn.Next,selectthePATHvariablefromtheEnvironmentVariablessection,andselecttheEditbutton.Typethefollowingcodeattheendoftheprovidedtextbox:;C:\Development\adt-bundle-<some-version-number>\sdk\platform-
tools;C:\Development\adt-bundle-<some-version-number>\sdk\tools
ThiswilladdthetwonecessaryAndroidCLIstoyourPATHvariable.Additionally,youneedtoaddthefollowingcode(belowthepreviouscode)toensurethatJAVAandANTaretheavailablecommands,bothofwhichwereinstalledwiththeAndroidSDK:
%JAVA_HOME%\bin
%ANT_HOME%\bin
Now,youcanSaveyoureditedPATHandsafelyclosetheEnvironmentVariablesdialogwindow.
NoteAtthispoint,whetheryouarerunningOSXorWindows,youshouldbeabletorunthefollowingcommandswithanyoutputwithoutanerroroutput.Ifyoureceivetheoutputsimilartocommandnotfound,thenrevisitthepreviousinstructions,rinse,andrepeatuntileverythingisconfiguredcorrectly:
$android
$java
$ant
Themostimportantofthesecommandsis$android,becauseitfacilitatestheinstallationandmanagementoftheavailableAndroidversions(alsocalledtargets)andemulators.TofinalizeyourAndroidconfiguration,youwillneedtoinstallthelatestversionofAndroidandcreateanemulatorforit.Bothwillbeusedtotestandpackageyourapplication.
InstallinganAndroidtargetandcreatinganemulatorToinstallthelatestAndroidtarget,beginbylaunchingAndroidSDKManagerbyrunningthefollowingcommand:
$android
AndroidSDKManagerfacilitatestheinstallationandmanagementofvariousAndroidtargets(OSversions),documentation,tools,andemulators,asshowninthefollowingscreenshot:
CordovaisexpectingthelateststableAndroidtargettobeinstalled.InthelistofAndroidtargets,selectthecheckboxtotheleftofthetwolatestAPIversions,beforeclickingontheInstallpackagesbutton(atthetimeofwriting,IinstalledtheAPIversions19and20).YouwillneedtoreadoverandAgreetotherequisiteTermsandConditionsforeachpackagebeforeinstallation.Oncetheinstallationhasfinished,youcansafelyclosetheAndroidSDKManagerwindow.
TipToviewalistofinstalledandavailableAndroidtargets,runthefollowingcommandat
anytime:
$android
NowthatthetwolatestAndroidtargetsareinstalled,youcancreateanemulatorwiththemfortestingyourCordovapackagedapplicationlocallyonyourdevelopmentworkstation.Tocreateyourfirstemulator,runthefollowingcommandwithinyourterminalorcommandline:
$androidcreateavd–n<your-emulators-name>–t<your-android-target>
Inmycase,Inamedtheemulatortarget19emulator,andIusedandroid-19asmyAndroidtarget.Takealookatthefollowingscreenshot:
Whenyourunthepreviouscommand,youwilloftenreceiveoutputsimilartothefollowing:
ValidABIs:default/armeabi-v7a,default/x86
Allthismeansisthattherearemultiplebuildsoftheandroid-19targetthatyoucanchoosefrombyappendingsomecodetothepreviouscommandandrerunningitasfollows:
$androidcreateavd–n<your-emulators-name>–t<your-android-target>--
abi<your-build-selection>
Whenasked,“Doyouwishtocreateacustomhardwareprofile[no]“,hittheEnter/Returnkeyandproceedwithoutmodification.WiththesuccessfulinstallationofthelatestAndroidtargetsandcreationofanewemulator,younowhaveeverythinginplacenecessarytobeginworkingwithCordova.
FromAngularwebapplicationstohybridmobileappswithCordovaWithallthenecessarytoolsinstalled,yourenvironmentconfigured,andyourAngularapplicationdeveloped,youareallsettobeginmovingyourAngularapplicationfromthebrowsertoAndroid.TogettheballrollingwithCordova,youcanrunthefollowingcommandfromwithintherootfolderofyourAngularapplication’ssourcecode:
$cordovacreate<subfolder-containing-all-cordova-code><reverse-url-of-
app><cordova-app-name>
IprefertonamethefolderthatwillcontainalltheCordovageneratedcode/mobileappbecauseitwillcontainallfuturemobileapplicationsyouintendtocreatesuchasiOS,Android,andsoon.BecauseIfollowedthisstandard,mycommandwasasfollows:
Nowthatyouhavescaffoldedthefoundationofyourfuturemobileapplication,youarefreetoaddtheplatformsyou’dliketopackage.Todoso,runthefollowingcommand:
$cordovaplatformaddandroid
Theoutputisasshowninthefollowingscreenshot:
Ihavetouchedonitbefore,butCordovacanpackageapplicationsforvariousplatforms,soyoucanrunasimilarcommandtoaddanothermobileOSasaplatform.IfyouareonaMacOSXsystem,youarefreetoaddthefollowingplatformsasbuildtargetsforyourapplication:
$cordovaplatformaddandroid
$cordovaplatformaddios
$cordovaplatformaddblackberry
Conversely,ifyouareonaWindowssystem,youarefreetoaddthefollowingplatformsasbuildtargetsforyourapplication:
$cordovaplatformaddwp7
$cordovaplatformaddwp8
$cordovaplatformaddandroid
$cordovaplatformaddblackberry
Witheachofthesetargetplatforms,thereexistsauniqueinstallationandconfigurationprocess,whichissimilartothestepsyoufollowedtoinstallandconfigureAndroid.Ifyouwouldliketodoso,youcanbeginbyrunningtheplatformaddcommandforyour
desiredtargetandfollowingtheinstructionsprovidedintheerroroutput.Theyaretypicallyverypithyandeasytofollow.
TipIfyouarepickingupaprojectthatincludesCordova,orinheritingone,youcanrunthefollowingcommandtoreceivealistofaddedplatformsastheoutput:
$cordovaplatformsls
Toremoveanaddedplatform,youcanrunthefollowingcommandwithcaution:
$cordovaplatformremove<platform-name>
Nowthatyou’veaddedAndroid,oranotherplatform,youarefreetotakeyournewlycreatedemulatorforaspinonyourdevelopmentworkstation.
DeployingyourapptoanemulatorRemembertheAndroidemulatoryoucreatedafewsectionsago?ItsprimaryfacilityistoprovideyouwithawaytotestyourapplicationwithintheAndroidOSenvironmentwithouttheneedforaphysicaldevice.Ithinkmostwebdeveloperscanagreethatoneofthecontributingfactorstoapositivedeveloperexperienceisarapiddevelopment/testcycle.Anemulatorisnotgoingtobeasfastasacycleorasfastasrefreshingyourbrowser,butitwillbefasterthanloadingtheappontoaphysicaldeviceeverytimeyoumakeachangetoyourcode.Totakeyouremulatorforaspinandtoseewhatisincludedbydefault,runthefollowingcommand:
$cordovaemulateandroid
Thiscommandwilltakelongerthan(likely)anticipatedtodisplayyourAndroidemulator,andthenitwilltakeanotherminute(s)tofullyboot.Whilebooting,theemulatorwilllooksimilartothefollowingimage.Patienceisavirtue,andthisisnoexception.
Oncetheemulateddevicehasfullybooted,youcanusethecontrolsontheleft-handside
alongwithyourcursortonavigatetheOS.TolocatetheCordovaapplicationloadedontothedevice,navigatetoApplicationDrawer.Youwillseesomethingsimilartothefollowingscreenshot:
ToopenyourCordova-packagedapplication,clickontheCordovaiconwiththenameofyourapplicationbelowit.Don’tbealarmedwhenyoudonotseeyourapplication’sinterface;instead,youwillseesomethingsimilartothefollowingscreenshot:
Thereasonwhyyouarenotseeingyourapplicationandinsteadseewhatisshowninthepreviousscreenshotisbecausewhenyouaddaplatformtoyourproject,itdoesnotautomaticallymoveoveryoursourcecode.ThereasonbeingthatyouwilllikelyhaveCordova-specificcodewithinyourapplication’smobileversionthatyouwillnothave(orwant)inyouroriginalapplicationsourcecode.ThisisalsothereasonforplacingallCordovacodeandapplicationswithinasubfolderofyourapplication’ssourcecode.Atthispoint,youarefreetoclosetheemulator,soyoucanbeginmovingyourcodeintoCordova.
Movingyourcodeinto/wwwIfyou’vetakenalookthroughthefoldersandfilesgeneratedbyyou,when$cordovacreate…and$cordovaplatformadd…wererun,youmighthavenoticedtheadditionofa/wwwfolder.Thisiswhereyourmobileapplication’ssourcecodewillliveandbepackagedfrom.
TipNowisagreattimetocreateanewGitbranchforyourCordova-packagedapplicationifyouhaven’talreadydoneso.Also,noneofthe$cordovacommandsthatfollowarespecifictoAndroidandthereforeallapplytoiOS,Blackberry,andsoon.
There’snoshameincopyingandpastingallofyourwebapplication’ssourcecodefromtherootfolderinto/mobile-app/www/.Infact,I’dliketostarthereanddealwitherrorsifany.NowthatyourapplicationcodehasreplacedthedefaultCordova“DeviceisReady”codewithyourAngularapplication’ssourcecode,it’stimetorinseandrepeatyourCordovabuildworkflow:
1. Type$cdlocation/of/your/angular/app/mobile-app.2. Add$cordovabuildandroid.3. Add$cordovaemulateandroid.
Allowtimetofullyboottheemulator.
4. Launchtheapplication.5. QAyourapplicationflow.6. Makethefollowingadjustmentstothecodeifneeded:
$cordovaemulate
7. Buildandreinstalltheapplicationwithintherunningemulator.8. Repeatsteps4-7untiltheapplicationhaspassedQA.
Takealookatthefollowingscreenshot:
Tospeedupyourdevelopmentworkflow,youcan“emulate”adevice’sdimensions,useragent,andnetworkspeedfromwithintheGoogleChromeDeveloperTools.ThiscanbeusefulifyoumakeasmallchangeandwanttoviewtheresultsquickerthanemulatinganOS.Todoso,you’llneedtolaunchaserverwithinyour/wwwfolderbyrunning$cordovaserveandroidandnavigatingtolocalhost:8000fromwithinGoogleChrome.Next,launchthedevelopertoolsbytypingCtrl+Shift+IonWindowsorCmd+Shift+IonOSX.Finally,clickonthemobilephoneiconlocatednearthetopright-handcornerofthedevelopertools.Oncethedevicemodehasbeenenabled,youcanselectapredefineddevice(Nexus5ischosen,asshowninthefollowingscreenshot)and/orthenetworkspeedtoquicklytestyourdevelopments:
DeployingyourapptoyourphysicaldevicewithCordovaYouwilllikelyquicklycometotermswiththefactthatallemulators,Androidnotexcluded,arepainfultodealwith.Itisalso,Ifeel,muchmoregratifyingtoseeandtouchthefruitsofyourlaboronyourowndevice.However,Cordovagivesyouthatwarmfeelingyougetwhenusingyourownapplicationonyourowndevice.Todoso,plugyourphoneintoyourdevelopmentworkstationviaUSB,andrunthefollowingcommandwithinyourterminalorcommandline:
$cordovarunandroid
NoteIfyouaredeployingyourapplicationtoyourphysicalAndroiddeviceforthefirsttime,youmustenableUSBDebuggingwithinyourdevice’sSettings.Formoredetailedinstructionsonhowtosetthisup,gotodeveloper.android.com/tools/device.html.
Theaforementionedcommanddoesessentiallythesamethingsastheemulatecommand,butinstead,itdeploysyourpackagedAngularapptoyourconnectedphysicaldeviceasaninstalledapplication.Inthepreviousscreenshot,Imovedtheapptomydesktopforeasyaccessandtookascreencaptureonthedevice(holdvolumedown+powertocaptureyourscreenonAndroid).Onceyoulocatetheinstalledapplicationwithyourappdrawer,feelfreetolaunchitandQAitsfunctionality,interface,andinteractions.SimilartodeployingandtestingyourapplicationwithinanAndroidemulator,yourworkflowwillbeasfollows:
1. Type$cdlocation/of/your/angular/app/mobile-app.
2. ConnectyourphysicalAndroiddeviceviaUSB.3. EnableUSBdebugging.4. Add$cordovarunandroid.
Allowtimetobuildtheapplicationandinstallitonaphysicaldevice.
5. QAyourapplicationflow.6. Makeadjustmentstothecodeifneeded.7. Add$cordovarunandroid.
Thiscommandbuildsandreinstallstheapplicationonaphysicaldevice.
8. Repeatsteps4-7untiltheapplicationhaspassedQA.
Takealookatthefollowingscreenshot:
NowthatyourapplicationhasbeentestedbothinanAndroidemulatorandonaphysicaldevicebywayofthecordovaemulateandruncommands,thetimehascometoexplorealternatetoolstacksthatachievethesameoutcome,butimproveyourdeveloperexperience.
FromAngularwebapplicationstomobileappswiththeCordovaChromeApptoolchainTheCordovaChromeApptoolchainisthenewestoptioninthewebapplicationtohybridmobileapptoolspace,havingonlybeenreleasedtothepublicinJune2014atGoogleIO.Itwastherefore,atthetimeofthiswriting,stillintheearlydeveloperpreview.
(Source:https://github.com/MobileChromeApps/mobile-chrome-apps)
BecausetheCordovaChromeApptoolchainisstillintheearlydeveloperpreview(alpha),Iwasnotabletosuccessfullydeploykraknasamobileappusingthe$ccacommand-linetool.Nevertheless,thebiggestcomplaintIhearfromotherwebdeveloperswhohaveattemptedtodeployawebapplicationasahybridmobileapplicationisthatout-of-the-boxCordovausestheAndroidbrowsertodisplayyourapplication’sUI.TheAndroidbrowserisnottobeconfusedwithGoogleChromeforAndroid,astheAndroidbrowserdoesnotsupportnearlyasmanyforthcomingAPIsasChromedoes.
NotePriortoAndroidv4.2,CordovapackagedappwasshippedwithanapplicationcalledtheAndroidbrowser,becauseastableversionofGoogleChromeforAndroiddidnotexist.ItwasduringthistimethatCordovawascreated,andthereforeCordovastillusestheAndroidbrowserapplication.
NowthatChromeforAndroidisverymuchstableandshipsasthedefaultbrowseronAndroidv4.2andhigher,weasdeveloperswanttoleveragetheforthcomingAPIsandChrome.Google’sanswertothisproblemintheCordovaChromeApptoolchain,whichextendsCordova,wastoreplacethebrowserituseswithGoogleChromeforAndroid.BecauseitisbuiltatopCordova,yourworkflowwillbestrikinglysimilar.
ConfiguringyourdevelopmentenvironmentfortheCordovaChromeApptoolchainTobegin,youwillneedtoinstallCCA,acommand-lineutilitythatwillbehaveverymuchlikethepreviouslyused$cordovaCLI.Todoso,runthefollowingcommandsinyourterminalorcommand-lineapplication:
$curl-L
https://raw.githubusercontent.com/creationix/nvm/master/install.sh|sh
$source~/.bash_profile||source~/.profile||source~/.bashrc
$nvminstall0.10
$nvmaliasdefault0.10
$sudonpminstall-gcca
ThiswillinstalltheNodeVersionManager(NVM)thatallowsyoutousevariousversionsofNode.jsonyourdevelopmentenvironmentalongwith$cca.
NoteBecausetheCordovaChromeApptoolchainextendsCordova,allofthedependenciesyouinstalledfortheprevioussectionarealsoneededforCCA.IfyouhaveskippedtheConfiguringyourdevelopmentenvironmentforApacheCordovasection,pleasegobackandfollowtheinstructionsgiventhere.
PackagingyourAngularwebapplicationformobilewithCCABecausetheCCAworkflowisstillintheearlydeveloperpreview,thefollowingwillbeanoutlineoftheworkflowinitscurrentstate.Beforefollowingthecomingworkflow,itwouldbewisetoconsultthecurrentdocumentationfortheprojectbynavigatingtohttps://github.com/MobileChromeApps/mobile-chrome-apps/blob/master/docs/GettingStarted.md:
1. Add$ccacreateYourApp.2. MoveyourAngularapplication’ssourcecodeintothenewlycreated/YourApp/www/
folder(inthesamefashionasCordova):
$ccaemulateAndroid
ThiscommandwillrunyourlocalAndroidemulatorwithyourappinstalledfortestingandQA:
$ccarunAndroid
ThiscommandwillinstallyourapponyourattachedAndroiddevicefortestingandQA:
3. Optionally,addiconsand/orasplashscreentoyourmobile.manifest.jsonfile:
$ccaprepare
Runthiscommandeverytimeyoumakeanupdatetoyourapplicationtorecompile.
WhiletheCordovaChromeApptoolchainisapromisingsolution,itisstillinneedofcommunitysupportandlovebeforeitbecomesaproductionreadysolution.Therefore,Iencourageyoutogiveitatryandprovideanyfeedbackyoucantohttps://github.com/MobileChromeApps/mobile-chrome-apps/issues.
FromAngularwebapplicationstomobileappswithPhoneGapBuildPhoneGapBuildisacloud-basedtoolthatachievesthesameresultastheApacheCordovacommand-lineutilitywithoutthesetup.ThekeydifferencebetweenApacheCordovaandPhoneGapBuildisthatCordovarunsonyourdevelopmentworkstation,andthereforeyouareinchargeofkeepingallofyourdependenciesuptodateandingoodworkingorder,whilePhoneGapprovidesacloud-basedbuildenvironmentandengineersatAdobemanagetheenvironmentforyou.Apartfromenvironmentalmanagement,PhoneGapprovidesaslightlydifferent(somewouldsayimproved)developerexperiencethroughtheirwebinterfacelocatedathttps://build.phonegap.com/.PhoneGapBuildrunsasawebapplicationonacloudinfrastructure.TheinherentimprovementsoverrunningCordovalocallyareasfollows:
IncreasedbuildspeedVersionandupdatemanagementCross-platformbuildsinoneclickNocommandline
TobuildandpackageyourAngularapplicationusingthePhoneGapBuildtool,webeginbynavigatingtotheaforementionedURLandcreatingafreeaccount.Onceloggedintoyournewaccount,youwillwanttocreateanewapplicationbyselectingtheblue+newappbutton.YouwillbepresentedwiththeoptiontoeitherimportyourAngularapp’ssourcecodefromGitHub(ifopensource)ortouploadyourapplicationasa.zipfile.Choosetheoptionthatbestworksforyourapplication,anduploadittoPhoneGap.Youwillthenbeaskedtogiveyourappanameandoptionaldescription.ThefollowingstepistheonlyconfigurationnecessarytopackageyourAngularapplicationformobile,whichisfairlyremarkablewhencomparedtothesetupforCordova.YouarenowfreetoselecttheblueReadytoBuildbuttontobeginthecloudbuildprocess.Youwillseeiconsforeachmobileplatformwithaloadingbarbeloweachthatindicateswhentheyhaveeachsuccessfullybeenbuilt.Assumingthatyourplatform(s)ofchoicehavesuccessfullybuiltandpackagedyourhybridmobileAngularapplication,youcaninstallyournewappbycapturingaphotooftheQRcodeonyourmobiledevice.
NoteYouwillneedaQRcodereaderapplicationinstalledonyourmobiledevicefortheQRcodetobetranslatedintotheapplicationthatcanbedownloadedfrombuild.phonegap.com.NavigatetotheAppStoreorGooglePlayStoreandsearchfortheQRcodetoinstallaQRcodereaderapponyourdevice.
ThefollowingisascreenshotofthePhoneGapBuilddashboardforthekraknapplication:
PublishingyourapplicationThereareafewstepsyouwilllikelywanttoundertakebeforepublishingyourapplication,suchasincludingyouriconandotherapplicationmetadatathatwillbeusedwhendisplayingyourapplicationonyourchosenplatform’sapplicationmarketplace.Todothis,youwillneedtomodifytheconfig.xmlfilelocatedwithinyourlocation/of/your/angular/app/mobile-app/foldertocontainthefollowingXMLcode:
<platformname="android">
<iconsrc="android/res/ldpi.png"density="ldpi"/>
<iconsrc="android/res/mdpi.png"density="mdpi"/>
<iconsrc="android/res/hdpi.png"density="hdpi"/>
<iconsrc="android/res/xhdpi.png"density="xhdpi"/>
</platform>
Youwillneedtocreatethesefiles,ofcourse,andplacetheminthecorrectlocationaspreviouslystated.Donecorrectly,fromnowonwhen,yourunanyofthe$cca*or$cordova*commands,youwillseethenewiconsonyourdeviceoremulator.Nowthatyourapplicationhasbeenfullytestedandhasthemarketplacemetadataincluded,youcanrunthefollowingcommandtooutputyourcoveted.apkfile:
$cordovabuild--releaseandroid
Thegenerated.apkfilecanbefoundwithinyourbinfolderatangular/app/mobile-app/platforms/android/bin/,andwillbenamedsomethingsimilarto<your-app-name>-release-unsigned.apk.The-unsignedportionofthenamemeansthatyouwillneedtosigntheapplicationbeforeitcanbepublishedtotheGooglePlayStore.
Signingyour.apkfileTosignyourunsigned.apkfile,youwillneedtorunitthroughanalignmentutilitytooptimizeitscontentforpublishingontheGooglePlayStore.YouwillbeginbygeneratingauniqueprivatekeyforyourapplicationbyutilizingthekeytoolCLIutilitythatwasinstalledaspartofyourAndroidDeveloperKitbyrunningthefollowingcommand:
$keytool-genkey-v-keystoreandroid-signing-key.keystore-alias
alias_name-keyalgRSA-keysize2048-validity10000
Youwillbepromptedtoprovideapassphrasefortheprivatekeyalongwithafewotherquestionsyouwillneedtoanswer.Whenthekeytoolisfinished,youwillhaveanewfilecalledandroid-signing-key.keystorewithinyourworkingdirectory.
NoteMakeanoteofbothyourprivatekey’spassphrase(necessaryforencryptingyoursignedapplication)andfilelocation,asyouwillneedbothforfuturereleasesofyourapplication.
Withyourprivatekeygenerated,youcannowuseittosignyourapplicationusinganotherCLIthatcomeswithyourADKcalledjarsignerbyrunningthefollowingcommand:
$jarsigner-verbose-sigalgSHA1withRSA-digestalgSHA1-keystoreandroid-
signing-key.keystore<your-app-name>-release-unsigned.apkalias_name
Lastly,youwillneedtorealignyour.apkfiletooptimizeitforpublishingontheGooglePlayStorebyrunningthefollowingcommand:
$zipalign-v4<your-app-name>-release-unsigned.apk<your-app-name>.apk
Theresultisthefruitsofyourlaborsofar—afullysignedandoptimized.apkfilethatcontainsyourAngularapplicationpackageforAndroidbyApacheCordova.
PublishingtotheGooglePlayStoreTheGooglePlayStore,alongwithAndroid,hasgrownfasterthananyothermobileapplicationmarketplacesinceitsinceptioninOctober2008.ThismakesitanexcellentplatformforyoutoengagewithnewandexistingusersviayournewAngularhybridAndroidapplication.TopublishanapplicationtotheGooglePlayStore,youwillneedtocreateadeveloperaccountbynavigatingtotheGooglePlayDeveloperConsoleatplay.google.com/apps/publish/signup/.Youwillbepromptedtopayanannual$25toregisterasaGooglePlayDeveloper,afairpricewhencomparedtotheannual$100requiredbyApple’sAppStore.AssumingthatyouarenowaregisteredGooglePlayDeveloper,youarefreetopublishyourapplicationtotheGooglePlayStorebyselectingthebluePublishanAndroidApponGooglePlaybutton,asseeninthefollowingscreenshot.Onceselected,youwillbepromptedtouploadyoursignedapplication,asyouwoulduploadanyotherfileinawebbrowser.Takealookatthefollowingscreenshot:
TroubleshootingdeploymentissuesCordovacontainsanothervaluabletooltohelptroubleshootissuesthatcanarisewhensettingupanewapplicationormaintaininganexistingapplication.Itfacilitatesaquickwayforyoutocheckwhetherthecodewithinyour/wwwfolderisnotcausinganyJavaScripterrors.ToquicklycheckwhetheryourCordova-builtapplication’scodeissound,runthefollowingcommand:
$cordovaserveandroid
TheCordovaserverwillstartalocaltestingserveronport8000withtherootbeing/www.YoucanthendebugyourCordova-builtapplication’ssourcecodelikeyouwouldanyotherwebapplicationwiththebrowserdevelopertools.TheoutputinyourterminalwhiletheserverisrunningisalistofHTTPtraffic,whichcanalsobeusedfortroubleshootingifyouarereceiving500errors.Finally,tostoptheserver,typeCtrl/Cmd+C.
IfyourapplicationisfunctioningasyouintendwithinthelocalCordovaserver,butnotonyourphysicalAndroiddevice,youmightconsiderusingaCordovaplugincalledCordovaConsole.Toaddthisplugintoyourdevelopmentversionofyourapplication,runthefollowingcommand:
$cordovapluginaddorg.apache.cordova.console
TheCordovaConsolepluginwillallowyoutoplacetraditionalJavaScriptconsole.log()methodcallswithinyourapplication’ssourcecodetooutputmeaningfuldebuginformationwhenrunonyourdevice.Similarly,ifyou’refeelingoldschool,youcanplacethealert()methodcallsinyoursourcecodetooutputthedebuginformationinanalertdialogbox.
Beforerunning$cordovabuild--releaseandroid,runthefollowingcommandtoremovetheCordovaConsoleplugininyourproductionbuild:
$cordovapluginremoveorg.apache.cordova.console
Furthermore,removealltheconsole.log()andalert()methodcallstoensurethebestpossibleuserexperience.
SummaryAsyouarewellawarebytheendofthischapter,deployingamobileAngularapplicationisalengthybutrewardingprocess.Withinthewebdevelopercommunity,thegeneralsentimentsaroundthesetypesofapplicationsisstillmixed.Nevertheless,therearemanydevelopersworkingtoimprovetheoveralldeveloperexperienceofdeployingawebapplicationtomobile.ThemostpromisingofwhichisFirefoxOS,builtfromthegroundupasaweb-basedoperatingsystemthatrunsnothingbutwebapplications.Thismeansthatnow,andinthenotsodistantfuture(inacceleratedwebtime),webapplicationswilllikelybeconsideredfirst-classcitizensonthetopofmobileplatforms,AndroidandiOS(hopefully)included.
Toconclude,youlearnedthebriefhistoryofhowwebapplicationscametomobileplatforms,howtoconfigureyourdevelopmentenvironmenttofacilitatethetransitionfromAngularwebtomobileapp,howtouseApacheCordovaandPhoneGapBuildaliketopackageyourAngularmobileapplication,andhowtopublishyouapplicationontheGooglePlayStore.IhopethatthischapterhasopenedyoureyestotheopportunitiesaroundbuildingmobileAngularapplicationstoengagewithawideraudience.
Staytuned,becausenextupyouwilllearnhowtodeployyourAngularapplicationasapackagedappforconsumptionontheChromeWebStore.
Chapter6.DeployingasChromeAppsGoogleChromehassucceededandcontinuestosucceedatitsmissionofMovingtheWebforward,andChromeAppsarejustoneofthefacetsofthissuccess.Chromeisinthebusinessofprovidingusersanddevelopersalikewiththebestexperiencepossible.YourAngularJSapplicationwillsoonbeabletoreachawholenewaudiencewithGoogleChromeasitsplatform.
Inthischapter,youwilllearnhowto:
ConfigureyourChromeinstancetotestandtroubleshootyourAngularJSChromeAppAugmentyourAngularJSapplicationforpackagingasaChromeAppPackageyourAngularJSapplicationasaChromeAppDeployyourapplicationtotheChromeWebStore
WhyChromeApps?ChromeAppsprovideauniqueopportunitytodeployyourapplicationinthesamecontextasatraditionaldesktopapplication.AnalogoustohowApacheCordovaallowsyoutodeployyourAngularJSapplicationinthecontextofatraditionalmobileapplication,ChromeAppsdothesame,butinthecontextofthedesktop.Thisisachievedbymimickingtheuserexperienceoftraditionaldesktopapplicationsandapplyingthesestandardstowebapplications.Becauseofthesestandards,usersexpecttoaccessyourwebapplicationsthroughtheirfavoritebrowser,andconverselytheyexpecttoaccesstheirdesktopapplicationsbylaunchingthemfromtheirOS’sprovidedmeans(Start|AllProgramsonWindowsandtheApplicationsfolderonMac).Beyondlocationandmeansoflaunchingtheapplication,anotherkeydifferenceisthatthedesktopapplicationstypicallyopenintheirownself-containedwindow.ChromeappsmimicthisstandardbyprovidinganAPIfordeveloperstoexpresshowtheirapplicationshouldbehaveinthisnewcontext.WewillexplorethesenewAPIsbydeployingthekraknapplicationasanAngularJSChromeApp.
ChoosingthebestapptypeTherearemultipleoptionstoconsiderbeforedeployingyourAngularapplicationasaChromeApp.Thankfully,theChrometeamhasrecentlyreleasedadecisionflowchartthatcanaidyouinexpressinghowyourapplicationwillmanifestwithinChrome.Thefollowingchartalsohelpsyoudistinguishbetweentheapptypesbyhowyourapplicationwilllookandbeused:
BecauseyouareapproachingChromeAppsfromtheperspectiveofalreadyhavinganAngularJSapplicationbuilt(oraspirationsofsuch),theonlychoiceyouwillhavetomakeisbetweenthehostedapptypeandthepackagedapptype.Thebiggestadvantageisthe2GBpackagesizelimitation.Ifthisisexceeded,youhavelittlechoiceandshouldmoveforwardwithahostedapp.
TheChromeAppsetupComparedtothepreviousenvironmentsthatyouexploreddeployingyourAngularapplicationto,Chromehasaveryminimalsetupthatrequiresalmostzeroconfiguration.Tobeginwith,youshouldhavethelatestversionofGoogleChromeinstalledonyourdevelopmentworkstation’sOS.IfyouhaveyettoinstallGoogleChrome,youcannavigatetohttp://BleedingEdgeBrowsers.comtoinstallthelatestbuild.
TipIfyouplanonusinganyofthechrome.experimental.*APIsinyourapplication,youshouldhaveeitherChromeCanaryorChromeDevinstalledtoensuresupport.YoucanenableexperimentalAPIsbynavigatingtochrome://flags.
Beyondinstalling,youwillneedtoconfigureChrometoacceptlocal/unpackagedextensionsfortestingyourAngularChromeApp.Therearetwowaystoachieveyourdesiredconfiguration.Thefirst(andthefastestoption)istolaunchyourChromebrowserandnavigatetochrome://extensions.ThesecondwayistoagainlaunchyourChromebrowser,navigateto,andselectthehamburgermenuicon.Fromthedrop-downmenu,selecttheSettingsmenuitemnearthebottom.FromtheSettingsview,selecttheExtensionsmenuitemtotheleftoftheview.NowallthatremainsistoselectthecheckboxthatislabeledDeveloperMode.WithDeveloperModeenabled,youwillnoticetheadditionofthreebuttonsaboveyourlistofinstalledExtensions.ThefollowingscreenshotillustratesthatDeveloperModeisindeedenabled,andtheLoadunpackedextension…,Packextension…,andUpdateextensionsnowbuttonsarevisible:
ThekeytakeawayhereisthatyoutoldChromethatyouwillbetestingeitheranextensionoraChromeAppwithinyourlocalinstance,andChromesaid,“Great,herearesometoolsyou’llneedtodothis.”YouwillusethesetoolstotestyourAngularChromeApplocallyandeventuallytopackageyourAngularChromeAppfordeploymentontheChromeWebStore.
AugmentingyourAngularAppforChromeNowthatChromeishelpingyouwithtestingandpackagingyourapplication,allthat’slefttodoistoaugmentyourexistingAngularapplicationtosupporttheChromeAppAPIsandstructure.WhenyouLoad[an]unpackagedextension…oranapplicationintoChromefortesting,itisexpectingtoseeanimportantfilethattellsChromehowyourapplicationwillwork.Thisfileiscalledmanifest.json.
Themanifest.jsonfileThemanifest.jsonfileisasimpleJSONfilethatcontainsinformationusedbyChrometomanifestyourAngularChromeApp.TherequiredkeysthatChromeneedstosuccessfullydisplayyourappincludemanifest_version,name,andversion.Theminimalsyntaxincludedinanyapplication’smanifest.jsonfileisasfollows:
{
"name":"appname",
"version":"0.1",
"manifest_version":2
}
IconsInadditiontotherequiredkeys,youwilllikelywanttoincludeseveralkeysinyourapplication’smanifest.jsonfile,iconsbeingoneofthem.Chromeisexpectingspecificsizediconstodisplayyourapplicationontheusers’computersandintheChromeWebStore.Theimagesizesare16pxx16px,48pxx48px,and128pxx128px.Toincludetheiconsinyourmanifest.jsonfile,appendthefollowingsyntaxbelowthemanifest_versionfile:
"icons":{
"16":"icons/icon_16.png",
"48":"icons/icon_48.png",
"128":"icons/icon_128.png"
}
ContentsecuritypolicyIfyourAngularapplicationislikekraknandleveragesFirebaseasyourbackendsolution,andyouareusingtheFirebaseSimpleLoginAPI,youneedtobeawareofChrome’sContentSecurityPolicy(CSP).TheCSPdoesnotallowyourapplicationtoloadexternalscriptsorexternalobjectresources.Askrakn’smodule.SimpleLoginTools.jsfiledoesexactlywhatCSPdoes,kraknwillnotconnecttoFirebase,asshowninthefollowingscreenshot,andthereforewillnotrunasaChromeApp:
TheCSPstatesnothingagainsttheuseofAngularJS,soitisperfectlylegitimatetocontinuedeployingyourAngularapplicationasaChromeApp.TheChromeAppCSPissynthesizedinthefollowingpoints:
“Youcan’tuseinlinescriptinginyourChromeApppages.Therestrictionbansboth<script>blocksandeventhandlers(<buttononclick=”…”>).
Youcan’treferenceanyexternalresourcesinanyofyourappfiles(exceptforvideoandaudioresources).Youcan’tembedexternalresourcesinaniframe.
Youcan’tusestring-to-JavaScriptmethodslikeeval()andnewFunction().”
YoucanrefertoChrome’sApppolicyathttps://developer.chrome.com/apps/contentSecurityPolicy.
Otherwaystocustomizeyourmanifest.jsonfileCommonadditionalpropertiesareavailabletocustomizeyourapplication’smanifest.jsonfile,whichareasfollows:
"default_locale":"en",
"description":"Aplaintextdescription",
"browser_action":{...},
"page_action":{...},
"author":"YourName",
"minimum_chrome_version":"versionString",
"offline_enabled":true,
"permissions":[...],
Forafulllistofavailablekeys,youcannavigatetohttps://developer.chrome.com/extensions/manifest.
Permissions,offline_enabled,author,anddescriptionareallusedtooptimallydisplayyourapplicationswithintheChromeWebStore,soitisadvantageoustoincludethesekeysinyourmanifest.Youneedtoincludeareferenceinyourmanifesttoa
background.jsfile.Youwillusethisfiletocreateaself-containedwindowforyourapplicationtolaunchwithin,achievingthesameuserexperienceasadesktopapplication.
Thebackground.jsfileYoucannameyourbackgroundfileswhateveryoulike,butbackground.jsseemstobethestandard.Theminimumcodethatyoushouldincludeinyourbackgroundfileisthefollowingsnippet,andnoAngular-specificcodeisneededwithinthisfile.Background.jsisusedbyChrometomanifestandappropriatelysizeyourChrome-packagedAngularapp’swindow.First,wewilllistenfortheapplicationlauncheventandprovideitwithacallbackfunctionthatwillhandleyourapplication’sreactiontothelaunchevent:
chrome.app.runtime.onLaunched.addListener(function(){
Onlaunching,youneedtospecifythatyourapplicationshouldopeninaself-containedwindowwithindex.htmlastheinitializerofyourapplication:
chrome.app.window.create('index.html',{
Youarefreetocustomizetheboundsofyourapplicationwindowwiththefollowingcode:
id:'appWindow',
bounds:{
width:200,
height:650,
left:100,
top:100
},
minWidth:200,
minHeight:650
});
});
DeployingtoyourChromeinstanceWiththeadditionoftheChromeApp-specificfiles,yourAngularJSapplicationisreadyfordeploymenttoyourlocalChromeinstance.Todoso,launchyourlocalGoogleChromeinstance(thesameonethatyouconfiguredforDevelopermode).Youcannownavigatebacktochrome://extensions,andselecttheLoadunpackedextension…buttonnearthetopofthepagetotheleft.YouwillthenbepromptedtouploadyourunpackedextensiontoChrome.
NoteYoudon’tneedtoziptherootfolderbeforecompletingthisstep.
Onceitisselectedanduploaded,youshouldbeabletoseetheadditionofyourChromeAppwithinthelistofinstalledextensionsandapps.Youmighthavealsonoticedthatthename,version,authordescription,andsoonhaveallbeendisplayed,courtesyofyourmanifest.jsonfile.NowthatyouhavedeployedyourAngularJSChromeApptoyourlocalChromeinstance,youcannavigatetochrome://apps,andyoushouldseeyourapplication’siconandnamewithinthelistofinstalledChromeApps,asshowninthefollowingscreenshot:
Notethatyouriconandnamearebothusedinthisinterface,andthatyourapplication
shouldhavebeenlaunchedinthesize/boundsthatyouspecifiedinyourbackground.jsfile.Ifyoufindtheneedtoupdateyourapplication’ssourcecode,manifest.jsonfile,orbackground.jsfile,youwillneedtoreturntothechrome://extensionspage,andclickontheUpdateextensionsnowbuttonnearthetopofthepagetotheright.ThiswillautomaticallypullinthelatestchangestoyourinstalledAngularJSChromeApp.
TroubleshootingdeploymentissuesIf,likeme,youareexperiencingdeploymentissueswithyourAngularJSChromeApp,takecomfortinthefactthattheChromeDeveloperToolscanbeusedtothesameeffectasonanormalhostedwebapplicationorsite.BeforetheChromeDevToolsareneeded,youwilllikelyseeanerrorjustbelowyourapplicationonthechrome://extensionspagerightafteryouuploadyourapplicationtoyourlocalChromeinstance.Ifso,navigatetochrome://appsandproceedwithlaunchingyourapplication.Now,youcaninspectthedamagedcodebynavigatingtochrome://inspectandnavigatingtotheAppslistfromtheleft-handsidemenu.YoushouldbeabletoseeyourapplicationlistedwithintheAppswithalinkbelowitthatislabeledinspect,asshowninthefollowingscreenshot.TolaunchDevTools,clickonthelink.ThebestplacetostartwithintheDevToolspageistheConsolepanel,whichislikeanyotherJavaScriptconsoleanditwillgiveyouanydetailederrormessages.ItisworthnotingthatyoucanusetheotherDevToolspaneltothesameeffectasonanyotherhostedwebapplicationorsite,includingperformanceaudits,timeline,andnetwork.
DeployingtotheChromeWebStoreDeployingtotheChromeWebStoreisverysimilartotheprocessyoufollowedinthepreviouschapterofdeployingtotheGooglePlayStorewithyourAngularJSHybridAndroidapplication.Tobeginwith,youwillneedtozipyourAngularJSChromeApp,whichyouwillsoonuploadtotheChromeWebStoreDeveloperDashboard.Onceitiszipped,navigatetohttps://chrome.google.com/webstore/developer/dashboard,andsigninwithyourGoogleaccount.WhenyouaresuccessfullyauthenticatedintotheChromeWebStoreDeveloperDashboard,theonlyrealactionyoucandoisclickontheAddnewitemontheright-handsideofthepage.Whenyouclickonthistab,youwillbepromptedtouploadtheZIPfileofyourAngularJSChromeAppthatyoucreated.Pleasedoso:
YouwillthenbepresentedwithaformtofurthercustomizehowyourChromeAppwillbepresentedwithintheChromeWebStore,suchasadetaileddescription,screenshots,YouTubevideo,promoimages,Analyticstracingcode,websites,andmoreasfollows:
Apartfromfurtherpromotionaloptions,thispageprovidesyouwithatoolforpreviewingyourpromotionaltiles,astheywillbepresentedwithintheChromeWebStore.Toutilizethistool,clickonthePreviewmypromotionaltilesbuttonnearthemiddleofthepage.Yourpromotiontilespreviewwilllooksimilartothefollowingscreenshot:
Nowthatyouhavefullycustomizedyourapplication’spromotionalexperienceallthatremainstodoistoselectthePublishapplicationbuttonontheright-handsideofthepagenearthebottomoftheform.YouwillbepromptedtoconfirmthepublishingactionandredirectedtoyourapplicationwithintheliveChromeWebStore,whichissimilartothefollowingscreenshot:
Congratulations!YoujustsuccessfullydeployedyourAngularJSChromeApptotheChromeWebStoreforconsumptionbymillionsofusers.
SummaryComparedtotheotherplatformsandenvironments,theGoogleChromeWebStoreisthenewestandmostexciting.Android,theChromebrowser,andChromeOSareallplatformsforuserstodiscoverandengagewithyourAngularJSChromeapplications.Itisexponentiallypowerfultobuildasingleapplicationthatcanbedeployedtoandthrivewithinsuchadiversearrayofenvironmentswhilemaintainingyourcreativevision.Toattainthispower,youlearnedhowtoconfigureyourChromeinstancetotestandtroubleshootyourAngularJSChromeApp.YouthenaugmentedyourAngularJSapplicationforpackagingasaChromeAppanddeploymenttotheChromeWebStore.Lastly,youexploredhowtocustomizeandpolishyourapplicationtobepresentedwithintheChromeWebStoretofurtherenhanceyourusers’experience.
Inthenextchapter,youwilllearnhowtomanagethepostdeploymentphaseofyourAngularJSapplication’slifecycle.Thisincludesapplicationmonitoring,analytics,deployingupdates,andmuchmore.
Chapter7.PostdeploymentYourstrategyandworkflowsforpostdeploymentmaintenance,fixes,andfeatureadditionscontributeinlargeparttohowyourapplicationwillbeenjoyedbyyourusers.Therefore,itiskeytoformandunderstandtheseworkflowswellbeforeyourbeginshippingupdatesintoproduction.
Inthischapter,youwilllearnhowto:
IncorporateGoogleAnalyticsintoyourAngularJSapplicationConfidentlydeployupdatestoalloftheenvironmentsweexploredsofar
FeaturesandfixesUpdatestypicallyfallintooneofthetwodistinctcategories:fixesandfeatures.MywishforyourAngularapplicationisthatyouspendthemajorityofyourtimeonfeaturescomparedtofixes.However,whenissuesdoarise,itisuptoyoutoformastrategybeforeyouareforcedtodeployahotfixintoproduction.Yourstrategyforhowyouhandledeployingfixeswillcontributetoyouruserperceptionandexperience,andweallagreethatperceptioniskey.
AddingsupporttoGoogleAnalyticsAddingGoogleAnalyticstoawebapplicationistypicallyastraightforwardprocess.However,whenyoumakethejumptoaSinglePageApplication(SPA)framework,suchasAngularJS,thingsgetalittlemorecomplicatedforGoogleAnalytics.BecauseofAngular’sng-viewdirective(withinyourindex.html)injectingcontentuponroutechanges,thetrackingnecessaryforGoogleAnalyticsdoesnotgetupdateduponsuchevents.Luckily,Angular’scommunityhassteppeduptothischallengeandproducedathird-partymodulecalledangular-google-analyticsthatresolvesthechallengesfacedinthisendeavor.Theangular-google-analyticsmoduleresolvesourworriesbyprovidingaservicethatsendsanewpagevieweventtoGoogleAnalyticswheneveryourAngularapplication’s$location.path()changes.
Settinguptheangular-google-analyticsmoduleI’llassumethatyoualreadyhaveaGoogleaccountwithaGoogleAnalyticssitesetupandreadytoreceivedata.ThismeansyoushouldalreadyhaveyourtrackingIDinhand,somethingsuchasUA-xxxxx-xx.Apartfromthis,allyouneedisyouralreadyinstalledBowercommand-lineinterface(CLI).
Webeginbyopeningyourterminalorcommand-lineapplicationandnavigatingtotherootofyourAngularapplication,orthefolderthatcontainsyour/bower_componentsfolder.Toinstalltheangular-google-analyticsmodulealongwithitsdependencieswithinyourapplication,runthefollowingcommand:
bowerinstallangular-google-analytics–save
Next,youneedtoaddareferencetothemodule’scodewithinyourindex.htmlfile(somewherebelowyourreferencetoAngularJS)asfollows:
<scriptsrc="bower_components/angular-google-analytics/dist/angular-google-
analytics.js></script>
Now,kindlyswitchovertoyourapp.jsfile,theonethatcontainsyourglobalappdefinition,andaddthefollowinglineofcodetoinjecttheangular-google-analyticsmoduleasaglobaldependency:
varapp=angular.module('yourAppName',['angular-google-analytics',…])
Allthatremainstobedoneistoconfigurehowyou’dliketoutilizeGoogleAnalyticswithinyourAngularJSapplication.ThebareminimumhereisyourpreviouslyattainedAnalyticstrackingID,anexampleofwhichisasfollows:
.config(function(AnalyticsProvider){
//initialconfiguration
AnalyticsProvider.setAccount('UA-XXXXX-xx');
//optionaltrackallroutes(ornot)
AnalyticsProvider.trackPages(true);
}))
.run(function(Analytics){
//injectAnalyticsatleastoncewithinyourapplication
//toautomaticallytrackallroutes
});
Anotheroptionthatyouhaveinsteadofinjectingtheanalyticsmoduleasadependencyoftheglobalrun()methodistoexplicitlytrackindividualpagesatthecontrollerlevel.Theonlydifferencewiththissetupisthatthereisanextralineofcodepercontroller,butit’snicetohavethislevelofgranularcontrolatyourdisposal.Toleveragetheanalyticsmoduleatthecontrollerlevel,first,injecttheanalyticsmoduleasadependencyofyourcontroller,andthencalltheAnalytics.trackPage()methodwiththeonlyargumentbeingtherouteyouwanttotrackasfollows:
.controller('radController',['Analytics',function(Analytics){
//createanewpageviewevent
Analytics.trackPage('/your/rad/route');
…
}]);
Thecontrolyouhaveoverthismoduledoesn’tstopthere.Itcanbeconfiguredtotrackanyothereventyoufindvaluable,supportcross-domainlinking,andeventotracke-commerce-specificeventswiththeuseoftheAnalytics.addTrans()method.Ifinterested,youcannavigatetohttps://github.com/revolunet/angular-google-analyticstolookoverthefulldocumentationorpossiblycontributetothiseffort.
NowthatyouhaveupdatedyourAngularJSapplicationwithausefulenhancement,youcanlearnhowtodeploytheupdatestoalloftheenvironmentswehavecoveredsofar.
DeployingupdatestoApacheInChapter2,DeployingtoApache,youlearnedhowtoconfigureyourApacheenvironmenttobestserveyouroptimizedAngularJSapplication.Fromthischapter,youlearnedhowtodeployyourAngularapplicationfromyourlocalApacheenvironmenttoyourremoteApacheenvironmentwiththeaidofFTPCLIandautomatedSSH.YouwillbuildonthisknowledgebylearninghowtodeployupdatestoyourproductionApacheserverwithbothFTPandSSH.
TheFTPcommand-lineinterfaceDeployinganupdatetoApachefromyourterminalorcommand-lineapplicationisahighlystraightforwardprocess.Allyouneeddoistoperformthefollowingsteps:
1. Launchyourterminalorcommand-lineapplicationasfollows:
$cdpath/to/your/local/apache/htdocs/app/dist
$ftp123.4.5.678
ftp>cdpath/to/your/public_html/app
ftp>mput*
ftp>close
2. Confirmthattheupdatewasasuccess.
TorecaptheFTPdeploymentworkflow;youneedtonavigatetoyourlocallybuiltAngularJSapplication,connecttoyourproductionApacheserverovertheFTPprotocol,navigatetotherootofyourproductionapplication,pushtheentirefolderfromlocaltoproduction,andfinally,closetheFTPconnection.
AnFTPclientAnFTPclientimprovesonthesamedeploymentworkflowbyaddingtheabilitytodraganddropyourfilesintoproduction.
1. LaunchyourFTPclient(FileZilla,Transmit,andsoon).2. Navigatetoyourlocallybuiltcopyofyourapplication’ssourcecodeontheleft-hand
sideoftheinterface.3. ConnecttoyourproductionApacheserverontheright-handsideoftheinterface.4. NavigatetotherootofyourproductionAngularapplication.5. Selecttheupdatedfiles/folders/resourcesontheleft-handsideanddragthemtothe
right.6. Confirmthattheupdatewasasuccess.
GitandSSHDeployingovertheSSHprotocolwithgitpushisthemostempoweringmeansofdeploymentIhaveencountered.Itencouragesthefollowingbestpracticesinyourworkflowsimplyasasideeffectofconfiguringyourproductionservertoaccepttheautomateddeployments:
1. Launchyourterminalorcommand-lineapplicationasfollows:
$cdpath/to/your/local/apache/htdocs/app/dist
$gitpushoriginmaster
2. Confirmthattheupdatewasasuccess.
TorecaptheSSHandGitdeploymentworkflow,younavigatedtoyourlocallybuiltAngularJSapplicationandpushedyourupdatedcodetoyourapplication’sGitHubrepository.RememberthatonceanupdateispushedtoGitHub,aservicehookistriggeredthatSSHestheupdatedcodetoyourproductionenvironment.
DeployingupdatestoHerokuInChapter3,DeployingtoHeroku,youlearnedhowtoconfigureyourHerokuenvironmenttobestserveyouroptimizedAngularJSapplication.Fromthischapter,youlearnedhowtodeployyourAngularapplicationfromyourlocalNode.jsenvironmenttoyourremoteHerokuenvironmentwiththeaidoftheHerokuToolbeltCLI.DeployingupdatestoHerokuisjustasimpleprocessasyourGitandSSHworkflowwejustcovered.Theonlydifferenceisthattheremotebranchyou’repushingtoisnotGitHub,butinstead,yourHerokuinstance.YouwillbuildonthisknowledgebylearninghowtodeployupdatestoyourproductionNode.jsserverwiththeHerokuToolbelt.
1. Launchyourterminalorcommand-lineapplicationasfollows:
$cdpath/to/your/local/apache/htdocs/app/dist
$herokulogin
2. AuthenticatewithyourHerokucredentialsasfollows:
$gitpushherokumaster
$herokulogout
3. Confirmthattheupdatewasasuccess.
TorecaptheHerokudeploymentworkflow,younavigatedtoyourlocallybuiltAngularJSapplicationandpushedyourupdatedcodetoyourproductionHerokurepository.Toensurethedeploymentwassuccessful,logintoyourHerokuDashboardandnavigatetoActivitytoviewalogofyourdeployments.
DeployingupdatestoFirebaseHostingInChapter4,DeployingtoFirebaseHosting,youlearnedhowtoutilizeyourFirebaseHostingenvironmenttobestserveyouroptimizedAngularJSapplication.Fromthischapter,youlearnedhowtodeployyourAngularapplicationfromyourlocalNode.jsenvironmenttoyourremoteFirebaseHostingenvironmentwiththeaidoftheFirebaseCLI.DeployingupdatestoyourFirebaseHostingisjustassimpleaprocessasyourHerokuworkflowwejustcovered.TheonlydifferenceisthattheFirebaseCLIfacilitatestheupdatepushbywayofthedeploycommand.
1. Launchyourterminalorcommand-lineapplicationasfollows:
$cdpath/to/your/local/apache/htdocs/app/dist
$firebaselogin
2. AuthenticatewithyourFirebasecredentialsasfollows:
$firebasedeploy–m"yourupdatesummary"
$firebaselogout
3. Confirmthattheupdatewasasuccess.
TorecaptheFirebasedeploymentworkflow,younavigatedtoyourlocallybuiltAngularJSapplicationandpushedyourupdatedcodetoyourFirebaseHostingproductionenvironment.Toensurethedeploymentwassuccessful,logintoyourFirebaseForgeDashboardandnavigatetoHostingtoviewalogofyourdeploymentsortoRollbackfortheupdate.
DeployingupdatestomobileappsInChapter5,DeployingaMobileApp,youlearnedhowtobuildyourAngularapplicationandpackageitasahybridmobileapplicationwithsomeadditionstoyourtool-stack.Fromthischapter,youlearnedhowtodeployyourAngularhybridapplicationfromyourlocaldevelopmentenvironmenttotheGooglePlayStoreforconsumptionbymillions.DeployingupdatestoyourAngularJShybridapplicationisanenjoyableprocess,becauseyourenvironmenthasalreadyundergonethenecessaryconfigurationcoveredinChapter5,DeployingaMobileApp.RecallthatthereisminimaldifferencesintheworkflowsofCordovaandCCAbecausetheyareusingthesameunderlyingtechnologyandswappingonlythebrowserfromtheAndroidbrowsertoGoogleChrome.
DeployingupdatestothelocalemulatorwithCordovaYourlocalemulatorsareaquick-and-dirtywaytotestsmalltomoderatechangestoyourhybridapplication.
1. Launchyourterminalorcommand-lineapplicationasfollows:
$cdpath/to/your/angular/app/mobile-app
$cordovabuild<platform>
$cordovaemulate<platform>
2. Launchtheapplication.3. Confirmthattheupdatewasasuccess.
TorecaptheCordovadeploymentworkflow,younavigatedtoyourlocallybuiltAngularJSapplication,builttheupdatednativeapplication,installeditwithinanemulator,bootedtheemulator,andensuredthattheupdatewassuccessful.
DeployingupdatestothephysicaldevicewithCordovaInstallingyourupdatedAngularhybridapplicationonthemetalisessentiallythesameprocessaswiththeemulator,excepttheonlydifferenceisuseoftheruncommandinsteadofthebuildandemulatecommands.
1. ConnectyourphysicaldevicetoyourdevelopmentworkstationviaUSB.2. EnableUSBDebugging.3. Launchyouterminalorcommand-lineapplicationasfollows:
$cdpath/to/your/angular/app/mobile-app
$cordovarun<platform>
4. Launchtheapplication.5. Confirmthattheupdatewasasuccess.
DeployingupdatestothelocalemulatorwithCCACCAenhancesyourhybridapplicationbyprovidingamorecapablerun-timeinGoogleChromeforyourAngularapp.
1. Launchyourterminalorcommand-lineapplicationasfollows:
$cdpath/to/your/angular/app/mobile-app
$ccabuild<platform>
$ccaemulate<platform>
2. Launchtheapplication.3. Confirmthattheupdatewasasuccess.
DeployingupdatestothephysicaldevicewithCCACCAcandeployyourmobilehybridAngularapptoyourphysicaldeviceforamorereal-worldtestenvironmentinmuchthesamewayasCordovadoes.
1. ConnectyourphysicaldevicetoyourdevelopmentworkstationviaUSB.2. EnableUSBDebugging.3. Launchyourterminalorcommand-lineapplicationasfollows:
$cdpath/to/your/angular/app/mobile-app
$ccarun<platform>
4. Launchtheapplication.5. Confirmthattheupdatewasasuccess.
BuildingupdateswithPhoneGapBuildPhoneGapBuildmakesbuildinganupdatedversionofyourAngularhybridappassimpleasclickingonabuttonanduploadingafile.It’saremarkablefeatwhencomparedtobuildingyourappforeachplatformmanually.
1. Zipupyourupdatedandbuiltapplication.2. Navigatetohttp://build.phonegap.com/.3. AuthenticatewithyourGitHubcredentials.4. SelecttheUpdateCodebuttonunderyourapplication.5. Uploadtheupdated.zipfilewhenprompted.6. WatchPhoneGapbuildingyourapplicationforeachplatform.7. InstalltheupdateonyourphysicaldevicewiththeprovidedQRcode.8. Confirmthattheupdatewasasuccess.
DeployingupdatestoGooglePlayStoreThefruitsofyourlaborarerealizedonceyoupublishyourupdatedapplicationtotheGooglePlayStoreorAppleAppStore,andthistooisassimpleasclickingonabuttonanduploadingafile.
1. AttainyourCordova,CCA,orPhoneGapbuilt.apkfileforyourupdatedAngularhybridapplication.
2. Navigatetohttps://play.google.com/apps/publish.3. AuthenticatewithyourGoogleAccount.
4. NavigatetotheAPKtab.5. SelecttheUploadnewAPKtoProductionbutton.6. Selectyourupdatedandbuilt.apkfileandupload.7. SelectthePublishbutton.8. Installtheupdateonyourphysicaldevicefromyourapplication’sPlayStorelisting.9. Confirmthattheupdatewasasuccess.
DeployingupdatestoChromeAppInChapter6,DeployingasChromeApps,youlearnedhowtoaugmentandpackageyourAngularapplicationasaChromeAppwiththehelpofyourlocalGoogleChromeinstance.Fromthischapter,youlearnedhowtodeployyourAngularChromeAppfromyourlocalChromeinstancetotheChromeWebStoreforconsumptionbymillions.
PackingupdateswithyourlocalChromeinstanceTopackageanupdatedversionofyourAngularChromeapp,repeatthePackExtensionprocessthatwecoveredinChapter6,DeployingasChromeApps,butwithyourupdatedapplication.
1. LaunchGoogleChrome.2. Navigatetochrome://extensions.3. SelecttheUpdateextensionsnowbuttontotheupper-rightoftheview.4. Launchanewtab.5. Navigatetochrome://apps.6. Launchyourupdatedapplication.7. Confirmthattheupdatewasasuccess.8. Navigatebacktochrome://extensions.9. ClickonthePackExtensionbutton.10. BrowsetotherootofyourAngularChromeapp.11. ClickonthePackExtensionbutton.
TorecaptheLocalChromepackingworkflow,younavigatedtoChrome’sExtensionsmanagementpage,installedtheupdateswithaclick,ensuredthattheupdatesareinorder,andpackedyourupdatedChromeappwithaclick.NowyouarefreetopublishtheupdatetotheChromeWebStore.
DeployingupdatestotheChromeWebStoreNowthatyou’vepackagedyourupdatedAngularChromeapp,it’stimetodelightyourusersbyshippingthemanupdatetotheChromeWebStore.Usersthatalreadyhaveyourappinstalledwillreceivetheupdateautomatically.#winning!
1. LocateyourupdatedandpackedAngularChromeapp.2. LaunchGoogleChrome.3. Navigatetohttps://chrome.google.com/webstore/developer/dashboard.4. AuthenticatewithyourGoogleaccount.5. LocateyourAngularChromeappundertheYourListingsheader.6. SelecttheEditlinkattheright-handsideofthelisting.7. SelecttheLoadUpdatedPackagebutton.8. BrowsetoyourpackedAngularChromeappandupload.9. Confirmthattheupdatewasasuccess.
SummaryMasteringyourtoolstackthroughoutallthephasesofyourdevelopmentworkflow,includingpostdeployment,isparamountinensuringyouruserscontinuetoengagewithyourapplication.Youarethecornerstoneinyourtoolstackresponsibleforholdingeverythingelsetogether.Withoutyourregularuse,developmentandupdatesofyourapplicationwillslowlydecay.Updatesofferameansofaddingmoreandmorevaluetoyourapplicationovertimeandprovideasenseofsafetyasyourcompetitorscontinuetoinnovate.Theonlywaytoprotectyourworkfrombeingdisruptedistocontinuedisruptingityourselfthroughdiligentinnovationandcraftsmanship.
Chapter8.Conclusion–AngularJSDeploymentEssentials “Madeit.”
—Quorra,TronLegacy
Weemployedanumberoftoolsthatenhanceyourdeveloperexperiencebyamplifyingyourworkflowstonewheights.WefurtherimprovedourtoolstackbyachievingsinglecommanddeploymentstoApache,Heroku,FirebaseHosting,asaCordovamobileapp,asaChromeCordovaApp,andasaChromePackagedApp.Initialdeploymentisonlyasgoodasyourpostdeploymentstrategy,whichiswhatyouattainedinthepreviouschapter.HarnessingthetoolswecoveredinthistextwillallowyoutodeployasingleAngularJSapplicationtonewplatformsandnewcustomers.Achievementunlocked!
DevelopingadynamictoolstackIsmileeverytimeIdeploycodewithasinglecommand.ThisfeelingisprettymuchhowImeasuremydeveloperexperiencewhenworkingwithanylayerofmytoolstack.ThisisthelevelIstroveforwhenconstructingthetoolstackandworkflowforeachoftheenvironmentswecovered.
Itisinevitablethatnew,moreradical,environmentswillgraceusinthefutureandthatiswhyyourtoolstack,ateverylayer,mustremaindynamic.MaintainawatchfuleyeonyourGitHubNewsFeedfornewtoolsthatimproveyourworkflows.Whenyoucomeacrossarepothatlooksinteresting,readtheREADMEfile,andtryitout.Thespeedoftrialanderrorwhentestingthesenewtoolsisremarkablyquick,makingiteasytoassesswhetherornotthey’llimproveyourcurrenttoolstackandworkflow.Whenyoufindthenewhotnessanditworksforyou,swapitinoraddittoyourstack.ThecommunitysupportonappssuchasGitHub,Bower,andNPMseemstospawnnewtoolsatanincreasingrate.
Yetanotherwaytofurtherenhanceyourworkflowsandtoolstacksistocreateyourowntools.DeveloperssuchasPavelFeldman,AddyOsmani,PaulIrish,ChrisCoyer,BryanFord,SindreSorhus,UmarHansa,RicardoCabello,JohnBarton,JanKeromnes,myself,andmanymore,allcontributedtothemodernwebdevelopmentworkflow.Inthesummerof2012,IhadthedistincthorrorofparticipatingintheGoogleSummerofCodeprogramwiththeEclipseOrioncommunity.IproposedanewimplementationoftheEclipseOrionweb-basedcodeeditorasaChromeDevToolsextensionthatletdevelopersedittheirclient-sidecode.Wecalledtheprojects,OrionX,anditisstillattractingdailyinstallationsfromtheChromeWebStore.Thebestpartoftheexperiencewasmymentor,aco-creatorofFireBugandmemberoftheChrometeam,JohnBarton.IlearnedalotfromJohn,andhisothersummerintern,Jan,aboutextendingChromeDevTools.Janbuiltanextensionsimilartomine,butinsteadusedtheCodeMirrorweb-basedcodeeditorforclient-sidecodeediting.TheneedandwantforthesetoolsbringsdeveloperssuchasJohn,Jan,andmyselftogetherintocommunitiesthatcontinuetoenhanceourworkflows.
Youshouldn’tfeellikeyouhavetocareforyourtoolsverymuch,beyondregularupdatesofcourse.Sometoolshaveatonofdependenciesandwhileusuallyawesome,itcangetfairlymessywhentheythrowerrorsandslowdownyourdevelopmentordeploymentworkflows.Ifthishappensandtheparticulartoolisnoteasilyreplaceable,youmightnothaveachoice,buttypicallyyou’llbeabletofindanothertoolthatprovidesoverlappingfunctionality.Onthedeploymentside,wecoveredafewwaystodeploytoApache,Heroku,andasaCordovaMobileapp.Knowingthatthese,atfirst,seeminglyredundanttoolsexistmightsaveyoualotoftimeorheadacheswhenresolvingafutureissue.Thisisanotherreasontoconstantlyimproveyourdynamictoolstackbytryingnewthings.Ifyougotasmidgetooambitiouswithyourcurrenttoolselectionandthingsstallinabadway,you’llhaveyourprevioustoolselectiontofallbackon.Also,ifyouditchedatoolforapreviouschoice,setareminderinamonthortwototrythetooloutagainorinvestigatetheissue,fixitandsubmitapullrequest.We’reallmovingatthespeedofwebandthe
DeployingearlyanddeployingThisbookisaproofthatAngularisflexibleenoughtorunamazinglywellinavarietyofenvironmentswithminimalchangesorconfiguration.Angular’sflexibilitytranslatesintoenvironmentalflexibility,affordingitselfmanyenvironmentsinwhichtorun.Yetanotherfacetofyourdeveloperexperienceisthisabilitytodeployyourapplicationinamultitudeofdifferentenvironments.Iarguethatalackofflexibilityinyourchosenframework(specificenvironmentaldependencies)isanegativedeveloperexperiencebecauseitlimitsyourdeploymentpossibilities.Whenchoosingbetweenframeworks,deploymentflexibilityshoulddefinitelybetakenintoconsideration.
Thankfully,youmadeasolidchoicebyleveragingAngular,butbeyondminimaltonoenvironmentaldependenciesyoushouldconsideryouroptionsforrapiddeployment.Rapid(orsinglecommand,asI’vecalledit)deploymentisahallmarkofanawesomedeveloperexperiencewhenmaintainingyourproductionapplications.Again,alackofabilitytorapidlydeployyourcodeisahallmarkofanegativedeveloperexperience.Ifyoucomeacrossanenvironmentthatyoulikeforotherreasonsandthereisnotalreadyatoolthatfacilitatessingle-commanddeployments,seeifyoucanbuildone.Ifyoudocreateanimproveddeveloperexperienceanditsrad,consideropensourcingittoyourcommunitytogainsomecoolpointswithothermembers.Neversettle;yourtoolscanalwaysimproveandsocanyourexperience.
IndexA
.apkfilesigning/Signingyour.apkfile
aboutviewabout/Theaboutview
accountviewabout/Theaccountview
add-ons,Heroku/Add-onsAnalytics.addTrans()method/Settinguptheangular-google-analyticsmoduleAnalyticsview
using/UsingtheAnalyticsviewAndroidSDK
installing/InstallingtheAndroidSDKURL/InstallingtheAndroidSDKconfiguring/ConfiguringtheAndroidSDKandtoolsOSXconfiguration/OSXconfigurationWindowsconfiguration/WindowsconfigurationAndroidtarget,installing/InstallinganAndroidtargetandcreatinganemulatoremulator,creating/InstallinganAndroidtargetandcreatinganemulator
AngularApache,configuringfor/ConfiguringApacheforAngular
angular-google-analyticsmoduleabout/AddingsupporttoGoogleAnalyticssettingup/Settinguptheangular-google-analyticsmoduleURL/Settinguptheangular-google-analyticsmodule
AngularAppaugmenting,forChrome/AugmentingyourAngularAppforChrome
AngularApp,augmentingforChromeabout/AugmentingyourAngularAppforChromemanifest.jsonfile/Themanifest.jsonfilebackground.jsfile/Thebackground.jsfileChromeinstance,deployingto/DeployingtoyourChromeinstancedeploymentissues,troubleshooting/TroubleshootingdeploymentissuesChromeWebStore,deploying/DeployingtotheChromeWebStore
AngularJSdeploymentfeature/Deployingearlyanddeploying
Angularwebapplicationmigrating,tohybridmobileappwithApacheCordova/FromAngularwebapplicationstohybridmobileappswithCordovamigrating,tohybridmobileappwithCordovaChromeapptoolchain/FromAngularwebapplicationstomobileappswiththeCordovaChromeApp
toolchainmigrating,tohybridmobileappwithPhoneGapBuild/FromAngularwebapplicationstomobileappswithPhoneGapBuild
Apacheconfiguring,forAngular/ConfiguringApacheforAngularPageSpeedService/Google’sPageSpeedServiceforApacheupdates,deploying/DeployingupdatestoApache
ApacheCordovaabout/WhatisApacheCordovaandhowdoesitaddressissues?used,foraddressingissues/WhatisApacheCordovaandhowdoesitaddressissues?developmentenvironment,configuring/ConfiguringyourdevelopmentenvironmentforApacheCordovadependencies/AwordonCordova’sdependenciesinstalling/InstallingApacheCordovaused,formigratingfromAngularwebapplicationtohybridmobileapp/FromAngularwebapplicationstohybridmobileappswithCordovaused,fordeployingapptophysicaldevice/DeployingyourapptoyourphysicaldevicewithCordova
appdeploying,toemulator/Deployingyourapptoanemulatorcode,movinginto/wwwfolder/Movingyourcodeinto/www
applicationpublishing/Publishingyourapplication.apkfile,signing/Signingyour.apkfilepublishing,toGooglePlayStore/PublishingtotheGooglePlayStore
applicationhostingfirebase-toolsCLI,using/Usingthefirebase-toolsCLI
CCCA
used,fordeployingupdatestolocalemulator/DeployingupdatestothelocalemulatorwithCCAused,fordeployingupdatestophysicaldevice/DeployingupdatestothephysicaldevicewithCCA
chatviewabout/Thechatview
ChromeAngularApp,augmentingfor/AugmentingyourAngularAppforChrome
ChromeAppneedfor/WhyChromeApps?besttype,selecting/ChoosingthebestapptypeURL/Choosingthebestapptypesetup/TheChromeAppsetuppolicy,URL/Contentsecuritypolicyupdates,deployingto/DeployingupdatestoChromeApp
ChromeAppsetupabout/TheChromeAppsetup
Chromeinstancedeployingto/DeployingtoyourChromeinstance
ChromeWebStoredeployingto/DeployingtotheChromeWebStoreURL/DeployingtotheChromeWebStoreupdates,deployingto/DeployingupdatestotheChromeWebStore
command-lineinterface(CLI)about/VersioncontrolwithGitandGitHub
/InstallingApacheCordova,Settinguptheangular-google-analyticsmoduleContentDeliveryNetwork(CDN)
about/HTTPresourcesservedoverHTTPSURL/HTTPresourcesservedoverHTTPS
ContentSecurityPolicy(CSP)/ContentsecuritypolicyCordova
used,fordeployingupdatestolocalemulator/DeployingupdatestothelocalemulatorwithCordovaused,fordeployingupdatestophysicaldevice/DeployingupdatestothephysicaldevicewithCordova
CordovaChromeApptoolchainused,formigratingfromAngularwebapplicationtomobileapp/FromAngularwebapplicationstomobileappswiththeCordovaChromeApptoolchaindevelopmentenvironment,configuring/ConfiguringyourdevelopmentenvironmentfortheCordovaChromeApptoolchainused,forpackagingAngularwebapplicationformobile/Packagingyour
DDataview
using/UsingtheDataviewdeployment,withGitHub
automating/AutomatingdeploymentwithGitHubandSSHdeployment,withSSH
automating/AutomatingdeploymentwithGitHubandSSHdeploymentdestination
about/Deploymentdestinationdeploymentissues
troubleshooting/Troubleshootingdeploymentissues,Troubleshootingdeploymentissuesvisualdifftool/Avisualdifftoolvisualdifftool,usingwithGit/UsingdiffwithGit
deploymentissues,ChromeApptroubleshooting/Troubleshootingdeploymentissues
deploymentissues,Firebasetroubleshooting/TroubleshootingdeploymentissuesHTTPresourcesserved,overHTTPS/HTTPresourcesservedoverHTTPS
deploymentissues,Herokutroubleshooting/Troubleshootingdeploymentissues
developmentenvironment,forApacheCordovaconfiguring/ConfiguringyourdevelopmentenvironmentforApacheCordova
developmentenvironment,forCordovaChromeApptoolchainconfiguring/ConfiguringyourdevelopmentenvironmentfortheCordovaChromeApptoolchain
dynamictoolstackdeveloping/Developingadynamictoolstack
dynosabout/Dynosfeatures/Dynosscalability/Scalability
EEclipseAndroidDeveloperTools(ADT)
about/InstallingtheAndroidSDKoptions/InstallingtheAndroidSDK
EditorIntegrationandSublimeText/SublimeTextandEditorintegration
emulatorapp,deployingto/Deployingyourapptoanemulatorapp,deployingtophysicaldevice/DeployingyourapptoyourphysicaldevicewithCordova
Expressabout/ExpressURL/Express
express()method/Web.js
Ffeaturescategory/FeaturesandfixesFileTransferProtocol(FTP)/ManualdeploymentFirebase
URL/TheFirebasesetupsetup/TheFirebasesetup
firebase-toolsCLIusing/Usingthefirebase-toolsCLIFirebaseenvironment,configuring/ConfiguringyourFirebaseenvironment
FirebaseaccountURL/CreatingyourFirebaseaccountcreating/CreatingyourFirebaseaccount
FirebaseForgedashboardusing/UsingtheFirebaseForgedashboardDataview,using/UsingtheDataviewSecurityRulesview,using/UsingtheSecurityRulesviewSimulatorview,using/UsingtheSimulatorviewAnalyticsview,using/UsingtheAnalyticsviewSimpleLoginview,using/UsingtheSimpleLoginview
FirebaseHostingupdates,deploying/DeployingupdatestoFirebaseHosting
Firebasesetupabout/TheFirebasesetupaccount,creating/CreatingyourFirebaseaccountForgedashboard,using/UsingtheFirebaseForgedashboardapplication,hosting/Hostingyourapplication
fixescategory/FeaturesandfixesForeman/TheProcfileFTP
initiating,fromcommandline/FTPingfromyourcommandlineFTPclient/AnFTPclientFTPclients/FTPclients
GGit
URL/VersioncontrolwithGitandGitHubGoogleAnalytics
support,adding/AddingsupporttoGoogleAnalyticsangular-google-analyticsmodule,settingup/Settinguptheangular-google-analyticsmoduleupdates,deployingtoApache/DeployingupdatestoApacheupdates,deployingtoHeroku/DeployingupdatestoHerokuupdates,deployingtoFirebaseHosting/DeployingupdatestoFirebaseHostingupdates,deployingtomobileapp/Deployingupdatestomobileappsupdates,deployingtoChromeApp/DeployingupdatestoChromeApp
GoogleChromeURL/TheChromeAppsetup,DeployingupdatestotheChromeWebStore
GooglePageSpeedURL/Google’sPageSpeedServiceforApache
GooglePlayDeveloperConsoleURL/PublishingtotheGooglePlayStore
GooglePlayStoreapplication,publishingto/PublishingtotheGooglePlayStoreupdates,deployingto/DeployingupdatestoGooglePlayStore
Grunt/GruntGzippo/Gzippo
HHeroku
environment,settingup/SettingupyourHerokuenvironmentURL/Creatinganaccountdeploying/ScalinganddeployingtoHerokuadd-ons/Add-onsdeploymentissues,troubleshooting/Troubleshootingdeploymentissuesupdates,deploying/DeployingupdatestoHeroku
Herokuenvironmentsettingup/SettingupyourHerokuenvironmentaccount,creating/CreatinganaccountHeroku’sDashboard/Heroku’sdashboardnewapplication,defining/DefininganewapplicationHerokuToolbelt/TheHerokuToolbeltpre-deploymentconfiguration/Predeploymentconfiguration
HerokuToolbeltabout/TheHerokuToolbeltopensourceprojects/TheHerokuToolbeltfacilitates/TheHerokuToolbeltURL/Installationinstalling/InstallationSSHaccess/SSHaccessnewapp/NewappinToolbeltnewapp,indashboard/NewappindashboardHerokubranch/Herokubranch
Heroku’sDashboardabout/Heroku’sdashboard
Kkrakn
about/KraknGit,settingup/SettingupGitandGitHubGitHub,settingup/SettingupGitandGitHubapp,scaffoldingwithYo/ScaffoldingtheappwithYodevelopment/Developmentviews/Views,controllers,androutescontrollers/Views,controllers,androutesroutes/Views,controllers,androutesglobalcontrollerconstants/Globalcontrollerconstantsmodels/Modelsandservicesservices/Modelsandservices
kraknapplication/WhyChromeApps?
LlocalChromeinstance
used,forpackingupdates/PackingupdateswithyourlocalChromeinstanceLocalMasterBranch/Herokubranchlocalsetup
versusremotesetup/Acomparisonbetweenthelocalandremotesetuploginview
about/Theloginview
M/menuview
about/Themenuviewmanifest.jsonfile
about/Themanifest.jsonfileicons/IconsContentSecurityPolicy(CSP)/Contentsecuritypolicycustomizing,ways/Otherwaystocustomizeyourmanifest.jsonfileavailablekeys,URL/Otherwaystocustomizeyourmanifest.jsonfile
manualdeploymentabout/ManualdeploymentFTPing,fromcommandline/FTPingfromyourcommandlineFTPclients/FTPclients
Meldabout/AvisualdifftoolURL/Avisualdifftool
mobile-chrome-appsURL/FromAngularwebapplicationstomobileappswiththeCordovaChromeApptoolchain,PackagingyourAngularwebapplicationformobilewithCCA
mobileappupdates,deploying/Deployingupdatestomobileapps
Nng-showattribute/ThemenuviewNode.js
about/Node.jsNPM/NPM
NodeVersionManager(NVM)/ConfiguringyourdevelopmentenvironmentfortheCordovaChromeApptoolchainNPM/NPM
PPackage.json
about/Package.jsonURL/Package.json
PageSpeedService,forApache/Google’sPageSpeedServiceforApachePhoneGapBuild
used,formigratingfromAngularwebapplicationtomobileapp/FromAngularwebapplicationstomobileappswithPhoneGapBuildURL/FromAngularwebapplicationstomobileappswithPhoneGapBuild
PhoneGapBuildused,forbuildingupdates/BuildingupdateswithPhoneGapBuildURL/BuildingupdateswithPhoneGapBuild
pre-deploymentconfiguration,HerokuenvironmentExpress/ExpressGzippo/GzippoPackage.json/Package.jsonProcfile/TheProcfileWeb.js/Web.js
predeployment,Yeomanabout/Predeployment
Procfileabout/TheHerokuToolbelt,TheProcfile
RRemoteHerokuBranch/HerokubranchRemoteMasterBranch/Herokubranchremotesetup
versuslocalsetup/Acomparisonbetweenthelocalandremotesetup
SSecurityRulesview
using/UsingtheSecurityRulesviewSimpleLoginview
using/UsingtheSimpleLoginviewSimulatorview
using/UsingtheSimulatorviewSinglePageApplication(SPA)/AddingsupporttoGoogleAnalyticssourcecode
deployingfromlocal,toremote/FromlocaltoremoteSublimeText
andEditorIntegration/SublimeTextandEditorintegration
Uupdates
deploying,toApache/DeployingupdatestoApachedeploying,toHeroku/DeployingupdatestoHerokudeploying,toFirebaseHosting/DeployingupdatestoFirebaseHostingdeploying,tomobileapp/Deployingupdatestomobileappsdeploying,tolocalemulatorwithCordova/DeployingupdatestothelocalemulatorwithCordova,DeployingupdatestothephysicaldevicewithCordovadeploying,tolocalemulatorwithCCA/DeployingupdatestothelocalemulatorwithCCAdeploying,tophysicaldevicewithCCA/DeployingupdatestothephysicaldevicewithCCAbuilding,withPhoneGapBuild/BuildingupdateswithPhoneGapBuilddeploying,toGooglePlayStore/DeployingupdatestoGooglePlayStoredeploying,toChromeApp/DeployingupdatestoChromeApppacking,withlocalChromeinstance/PackingupdateswithyourlocalChromeinstancedeploying,toChromeWebStore/DeployingupdatestotheChromeWebStore
updates,deployingtoApacheabout/DeployingupdatestoApacheFTPcommand-lineinterface/TheFTPcommand-lineinterfaceFTPclient/AnFTPclientSSH/GitandSSHGit/GitandSSH
Vversioncontrol
withGit/VersioncontrolwithGitandGitHubwithGitHub/VersioncontrolwithGitandGitHub
VirtualPrivateServer(VPS)/Heroku’sdashboardvisualdifftool
about/Avisualdifftoolusing,withGit/UsingdiffwithGit
WWeb.js
about/Web.jswebapplications
tools/Therighttoolsforthejobworkflow,Yeoman
about/Yeoman’sworkflowYo/YoGrunt/GruntBower/Bower
top related