angularjs deployment essentials -...

247
www.allitebooks.com

Upload: ngomien

Post on 13-Feb-2018

230 views

Category:

Documents


0 download

TRANSCRIPT

www.allitebooks.com

www.allitebooks.com

AngularJSDeploymentEssentials

www.allitebooks.com

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

www.allitebooks.com

AngularJSDeploymentEssentials

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

ProductionCoordinator

NileshR.Mohite

CoverWork

NileshR.Mohite

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.

www.PacktPub.com

Supportfiles,eBooks,discountoffers,andmoreForsupportfilesanddownloadsrelatedtoyourbook,pleasevisitwww.PacktPub.com.

DidyouknowthatPacktofferseBookversionsofeverybookpublished,withPDFandePubfilesavailable?YoucanupgradetotheeBookversionatwww.PacktPub.comandasaprintbookcustomer,youareentitledtoadiscountontheeBookcopy.Getintouchwithusat<[email protected]>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.

www.allitebooks.com

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<[email protected]>,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<[email protected]>withalinktothesuspectedpiratedmaterial.

Weappreciateyourhelpinprotectingourauthorsandourabilitytobringyouvaluablecontent.

QuestionsIfyouhaveaproblemwithanyaspectofthisbook,youcancontactusat<[email protected]>,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:

[email protected]:[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="[email protected]"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"[email protected]"

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:[email protected]

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:[email protected]

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

toolwilllikelyhaveimproved.

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

Bbackground.jsfile/Thebackground.jsfileBatarang

about/BatarangBower/Bower

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

AngularwebapplicationformobilewithCCA

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

IIonicframework

about/TheIonicframeworkiPhone

about/Contextistheking

JJavaScriptObjectNotation(JSON)/UsingtheDataview

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

OOpenAuthentication(OAuth)

about/UsingtheSimpleLoginviewURL/UsingtheSimpleLoginview

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

XXcode

URL/ConfiguringyourdevelopmentenvironmentforApacheCordovaabout/AwordonCordova’sdependencies

YYeoman

about/Yeoman’sworkflowYo

about/Yoinstalling/InstallingYo